Swing JDialog bug? - java

I'm trying to create my own dialog by extending the JDialog class
this is the code i used to start:
import javax.swing.JDialog;
public class ColorManager extends JDialog {
private static final long serialVersionUID = 1L;
public ColorManager(){
super();
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.pack();
this.setVisible(true);
}
}
when i try to run the code it works fine but i'm getting the following exception:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: defaultCloseOperation must be one of: DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE, or DISPOSE_ON_CLOSE
i read that there were problems with WINDOWS_EXIT or something like that but the parameter i pass should do the job.
the thing that makes it even weirder is that when i change my class so it will contain a JDialog field instead of extending it, it seems to work just fine.
I asked a friend to test this on his computer and the code did not throw the exception, he is using jre version 1.6.022 and I'm using 1.6.022 both of us are using 64 bit.
so what did i do wrong? or is that a bug in the JRE?
Edit: forgot to mention, I'm using eclipse
Edit2: i tried the same code in Netbeans and it works fine, what could be my problem??

All the methods you call in constructor should be called on the EDT thread. It is not advised to do it inside the constructor, but if you insist make sure it runs on Swing (EDT) thread such as:
import javax.swing.JDialog;
public class ColorManager extends JDialog {
private static final long serialVersionUID = 1L;
public ColorManager(){
super();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.pack();
this.setVisible(true);
}
});
}
}
IMO the best way do accomplish it would be to move this into separate method and then call it after creating your ColorManager instance.
When using Swing you should always adhere to Swing threading rules. More information can be found at
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

All the above solution are great, I also had very disturbing moment with show the JDialog.
On NETBEAN 8.2 just left click the JFrame and choose properties, then set the defaultCloseOperation Property ... Usually the first on the list,
do the same for the JDialog
... Anyway that,s my own experience

Related

Guice cannot instantiate class that extends JPanel - NPE in call to super constructor

