JComboBox 确定项目在下拉列表中是否可见

发布于 2024-11-05 15:17:11 字数 2715 浏览 2 评论 0 原文

我试图确定每个项目在 JComboBox 下拉列表的 JViewPort 中是否可见

(我的星期五加班)

编辑:我不想实现 MouseListener 以将事件重复到 System.out.print(...)

不可能通过使用 SwingUtilities http://download.oracle.com/javase/6/docs/api/javax/swing/SwingUtilities.html ,但是这个 APi 超出了我的...

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ItemVisibleRecCombo extends JFrame {

    private static final long serialVersionUID = 1L;
    private JComboBox fontsBox;

    public ItemVisibleRecCombo() {
        String[] numbers = {"one", "two", "three", "four", "five", "six", "seven"};
        fontsBox = new JComboBox(numbers);
        fontsBox.setSelectedItem(0);
        fontsBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    manItemInCombo();
                }
            }
        });
        fontsBox.setModel(new DefaultComboBoxModel(numbers));
        fontsBox.setMaximumRowCount(3);
        add(fontsBox, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(400, 60));
        setLocation(200, 105);
        pack();
        setVisible(true);
    }

    private void manItemInCombo() {
        if (fontsBox.getItemCount() > 0) {
            final Object comp = fontsBox.getUI().getAccessibleChild(fontsBox, 0);
            if ((comp instanceof JPopupMenu)) {
                final JList list = new JList(fontsBox.getModel());
                final JPopupMenu popup = (JPopupMenu) comp;
                final JScrollPane scrollPane = (JScrollPane) popup.getComponent(0);
                final JViewport viewport = scrollPane.getViewport();
                final Rectangle rect = popup.getVisibleRect();
                Point pt = viewport.getViewPosition();
                for (int i = 0; i < list.getModel().getSize(); i++) {
                    pt = list.indexToLocation(i);
                    System.out.print(pt + " - ");
                    rect.setLocation(rect.x - pt.x, rect.y - pt.y);
                    System.out.println(new Rectangle(viewport.getExtentSize()).contains(rect));
                }
            }
        }
    }

    public static void main(String arg[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ItemVisibleRecCombo ivrc = new ItemVisibleRecCombo();
            }
        });
    }
}

I tried to determime for every Items if are or not visible in the JViewPort from JComboBox drop-down list

(my Friday OT)

EDIT: I don't want to implements MouseListener for Repeats events to System.out.print(...)

isn't possible pass JComboBox with JList, declared by JCombo#Model by using SwingUtilities http://download.oracle.com/javase/6/docs/api/javax/swing/SwingUtilities.html , but this APi is out of my...

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ItemVisibleRecCombo extends JFrame {

    private static final long serialVersionUID = 1L;
    private JComboBox fontsBox;

    public ItemVisibleRecCombo() {
        String[] numbers = {"one", "two", "three", "four", "five", "six", "seven"};
        fontsBox = new JComboBox(numbers);
        fontsBox.setSelectedItem(0);
        fontsBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    manItemInCombo();
                }
            }
        });
        fontsBox.setModel(new DefaultComboBoxModel(numbers));
        fontsBox.setMaximumRowCount(3);
        add(fontsBox, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(400, 60));
        setLocation(200, 105);
        pack();
        setVisible(true);
    }

    private void manItemInCombo() {
        if (fontsBox.getItemCount() > 0) {
            final Object comp = fontsBox.getUI().getAccessibleChild(fontsBox, 0);
            if ((comp instanceof JPopupMenu)) {
                final JList list = new JList(fontsBox.getModel());
                final JPopupMenu popup = (JPopupMenu) comp;
                final JScrollPane scrollPane = (JScrollPane) popup.getComponent(0);
                final JViewport viewport = scrollPane.getViewport();
                final Rectangle rect = popup.getVisibleRect();
                Point pt = viewport.getViewPosition();
                for (int i = 0; i < list.getModel().getSize(); i++) {
                    pt = list.indexToLocation(i);
                    System.out.print(pt + " - ");
                    rect.setLocation(rect.x - pt.x, rect.y - pt.y);
                    System.out.println(new Rectangle(viewport.getExtentSize()).contains(rect));
                }
            }
        }
    }

    public static void main(String arg[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ItemVisibleRecCombo ivrc = new ItemVisibleRecCombo();
            }
        });
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我乃一代侩神 2024-11-12 15:17:11

