JComboBox Lost Listener on Look and Feel change

When the user change the Look And Feel on the Fly , any Listener that is done using

myComboBox.getEditor().getEditorComponent().addXXXListener

is lost

I'm using Windows XP Service Pack 2, java 6 build 105

Does someone have any inputs why this happen or how this can be "fixed" or maybe prevent. Do I'm doing something wrong?

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.border.*;

import java.util.*;

import java.text.SimpleDateFormat;

/* ComboBoxDemo2.java requires no other files. */

publicclass ComboBoxDemo2extends JPanel

implements ActionListener{

static JFrame frame;

JLabel result;

String currentPattern;

public ComboBoxDemo2(){

setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

String[] patternExamples ={

"dd MMMMM yyyy",

"dd.MM.yy",

"MM/dd/yy",

"yyyy.MM.dd G 'at' hh:mm:ss z",

"EEE, MMM d, ''yy",

"h:mm a",

"H:mm:ss:SSS",

"K:mm a,z",

"yyyy.MMMMM.dd GGG hh:mm aaa"

};

currentPattern = patternExamples[0];

//Set up the UI for selecting a pattern.

JLabel patternLabel1 =new JLabel("Enter the pattern string or");

JLabel patternLabel2 =new JLabel("select one from the list:");

JComboBox patternList =new JComboBox(patternExamples);

patternList.setEditable(true);

patternList.addActionListener(this);

//-- XXX

//This KeyListener it is lost when the user change the theme on the fly

patternList.getEditor().getEditorComponent().addKeyListener(new KeyAdapter()

{

publicvoid keyPressed(KeyEvent e)

{

System.out.println(" Key pressed is "+e.getKeyCode());

}});

//

//Create the UI for displaying result.

JLabel resultLabel =new JLabel("Current Date/Time",

JLabel.LEADING);//== LEFT

result =new JLabel(" ");

result.setForeground(Color.black);

result.setBorder(BorderFactory.createCompoundBorder(

BorderFactory.createLineBorder(Color.black),

BorderFactory.createEmptyBorder(5,5,5,5)

));

//Lay out everything.

JPanel patternPanel =new JPanel();

patternPanel.setLayout(new BoxLayout(patternPanel,

BoxLayout.PAGE_AXIS));

patternPanel.add(patternLabel1);

patternPanel.add(patternLabel2);

patternList.setAlignmentX(Component.LEFT_ALIGNMENT);

patternPanel.add(patternList);

JPanel resultPanel =new JPanel(new GridLayout(0, 1));

resultPanel.add(resultLabel);

resultPanel.add(result);

patternPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

resultPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

add(patternPanel);

add(Box.createRigidArea(new Dimension(0, 10)));

add(resultPanel);

setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

reformat();

}//constructor

publicvoid actionPerformed(ActionEvent e){

System.out.println("Action Event");

JComboBox cb = (JComboBox)e.getSource();

String newSelection = (String)cb.getSelectedItem();

currentPattern = newSelection;

reformat();

}

/** Formats and displays today's date. */

publicvoid reformat(){

try{

Date today =new Date();

SimpleDateFormat formatter =

new SimpleDateFormat(currentPattern);

String dateString = formatter.format(today);

result.setForeground(Color.black);

result.setText(dateString);

}catch (IllegalArgumentException iae){

System.out.println("Ilegal argument Exception");

}

catch (Exception e){

System.out.println("Argument Exception");

}

}

/**

* Create the GUI and show it. For thread safety,

* this method should be invoked from the

* event-dispatching thread.

*/

privatestaticvoid createAndShowGUI(){

//Create and set up the window.

final JFrame frame =new JFrame("ComboBoxDemo2");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create and set up the content pane.

JComponent newContentPane =new ComboBoxDemo2();

newContentPane.setOpaque(true);//content panes must be opaque

frame.setLayout(new BorderLayout());

//frame.setContentPane(newContentPane,BorderLayout.CENTER);

JMenuBar menuBar =new JMenuBar();

JMenu theme =new JMenu("Theme");

ButtonGroup bttnGroup =new ButtonGroup();

JCheckBoxMenuItem metal =new JCheckBoxMenuItem("Metal");

bttnGroup.add(metal);

metal.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent e){

try{

UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());

SwingUtilities.updateComponentTreeUI(frame);

}catch(Exception a){a.printStackTrace();}

}

});

theme.add(metal);

JCheckBoxMenuItem system =new JCheckBoxMenuItem("System");

bttnGroup.add(system);

system.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent e){

try{

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

SwingUtilities.updateComponentTreeUI(frame);

}catch(Exception a){a.printStackTrace();}

}

});

theme.add(system);

menuBar.add(theme);

frame.setJMenuBar(menuBar);

JToolBar jtb =new JToolBar();

jtb.add(newContentPane);

frame.add(jtb, BorderLayout.PAGE_START);

//Display the window.

frame.pack();

frame.setVisible(true);

}

publicstaticvoid main(String[] args){

//Schedule a job for the event-dispatching thread:

//creating and showing this application's GUI.

javax.swing.SwingUtilities.invokeLater(new Runnable(){

publicvoid run(){

createAndShowGUI();

}

});

}

}

[10422 byte] By [edgardo_Ria] at [2007-11-26 17:21:44]
# 1
Why are you registering a listener to the editor component?
Rodney_McKaya at 2007-7-8 23:49:44 > top of Java-index,Desktop,Core GUI APIs...
# 2

The editor is defined by the L&F as is the renderer. The reason being that if the editor is to look like it belongs with the JComboBox, it has to be L&F specific. So, after a L&F change, you have to register your listeners. You should also probably unregister your current listeners before doing a L&F change.