We have a desktop Swing application with Google Guice 4.1.0 dependency injection. Everything worked fine during development, but something strange happened when colleague tried to run the application.
We have a MainWindow class that extends JPanel. In the constructor this class takes some controllers that itself are injectable. In main method Guice injector is created. Then the injector tries to instantiate MainWindow (injector.getInstance(MainWindow.class)). And it failed with NullPointerException!
This doesn't happen on my computer, and we use the same JDK.
Here is MainWindow class stripped down to problematic code (note: this does not reproduce the problem, unfortunately):
class MainWindow extends JPanel {
private final Foo foo;
private final JFrame frame;
#Inject
public MainWindow(Foo foo) {
super(new GridBagLayout()); // <-- NullPointerException
this.foo = foo;
this.frame = new JFrame("title");
}
public void createAndShowGUI() {
// ...
frame.add(this);
frame.pack();
frame.setVisible(true);
}
}
And here is main() method:
class Main {
private static final Injector injector = Guice.createInjector();
public static void main(String[] args) {
MainWindow mainWindow = injector.getInstance(MainWindow.class);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
mainWindow.createAndShowGUI();
}
});
}
}
Here is stack trace of the exception:
com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, java.lang.NullPointerException
at app.gui.MainWindow.<init>(MainWindow.java:133)
while locating app.gui.MainWindow
1 error
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028) ~[app-1.0-SNAPSHOT.jar:?]
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054) ~[app-1.0-SNAPSHOT.jar:?]
at app.Main.createAndShowGUI(Main.java:40) ~[app-1.0-SNAPSHOT.jar:?]
at app.Main.access$000(Main.java:26) ~[app-1.0-SNAPSHOT.jar:?]
at app.Main$2.run(Main.java:67) ~[app-1.0-SNAPSHOT.jar:?]
The NPE was thrown in the most surprising place – in the call to constructor of superclass of MainWindow (this is line 133). I started digging and found out that manual creation of MainWindow and injecting its dependencies works correctly:
MainWindow mainWindow = new MainWindow(injector.getInstance(Foo.class));
I suspected that maybe class loader didn't work correctly, so I tried again with logging classloader of both MainWindow and JPanel:
System.out.println("MainWindow: " + MainWindow.class.getClassLoader());
System.out.println("JPanel: " + JPanel.class.getClassLoader());
MainWindow mainWindow = injector.getInstance(MainWindow.class);
Class loaders are different (JPanel is loaded by bootstrap), but now the injection worked properly. I suppose this is because now JPanel class was explicitly loaded into main method context.
So my questions are:
Did anyone have similar problem?
Is it my mistake, or is it a bug?
If it is a bug, does it happen in Guice? Or maybe JRE?
More details about Java and OS:
I originally developed it with JDK 1.8.0u111, but then switched to JDK 1.8.0u121.
Application is compiled to Java 6.
Runs flawlessly on my computer with Windows 10, version 1607 (OS Build 14393.693), on JRE 6 and JRE 8 (from JDK).
NullPointerException is raised on colleague's computer with Windows 10, version 1511 (OS Build 10586.753), JDK 1.8.0u112 and 1.8.0u121.
Unfortunately I was unable to provide minimal version that reproduces the problem. Heck, I cannot even reproduce the problem, it happens only on colleague's environment.
I highly suspect this is due to a race condition. Swing components are not thread safe and should be instantiated on the EDT as per the swing package javadoc :
Swing's Threading Policy
In general Swing is not thread safe. All Swing components and related
classes, unless otherwise documented, must be accessed on the event
dispatching thread. Typical Swing applications do processing in
response to an event generated from a user gesture. For example,
clicking on a JButton notifies all ActionListeners added to the
JButton. As all events generated from a user gesture are dispatched on
the event dispatching thread, most developers are not impacted by the
restriction.
Where the impact lies, however, is in constructing and showing a Swing
application. Calls to an application's main method, or methods in
Applet, are not invoked on the event dispatching thread. As such, care
must be taken to transfer control to the event dispatching thread when
constructing and showing an application or applet. The preferred way
to transfer control and begin working with Swing is to use
invokeLater. The invokeLater method schedules a Runnable to be
processed on the event dispatching thread.
(emphasis mine)
Now you do start the UI in the EDT, using invokeLater, however you construct the UI on the main thread (through a Guice injector call).
The Guice injector call should also be in the invokeLater part to kick off the UI.

Display pop-up message window in Java?

I read about JDialogs and JOptionPane messages but I still can't get it to work. I have a GUI class that extends JFrame. All I want to do is have a popup at the beginning of my program which informs the user about a couple of things. In my main I create the following gui:
GUI g = new GUI();
Right after that I was to display the window. I have tried the following in the main method:
JOptionPane.showMessageDialog(g, "work?");
JOptionPane.showMessageDialog(frame, "work?"); //(frame was used in documentation example so I tried it)
I also tried to add the pop up into the GUI class with the following
JOptionPane.showMessageDialog(this, "work?"); //(I'm not exactly sure what the Frame Owner parameter is supposed to be, unless I'm confusing this with JDialog.)
In any case, how would I make this window appear? Every single one of the methods I tried compiled, and nothing happened.
public class GUI extends JFrame implements ActionListener{
private Container background;
private static buttons etc...
private static JLabel disp,edisp;
private static JTextArea info;
//setting up the GUI for my program, adding action listeners, I can post more if necessary
}
And then I have the main where I want to call the pop up window
public static void main(String[] args){
GUI g = new GUI();
JOptionPane.showMessageDialog(g,"Work?");
}
Make sure that these are called near the beginning, be it in the main method or not.
Also, try just setting the first parameter as null.
So it reads:
JOptionPane.showMessageDialog(null,"Work?");
Also, remember to import it!

Call method in another class to set label text (don't use netbeans' default stuff)