基本上,您正在寻找 list.locationToIndex (如果我理解正确的话),类似于

    Accessible a = fontsBox.getUI().getAccessibleChild(fontsBox, 0);
    if (a instanceof javax.swing.plaf.basic.ComboPopup) {
        JList list = ((javax.swing.plaf.basic.ComboPopup)a).getList();
        Rectangle rect = list.getVisibleRect();
        int first = list.locationToIndex(rect.getLocation());
        // similar for last, at the lower edge of the visible rect, left as exercise <g>
        // Edit: as of @Boro's comment, last is easier calculated with maxRowCount
        int last = first + fontsBox.getMaximumRowCount() - 1;
        ....

顺便说一句,还有另一个未传递到列表的属性:本应

   list.getVisibleRowCount() == combo.getMaximumRowCount()   

回答这个问题:第一个/最后一个之间的所有项目(包含在内),是可见的,第一个上方和最后一个下方的所有项目都不可见;-)

Basically, you'r looking for list.locationToIndex (if I understood you correctly), something like

    Accessible a = fontsBox.getUI().getAccessibleChild(fontsBox, 0);
    if (a instanceof javax.swing.plaf.basic.ComboPopup) {
        JList list = ((javax.swing.plaf.basic.ComboPopup)a).getList();
        Rectangle rect = list.getVisibleRect();
        int first = list.locationToIndex(rect.getLocation());
        // similar for last, at the lower edge of the visible rect, left as exercise <g>
        // Edit: as of @Boro's comment, last is easier calculated with maxRowCount
        int last = first + fontsBox.getMaximumRowCount() - 1;
        ....

BTW, yet another property that's not passed on to the list: would have expected

   list.getVisibleRowCount() == combo.getMaximumRowCount()   

To answer the question: all items between first/last, inclusively, are visible, all items above first and below last not visible ;-)

无边思念无边月 2024-11-12 15:17:11

如果它涉及获取组合框中可见的元素,我这里有一个算法,您可以使用

                Point pt = viewport.getViewPosition();
                int rowCount = fontsBox.getMaximumRowCount();
                int rowsize = viewport.getSize().height / rowCount;
                System.out.println("viewport.getHeight()="+ viewport.getHeight()
                        +"; viewport.getViewSize().getHeight()="+ viewport.getViewSize().getHeight()
                        +"; rowsize=" + rowsize+"; pt="+pt);                
                int firstVisibleElementIndex = pt.y/rowsize;
                int lastVisibleElementIndex = firstVisibleElementIndex + (rowCount-1);
                System.out.println("firstVisibleElementIndex="+ firstVisibleElementIndex
                        +"; lastVisibleElementIndex="+lastVisibleElementIndex);

它检查它会返回您的第一个和最后一个可见元素,然后由您决定如何处理它们。

编辑:这只是一个基于给定示例构建的快速(且令人讨厌)的解决方案。如需更好的解决方案,请参阅@kleopatra 的解决方案。

If it goes about getting the elements which are visible in the your combobox I have an algorithm here which you could use

                Point pt = viewport.getViewPosition();
                int rowCount = fontsBox.getMaximumRowCount();
                int rowsize = viewport.getSize().height / rowCount;
                System.out.println("viewport.getHeight()="+ viewport.getHeight()
                        +"; viewport.getViewSize().getHeight()="+ viewport.getViewSize().getHeight()
                        +"; rowsize=" + rowsize+"; pt="+pt);                
                int firstVisibleElementIndex = pt.y/rowsize;
                int lastVisibleElementIndex = firstVisibleElementIndex + (rowCount-1);
                System.out.println("firstVisibleElementIndex="+ firstVisibleElementIndex
                        +"; lastVisibleElementIndex="+lastVisibleElementIndex);

Check it out it returns you first and last visible element then it is up to you what you want to to with them.

EDIT: This is just a quick (& nasty) solution build on top of the given example. For a better solution please see @kleopatra 's solution.

や莫失莫忘 2024-11-12 15:17:11

将监听器从 ItemListener 更改为 ActionListener 似乎给出了预期的结果,无论是对于箭头键还是单击:

fontsBox.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
         manItemInCombo();
    }
});

Changing the listener from ItemListener to ActionListener seems to give the expected results, both for arrow keys and clicking:

fontsBox.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
         manItemInCombo();
    }
});
攒眉千度 2024-11-12 15:17:11

谢谢你,但你的假设不正确,这里是输出,我仍然无法测试 ViewPort 是否包含 Item 或不正确,没办法,我必须返回到我的原始声明,因为它正确显示第一个可见 Item phaaaa

编辑谢谢@ Anthony Accioly 以获得正确的建议 将侦听器从 ItemListener 更改为 ActionListener

ItemListener 的错误输出

