Java 从JComboBox弹出窗口获取当前突出显示的项目(非选定项目)

Java 从JComboBox弹出窗口获取当前突出显示的项目(非选定项目),java,swing,selection,jcombobox,highlight,Java,Swing,Selection,Jcombobox,Highlight,我希望能够在JComboBox下拉列表中当前突出显示的项发生更改时做出反应。请注意,我不是在寻找一种方法来获取当前选定的项目,而是突出显示的项目。当鼠标悬停在此弹出窗口上时,它会突出显示鼠标位置的项目,但这不会影响当前选定的项目,因此我无法简单地通过itemstener或ActionListener来实现我想要的 我试图创建一个组件,它由一个JComboBox和一个耦合的工具提示组成,该工具提示显示当前高亮显示项的附加信息(文档) 作为第一次尝试,我将向构造函数添加一些代码(扩展的JComboB

我希望能够在
JComboBox
下拉列表中当前突出显示的项发生更改时做出反应。请注意,我不是在寻找一种方法来获取当前选定的项目,而是突出显示的项目。当鼠标悬停在此弹出窗口上时,它会突出显示鼠标位置的项目,但这不会影响当前选定的项目,因此我无法简单地通过
itemstener
ActionListener
来实现我想要的

我试图创建一个组件,它由一个
JComboBox
和一个耦合的工具提示组成,该工具提示显示当前高亮显示项的附加信息(文档)

作为第一次尝试,我将向构造函数添加一些代码(扩展的
JComboBox
):

导入java.awt.BorderLayout;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入javax.accessibility.AccessibleContext;
导入javax.accessibility.AccessibleState;
导入javax.swing.DefaultComboxModel;
导入javax.swing.JComboBox;
导入javax.swing.JFrame;
导入javax.swing.JList;
导入javax.swing.SwingUtilities;
导入javax.swing.plaf.basic.ComboPopup;
公共类SomeFrame扩展了JFrame{
私有MyComboBox组合;
公共框架(){
setDefaultCloseOperation(在关闭时处理);
设置大小(100,20);
setLocationRelativeTo(空);
setLayout(新的BorderLayout());
combo=newmycombobox();
setModel(新的DefaultComboxModel(新字符串[]{“一”、“二”、“三”、“四”});
添加(组合);
包装();
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
SomeFrame=新的SomeFrame();
frame.setVisible(true);
}
});
}    
//这是重要的部分
私有静态类MyComboBox扩展了JComboBox{
公共邮箱(){
getAccessibleContext().addPropertyChangeListener(新的PropertyChangeListener()){
公共作废属性更改(属性更改事件evt){
if(AccessibleContext.ACCESSIBLE\u STATE\u PROPERTY.equals(evt.getPropertyName())
&&AccessibleState.FOCUSED.equals(evt.getNewValue())
&&getAccessibleContext(){
ComboPopup=(ComboPopup)getAccessibleContext().getAccessibleChild(0);
JList list=popup.getList();
System.out.println(“-->”+String.valueOf(list.getSelectedValue());
}
}
});
}
}
}
这似乎是可行的,但我通过一些阴暗的渠道和尝试/错误获得了这段代码,所以我认为必须有更好的方法来实现这一点。有什么想法吗?以上代码是否安全生产

我试图创建一个组件,它由一个JComboBox和一个耦合的工具提示组成

为组合框创建自定义渲染器。然后在渲染器中使用setToolTipText(…)方法


JTable教程的这一部分介绍了如何对表执行此操作。组合框渲染器的概念应该是相同的。

好问题和好解决方案-除了accessibleCombo中似乎存在缺陷,它不会在updateUI上更新其内部接线,即在切换LAF时:

  • 列表的可访问选择更改由注册到comboPopup列表的内部ListSelectionListener触发
  • comboPopup由ui委托控制,并在installUI中重新创建
  • accessibleCombo不会将其内部列表更新为新创建和安装的
你对此无能为力。因此,我将直接听取列表选择,然后您可以完全控制LAF更改的重新布线:

public static class XComboBox extends JComboBox {

    private ListSelectionListener listener;

    public XComboBox() {
        uninstall();
        install();
    }

    @Override
    public void updateUI() {
        uninstall();
        super.updateUI();
        install();
    }

    private void uninstall() {
        if (listener == null) return;
        getPopupList().removeListSelectionListener(listener);
        listener = null;
    }

    protected void install() {
        listener = new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) return;

                JList list = getPopupList();
                System.out.println("--> " + String.valueOf(list.getSelectedValue()));
            }
        };
        getPopupList().addListSelectionListener(listener);
    }

    private JList getPopupList() {
        ComboPopup popup = (ComboPopup) getUI().getAccessibleChild(this, 0);
        return popup.getList();

    }
}

如果我没有弄错的话,这将不允许我以我喜欢的方式定位工具提示。但这比我现在做的要好得多。我要试一试。谢谢你的建议。我根本没有意识到这个错误。大多数时候,我倾向于远离任何与LAF相关的东西。如果我不能提交自定义渲染器解决方案,我也会尝试这个方法。谢谢。我最终还是按照凯洛帕特拉的建议去了。我的问题可能有点误导,因为我提到了工具提示,但忘了提到将来可能会切换到其他更灵活的组件。