FULL PRODUCT VERSION :
Running on: jre1.5.0_04
ADDITIONAL OS VERSION INFORMATION :
Windows XP Pro (SP 2)
A DESCRIPTION OF THE PROBLEM :
When developing a Swing application I came to a point in my program where there needed to be a lot of processing before coloring the cells of a JTable. I decided to put this processing code in its own thread so I could maintain visability in the JFrame. In the new thread, one portion of the code asks the user to select a color from a JColorChooser. When I developed this program in Oracle's JDeveloper, the program runs fine, however when I throw the classes into an executable jar file to be run either locally or through a web browser as an applet I get an issue with the JColorChooser returning 'null' from the showDialog method. In my original program, very rarely does it actually return a color; however, in my test program, it will return colors more often, but still randomly returning 'null', even though a color has been selected and the "OK" button is being pressed.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a small swing application. I used an application provided from the tutorial section of Sun's website for using JColorChoosers titled ColorChooserDemo2 with the CrayonPanel removed. Essentially you need only two classes, one class to hold the code for the new thread, and one to run the swing application. Within the swing application start the new thread and have it popup a JColorChooser using JColorChooser.showDialog(...). Check that the dialog actually returns the color you selected and not 'null' if the "OK" button is pressed.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The program should work the same as it normally would if the JColorChooser were called from within the event-dispatching thread and return any color selected from the dialog.
ACTUAL -
Randomly, the program will error. Sometimes it will work just fine and return your selected color, and other times it will just return 'null.' The problem does not seem to revolve around any particular color selected. It seems like the problem may be stemming from the JDialog being destroyed before a color is returned.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
No specific errors are thrown, just a 'null' value returned.
REPRODUCIBILITY :
This bug can be reproduced often.
---------- BEGIN SOURCE ----------
//Test Class 1
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
public class Test extends JPanel
implements ActionListener,
ChangeListener
{
public JLabel banner;
public JColorChooser tcc;
public Test()
{
super(new BorderLayout());
//Set up banner to use as custom preview panel
banner = new JLabel("Welcome to the Tutorial Zone!",
JLabel.CENTER);
banner.setForeground(Color.yellow);
banner.setBackground(Color.blue);
banner.setOpaque(true);
banner.setFont(new Font("SansSerif", Font.BOLD, 24));
banner.setPreferredSize(new Dimension(100, 65));
JPanel bannerPanel = new JPanel(new BorderLayout());
bannerPanel.add(banner, BorderLayout.CENTER);
bannerPanel.setBorder(BorderFactory.createTitledBorder("Banner"));
//Set up color chooser for setting background color
JPanel panel = new JPanel(); //use FlowLayout
JButton bcc = new JButton("Show Color Chooser...");
bcc.addActionListener(this);
panel.add(bcc);
panel.setBorder(BorderFactory.createTitledBorder(
"Choose Background Color"));
//Set up color chooser for setting text color
tcc = new JColorChooser();
tcc.getSelectionModel().addChangeListener(this);
tcc.setBorder(BorderFactory.createTitledBorder("Choose Text Color"));
//Remove the preview panel
tcc.setPreviewPanel(new JPanel());
//Override the chooser panels with our own
AbstractColorChooserPanel panels[] = { };
tcc.setChooserPanels(panels);
tcc.setColor(banner.getForeground());
add(bannerPanel, BorderLayout.PAGE_START);
add(panel, BorderLayout.CENTER);
add(tcc, BorderLayout.PAGE_END);
}
public void setColor(Color newColor)
{
if (newColor != null)
{
banner.setBackground(newColor);
}
}
public void actionPerformed(ActionEvent e)
{
ColorChooserDemo2 thread = new ColorChooserDemo2(this, banner.getBackground());
Thread th = new Thread(thread);
th.start();
}
public void stateChanged(ChangeEvent e) {
Color newColor = tcc.getColor();
banner.setForeground(newColor);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("ColorChooserDemo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new Test();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String args[])
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
//Test Class 2
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
public class ColorChooserDemo2 implements Runnable
{
private JColorChooser chooser;
private Test parent;
private Color defaultCol;
public ColorChooserDemo2(Test prnt, Color bg)
{
parent = prnt;
defaultCol = bg;
}
public void run()
{
Color newColor = JColorChooser.showDialog(
parent,
"Choose Background Color",
defaultCol);
if (newColor != null)
{
parent.setColor(newColor);
}
else
JOptionPane.showMessageDialog(parent, "Null again.");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Modify the color chooser thread class to use the createDialog(...) method and be sure to get the color before disposing the dialog. Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
public class ColorChooserDemo2 implements Runnable, ChangeListener, ActionListener
{
private JDialog dialog;
private JColorChooser chooser;
private Test parent;
private Color defaultCol;
public ColorChooserDemo2(Test prnt, Color bg)
{
parent = prnt;
defaultCol = bg;
}
public void run()
{
createColorChooser();
}
private void createColorChooser()
{
chooser = new JColorChooser();
dialog = JColorChooser.createDialog(parent, "Color Test", true, chooser, this, this);
chooser.setColor(defaultCol);
dialog.setVisible(true);
Color color = chooser.getColor();
dialog.dispose();
if(color != null)
parent.setColor(color);
else
JOptionPane.showMessageDialog(parent, "Null again.");
}
public void stateChanged(ChangeEvent evt)
{ // Do Nothing, let Dialog handle all events at higher level
}
public void actionPerformed(ActionEvent evt)
{ // Do Nothing, let Dialog handle all events at higher level
}
}