1stIndex = 0, LastIndex = 2, SelectedItem1 = two, Value = one, two, three//ok
1stIndex = 0, LastIndex = 2, SelectedItem1 = three, Value = one, two, three//ok
1stIndex = 0, LastIndex = 2, SelectedItem1 = four, Value = one, two, three//wrong
1stIndex = 1, LastIndex = 3, SelectedItem1 = five, Value = two, three, four//wrong
1stIndex = 2, LastIndex = 4, SelectedItem1 = six, Value = three, four, five//wrong
1stIndex = 3, LastIndex = 5, SelectedItem1 = seven, Value = four, five, six//wrong
1stIndex = 4, LastIndex = 6, SelectedItem1 = six, Value = five, six, seven//ok
1stIndex = 4, LastIndex = 6, SelectedItem1 = five, Value = five, six, seven//ok
1stIndex = 4, LastIndex = 6, SelectedItem1 = four, Value = five, six, seven//wrong
1stIndex = 3, LastIndex = 5, SelectedItem1 = three, Value = four, five, six//wrong
1stIndex = 2, LastIndex = 4, SelectedItem1 = two, Value = three, four, five//wrong
1stIndex = 1, LastIndex = 3, SelectedItem1 = one, Value = two, three, four//wrong

ActionListener 的预期输出

1stIndex = 0, LastIndex = 2, SelectedItem1 = two, Value = one, two, three
1stIndex = 0, LastIndex = 2, SelectedItem1 = three, Value = one, two, three
1stIndex = 1, LastIndex = 3, SelectedItem1 = four, Value = two, three, four
1stIndex = 2, LastIndex = 4, SelectedItem1 = five, Value = three, four, five
1stIndex = 3, LastIndex = 5, SelectedItem1 = six, Value = four, five, six
1stIndex = 4, LastIndex = 6, SelectedItem1 = seven, Value = five, six, seven
1stIndex = 4, LastIndex = 6, SelectedItem1 = six, Value = five, six, seven
1stIndex = 4, LastIndex = 6, SelectedItem1 = five, Value = five, six, seven
1stIndex = 3, LastIndex = 5, SelectedItem1 = four, Value = four, five, six
1stIndex = 2, LastIndex = 4, SelectedItem1 = three, Value = three, four, five
1stIndex = 1, LastIndex = 3, SelectedItem1 = two, Value = two, three, four
1stIndex = 0, LastIndex = 2, SelectedItem1 = one, Value = one, two, three

编辑后的代码

import java.awt.*;
import java.awt.event.*;
import javax.accessibility.Accessible;
import javax.swing.*;

public class ItemVisibleRecCombo extends JFrame {

    private static final long serialVersionUID = 1L;
    private JComboBox fontsBox;

    public ItemVisibleRecCombo() {
        String[] numbers = {"one", "two", "three", "four", "five", "six", "seven"};
        fontsBox = new JComboBox(numbers);
        fontsBox.setSelectedItem(0);
        /*fontsBox.addItemListener(new ItemListener() {

        @Override
        public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
        manItemInCombo();
        }
        }
        });*/
        fontsBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                manItemInCombo();
            }
        });
        fontsBox.setModel(new DefaultComboBoxModel(numbers));
        fontsBox.setMaximumRowCount(3);
        add(fontsBox, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(400, 60));
        setLocation(200, 105);
        pack();
        setVisible(true);
    }

    private void manItemInCombo() {
        if (fontsBox.getItemCount() > 0) {
            final Accessible a = fontsBox.getUI().getAccessibleChild(fontsBox, 0);
            if (a instanceof javax.swing.plaf.basic.ComboPopup) {
                final JList list = ((javax.swing.plaf.basic.ComboPopup) a).getList();
                final Rectangle rect = list.getVisibleRect();
                final int first = list.locationToIndex(rect.getLocation());
                final int last = first + fontsBox.getMaximumRowCount() - 1;
                String selectedItem = fontsBox.getSelectedItem().toString();
                System.out.println("1stIndex = " + first + ", LastIndex = "
                        + last + ", SelectedItem1 = " + selectedItem
                        + ", Value = " + fontsBox.getItemAt(first).toString()
                        + ", " + fontsBox.getItemAt(first + 1).toString()
                        + ", " + fontsBox.getItemAt(first + 2).toString());
            }
        }
    }

    public static void main(String arg[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ItemVisibleRecCombo ivrc = new ItemVisibleRecCombo();
            }
        });
    }
}

thank you, but your assumptions weren't correct, here is output, still I can't test if ViewPort contains Item or not correctly, no way, I must return to my original declaration, because that show first visible Item correctly phaaaa

