Calm Sea
Calm Sea

Reputation: 181

jcombobox popup menue

What I am hoping is, when typing in editable JCombobox , the Popup Menu of the JCombobox to appear autumaticaly , i did this and it worked . But, when i changed the Icon of the Arrow Button in the JCombobox it didnt worked any more as shown in the picture

before changing Arrow Button Icon

enter image description here

After changing Arrow Button Icon (the Popup never appears, when one writes in the JCombobox)

enter image description here

this is what i did :

JTextComponent editor;
/** Creates new form combo */
public combo() {
    initComponents();

    editor = (JTextComponent) jComboBox1.getEditor().getEditorComponent();
    jComboBox1.setEditable(true);

    editor.addKeyListener(new KeyAdapter() {
        @Override
        public void keyReleased(KeyEvent e) {

            char keyChar = e.getKeyChar();
            if (jComboBox1.isDisplayable()) 
            { 
                jComboBox1.setPopupVisible(true);    
            }
            editor.setCaretPosition(editor.getText().length());

            //  System.out.println("wwwweeeee"+keyChar);
        }
    });    

    jComboBox1.setUI(new SynthComboBoxUI() {
        protected JButton createArrowButton() {

            JButton btn = new JButton();
            btn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Image/error3.png")));            
            return btn;
        }
    });
}    

Pleeeese help because i'm really tired from searching for a solution

Upvotes: 2

Views: 1023

Answers (1)

kleopatra
kleopatra

Reputation: 51525

The technical problem here is that the editor is created/maintained by the ui. When setting a custom ui it is replaced by a new editor, so you are listening to a component that is no longer part of the container hierarchy.

After digging a bit ... I still don't have a solution :-( On face value, you'd call setUI before installing the listener on the editor - BUT calling setUI is always wrong ... so simply don't.

Seeing that the ui is synth-based, the correct way to update its visual fore/background properties is to supply custom painters, per-application or per-instance. Nimbus specifically allows to install per-instance custom UIDefaults via the "Nimbus.Overrides" client property. For changing the icon on the arrow button, the appropriate override would be

Painter core = // a custom painter which paints the icon 
comboDefaults.put("ComboBox:\"ComboBox.arrowButton\"[Enabled].foregroundPainter", core);
combo.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
combo.putClientProperty("Nimbus.Overrides", comboDefaults);

All fine, except not working - looks like the overrides are not properly installed on the children.

Edit 2

... hours later ...

from all available resources, the above should work, see f.i. Jasper's initial explanation of how-to define custom properties:

ComponentA:ChildComponentB.foreground which lets you specify a ChildComponentB contained within ComponentA.

So I suspect it's really a bug. A not really satisfying hack-around is to install the override on the button itself:

JButton org = null;
for (int i = 0; i < combo.getComponentCount(); i++) {
    if (combo.getComponent(i) instanceof JButton) {
        org = (JButton) combo.getComponent(i);
        UIDefaults buttonDefaults = new UIDefaults();
        buttonDefaults.put("ComboBox:\"ComboBox.arrowButton\"[Enabled].foregroundPainter", painter);
        org.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
        org.putClientProperty("Nimbus.Overrides", buttonDefaults);
        break;
    }
}

That's not satisfying at all, as the button creation is controlled by the ui delegate, so this config will not survive a switch of LAF. Or the other way round: you'll need a install a PropertyChangeListener with the UIManager and on detecting a switch to Nimbus, manually copy the overrides from the combo to its children.

Upvotes: 5

Related Questions