Jasprea at 2007-7-8 23:49:44 > top of Java-index,Desktop,Core GUI APIs...
# 3
if I domyComboBox.getEditor().addKeyListener //-->The source don't compileif I domyComboBox.addKeyListener //--> The KeyListener won't workmaybe I'm registering the wrong way a KeyListener in a JComboBoxDo you have any other way Rodney?
edgardo_Ria at 2007-7-8 23:49:44 > top of Java-index,Desktop,Core GUI APIs...
# 4
It depends what you want to do with this key listener.What is the key listener used for?Anyway you can extend JComboBox and register you key listener in the updateUI function, if that's whay you need.
Rodney_McKaya at 2007-7-8 23:49:44 > top of Java-index,Desktop,Core GUI APIs...
# 5

Thanks to both Rodney_McKay and jasper for their replys and ideas

This code is working fine

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.border.*;

import java.util.*;

import java.text.SimpleDateFormat;

/* ComboBoxDemo2.java requires no other files. */

public class ComboBoxDemo2 extends JPanel

implements ActionListener {

static JFrame frame;

JLabel result;

String currentPattern;

private JComboBox patternList = new JComboBox();

public ComboBoxDemo2() {

setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

String[] patternExamples = {

"dd MMMMM yyyy",

"dd.MM.yy",

"MM/dd/yy",

"yyyy.MM.dd G 'at' hh:mm:ss z",

"EEE, MMM d, ''yy",

"h:mm a",

"H:mm:ss:SSS",

"K:mm a,z",

"yyyy.MMMMM.dd GGG hh:mm aaa"

};

currentPattern = patternExamples[0];

//Set up the UI for selecting a pattern.

JLabel patternLabel1 = new JLabel("Enter the pattern string or");

JLabel patternLabel2 = new JLabel("select one from the list:");

patternList = new JComboBox(patternExamples){

public void updateUI(){

System.out.println("UPDATE UI");

super.updateUI();

changeUIAddEditorListener();

}

};

changeUIAddEditorListener();

patternList.setEditable(true);

patternList.addActionListener(this);

//Create the UI for displaying result.

JLabel resultLabel = new JLabel("Current Date/Time",

JLabel.LEADING); //== LEFT

result = new JLabel(" ");

result.setForeground(Color.black);

result.setBorder(BorderFactory.createCompoundBorder(

BorderFactory.createLineBorder(Color.black),

BorderFactory.createEmptyBorder(5,5,5,5)

));

//Lay out everything.

JPanel patternPanel = new JPanel();

patternPanel.setLayout(new BoxLayout(patternPanel,

BoxLayout.PAGE_AXIS));

patternPanel.add(patternLabel1);

patternPanel.add(patternLabel2);

patternList.setAlignmentX(Component.LEFT_ALIGNMENT);

patternPanel.add(patternList);

JPanel resultPanel = new JPanel(new GridLayout(0, 1));

resultPanel.add(resultLabel);

resultPanel.add(result);

patternPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

resultPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

add(patternPanel);

add(Box.createRigidArea(new Dimension(0, 10)));

add(resultPanel);

setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

reformat();

} //constructor

public void actionPerformed(ActionEvent e) {

System.out.println("Action Event");

JComboBox cb = (JComboBox)e.getSource();

String newSelection = (String)cb.getSelectedItem();

currentPattern = newSelection;

reformat();

}

/** Formats and displays today's date. */

public void reformat() {

try {

Date today = new Date();

SimpleDateFormat formatter =

new SimpleDateFormat(currentPattern);

String dateString = formatter.format(today);

result.setForeground(Color.black);

result.setText(dateString);

}catch (IllegalArgumentException iae) {

System.out.println("Ilegal argument Exception");

}

catch (Exception e) {

System.out.println("Argument Exception");

}

}

/**

* Create the GUI and show it. For thread safety,

* this method should be invoked from the

* event-dispatching thread.

*/

private static void createAndShowGUI() {

//Create and set up the window.

final JFrame frame = new JFrame("ComboBoxDemo2");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create and set up the content pane.

JComponent newContentPane = new ComboBoxDemo2();

newContentPane.setOpaque(true); //content panes must be opaque

frame.setLayout(new BorderLayout());

//frame.setContentPane(newContentPane,BorderLayout.CENTER);

JMenuBar menuBar = new JMenuBar();

JMenu theme = new JMenu("Theme");

ButtonGroup bttnGroup = new ButtonGroup();

JCheckBoxMenuItem metal = new JCheckBoxMenuItem("Metal");

bttnGroup.add(metal);

metal.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

try{

UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());

SwingUtilities.updateComponentTreeUI(frame);

}catch(Exception a){a.printStackTrace();}

}

});

theme.add(metal);

JCheckBoxMenuItem system = new JCheckBoxMenuItem("System");

bttnGroup.add(system);

system.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

try{

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

SwingUtilities.updateComponentTreeUI(frame);

}catch(Exception a){a.printStackTrace();}

}

});

theme.add(system);

menuBar.add(theme);

frame.setJMenuBar(menuBar);

JToolBar jtb = new JToolBar();

jtb.add(newContentPane);

frame.add(jtb, BorderLayout.PAGE_START);

//Display the window.

frame.pack();

frame.setVisible(true);

}

public static void main(String[] args) {

//Schedule a job for the event-dispatching thread:

//creating and showing this application's GUI.

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

//

public void changeUIAddEditorListener() {

patternList.getEditor().getEditorComponent().addKeyListener(new KeyAdapter()

{

public void keyPressed(KeyEvent e)

{

System.out.println(" Key pressed is "+e.getKeyCode());

}});

}

//

}

edgardo_Ria at 2007-7-8 23:49:44 > top of Java-index,Desktop,Core GUI APIs...