EDIT thanks @ Anthony Accioly for correct sugestion Changing the listener from ItemListener to ActionListener

wrong outPut from ItemListener

1stIndex = 0, LastIndex = 2, SelectedItem1 = two, Value = one, two, three//ok
1stIndex = 0, LastIndex = 2, SelectedItem1 = three, Value = one, two, three//ok
1stIndex = 0, LastIndex = 2, SelectedItem1 = four, Value = one, two, three//wrong
1stIndex = 1, LastIndex = 3, SelectedItem1 = five, Value = two, three, four//wrong
1stIndex = 2, LastIndex = 4, SelectedItem1 = six, Value = three, four, five//wrong
1stIndex = 3, LastIndex = 5, SelectedItem1 = seven, Value = four, five, six//wrong
1stIndex = 4, LastIndex = 6, SelectedItem1 = six, Value = five, six, seven//ok
1stIndex = 4, LastIndex = 6, SelectedItem1 = five, Value = five, six, seven//ok
1stIndex = 4, LastIndex = 6, SelectedItem1 = four, Value = five, six, seven//wrong
1stIndex = 3, LastIndex = 5, SelectedItem1 = three, Value = four, five, six//wrong
1stIndex = 2, LastIndex = 4, SelectedItem1 = two, Value = three, four, five//wrong
1stIndex = 1, LastIndex = 3, SelectedItem1 = one, Value = two, three, four//wrong

and expected output from ActionListener

1stIndex = 0, LastIndex = 2, SelectedItem1 = two, Value = one, two, three
1stIndex = 0, LastIndex = 2, SelectedItem1 = three, Value = one, two, three
1stIndex = 1, LastIndex = 3, SelectedItem1 = four, Value = two, three, four
1stIndex = 2, LastIndex = 4, SelectedItem1 = five, Value = three, four, five
1stIndex = 3, LastIndex = 5, SelectedItem1 = six, Value = four, five, six
1stIndex = 4, LastIndex = 6, SelectedItem1 = seven, Value = five, six, seven
1stIndex = 4, LastIndex = 6, SelectedItem1 = six, Value = five, six, seven
1stIndex = 4, LastIndex = 6, SelectedItem1 = five, Value = five, six, seven
1stIndex = 3, LastIndex = 5, SelectedItem1 = four, Value = four, five, six
1stIndex = 2, LastIndex = 4, SelectedItem1 = three, Value = three, four, five
1stIndex = 1, LastIndex = 3, SelectedItem1 = two, Value = two, three, four
1stIndex = 0, LastIndex = 2, SelectedItem1 = one, Value = one, two, three

Edited code

import java.awt.*;
import java.awt.event.*;
import javax.accessibility.Accessible;
import javax.swing.*;

public class ItemVisibleRecCombo extends JFrame {

    private static final long serialVersionUID = 1L;
    private JComboBox fontsBox;

    public ItemVisibleRecCombo() {
        String[] numbers = {"one", "two", "three", "four", "five", "six", "seven"};
        fontsBox = new JComboBox(numbers);
        fontsBox.setSelectedItem(0);
        /*fontsBox.addItemListener(new ItemListener() {

        @Override
        public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
        manItemInCombo();
        }
        }
        });*/
        fontsBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                manItemInCombo();
            }
        });
        fontsBox.setModel(new DefaultComboBoxModel(numbers));
        fontsBox.setMaximumRowCount(3);
        add(fontsBox, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(400, 60));
        setLocation(200, 105);
        pack();
        setVisible(true);
    }

    private void manItemInCombo() {
        if (fontsBox.getItemCount() > 0) {
            final Accessible a = fontsBox.getUI().getAccessibleChild(fontsBox, 0);
            if (a instanceof javax.swing.plaf.basic.ComboPopup) {
                final JList list = ((javax.swing.plaf.basic.ComboPopup) a).getList();
                final Rectangle rect = list.getVisibleRect();
                final int first = list.locationToIndex(rect.getLocation());
                final int last = first + fontsBox.getMaximumRowCount() - 1;
                String selectedItem = fontsBox.getSelectedItem().toString();
                System.out.println("1stIndex = " + first + ", LastIndex = "
                        + last + ", SelectedItem1 = " + selectedItem
                        + ", Value = " + fontsBox.getItemAt(first).toString()
                        + ", " + fontsBox.getItemAt(first + 1).toString()
                        + ", " + fontsBox.getItemAt(first + 2).toString());
            }
        }
    }

    public static void main(String arg[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ItemVisibleRecCombo ivrc = new ItemVisibleRecCombo();
            }
        });
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文