I'm using netbeans and want to edit the text in a label. I want to edit this label from another class in the main driver class. I have about 7 or 8 JDialog pages and let's say the label is on one of those pages.
When I try to call the method from one of those JDialogs so that I can edit it, it keeps asking for a java.awt.Frame. Where would I find that Frame name? Or, is there an easier way of editing labels from another class?
Netbeans makes labels private by default so I looked online and people have said making a setter method would be easiest.
QuickScreen is a .java file for instance...
public static void resetNumbers(){
QuickScreen qs = new QuickScreen(some frame);
qs.editLabel("Hello");
}
Please refer to my last comment on bmoran's solution.
If you change the label you want to set to either default or protected level access, then you can set it from your dialog as long as both classes are in the same package (for default) or your dialog box extends the class that the label is in (protected).
public class FrameClass extends JFrame {
JLabel label1;// package access
MyDialog dialog;
//constructor *** Netbeans may have an init() method ***
public FrameClass(){
label1=new JLabel("Hello!");
...
}
...
}
public class MyDialog{
public void changeLabel(){
FrameClass.label1.setText("Good Bye!");
}
}

Why bother with setting the "sun.awt.exception.handler" property?

Here's some code that catches an exception thrown on the Event Dispatch Thread:
package com.ndh.swingjunk;
import java.awt.EventQueue;
import javax.swing.JFrame;
public class EntryPoint {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
// System.setProperty("sun.awt.exception.handler", MyExceptionHandler.class.getName());
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new SomeWindow("foo").setVisible(true);
}
});
}
}
class SomeWindow extends JFrame {
public SomeWindow(String title) {
this.setTitle(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
throw new RuntimeException("hello");
}
}
I've seen warnings that exceptions thrown on the Event Dispatch Thread don't get handled by the UncaughtExceptionHandler, but that doesn't seem to be the case for my example; it works the same whether the registration line is commented out or left in. Is my example messed up somehow, or is registering the exception handler with the sun.awt.exception.handler no longer necessary?
The EDT class (java.awt.EventDispatchThread, don't look for it in the javadoc, this class is package private) has changed a lot since the origins of AWT.
In JDK6, you can see that this class now can properly handle exceptions occuring inside the EDT. Exception handling is a bit complex in the current version:
if you have set the
sun.awt.exception.handler property,
then your handler will be called for
every exception thrown by developer's
code called inside the EDT
(compatibility with previous JDK
versions is ensured).
otherwise, any exception will be
rethrown, hence will stop the current EDT, and any default
UncaughtExceptionHandler will be
able to catch it, as your snippet
demonstrates.
BUT (and this is very important), if you carefully look at the code of EDT, you'll see that this mechanism won't work if the exception occurs in the EDT while a modal dialog is displayed (I guess this is because EDT and EventQueue management is quite complicated and I would even dare say "messy": a lot of code looks like hacks in there).
In this exact situation, exceptions will be logged to System.err, except if you have set the sun.awt.exception.handler property. Having a default UncaughtExceptionHandler will not help.
So my take on this is that, YES, you should still bother with sun.awt.exception.handler property, except if you can say for sure that your application doesn't use modal dialogs (don't forget that JOptionPane dialogs are also modal).
You've called setDefaultUncaughtExceptionHandler instead of setUncaughtExceptionHandler. (If a SecurityManager is present: the former requires RuntimePermission setDefaultUncaughtExceptionHandler; the latter as SecurityManager.checkAccess(Thread).)

Java JFrame keeps loading

Hi this is a stange one for me so I hope you can help :)
I have a method..
public void WMPEGUI(String info)
it loads a JFrame...
final JFrame mainFrame = new JFrame("JFrame");
the method is set up to recieve strings into it to later be wrote out to a text area also created within the method. When I run the program everytime the methods recieves a string it opens a new JFrame I have tried to solve it using...
mainFrame.setAlwaysOnTop(true);
mainFrame.setLocationByPlatform(true);
But this hasn't solved it, hence asking you kind people. If anyone knows why as I can't find anything on it :/
Many thansk in advance
Well I think your problem is that according to you, your method loads a JFrame. You need to create the JFrame outside that method, somewhere else within the same class, and then refer to it (or to one of it's containers where you will display that string).
Something like this:
public class YourClass {
//Class variables
...
JFrame mainFrame = new JFrame("JFrame");
...
public void WMPEGUI(String info) {
...
mainFrame.someMethod(...) //or a get for one of its containers
...
}
}

Categories

Resources