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

我试图从JComboBox下拉列表中的JViewPort中查看每个项目是否可见

(我星期五加油)

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

是不可能通过JList传递JComboBox,由JCombo#Model使用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(); } }); } } 

基本上,你正在寻找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  // Edit: as of @Boro's comment, last is easier calculated with maxRowCount int last = first + fontsBox.getMaximumRowCount() - 1; .... 

顺便说一句,还有另一个没有传递给名单的财产:本来可以预料到的

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

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

如果要获得combobox中可见的元素,我可以使用一个算法

  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的解决方案。

将侦听器从ItemListener更改为ActionListener似乎为箭头键和单击提供了预期的结果:

 fontsBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { manItemInCombo(); } }); 

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

编辑感谢@ Anthony Accioly正确Changing the listener from ItemListener to ActionListener

ItemListener错误的outPut

 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(); } }); } }