Reputation: 55
My custom JFrame implements runnable interface, so it contains the run method, and in my main method, this is how I try to open my frame:
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
Cadre cadre = new Cadre();
}
}.start();
}
Unfortunately this done not make the frame appear, it seems to ignore the frame's run method.
and here's my class:
public class Cadre extends JFrame implements Runnable {
private PanneauHaut panneauHaut;
private PanneauBas panneauBas;
@Override
public void run() {
System.out.println("Thread started");
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
this.panneauHaut = new PanneauHaut();
this.panneauBas = new PanneauBas();
JPanel mainPanel = new JPanel();
JTextField kooltxt = new JTextField("hehehe");
mainPanel.setLayout(new BorderLayout());
mainPanel.add(panneauHaut, BorderLayout.NORTH);
mainPanel.add(panneauBas.getPanel(), BorderLayout.SOUTH);
this.setContentPane(mainPanel);
this.setVisible(true);
}
}
What could be wrong?
Upvotes: 1
Views: 1552
Reputation: 347194
You don't and you shouldn't. Swing is single threaded AND not thread safe. Look at Concurrency in Swing for more details
The "major" problem is, you are creating a new instance Cadre
in the Thread
's run
method, but nothing is calling the Cadre
s run
method...
new Thread() {
@Override
public void run() {
Cadre cadre = new Cadre();
}
}.start();
Where is Cadre#run
called?
A "better" solution would be to do something more like EventQueue.invokeLater(new Cadre())
, which will execute the Cadre
's run
method within the context of the Event Dispatching Thread - safely
Nothing happens with invokeLater
Works fine for me - any additional problems are likely some where else in the code you've not provided, that or you need to do a clean and build to flush out any "stale" binaries.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Cadre());
}
public static class Cadre extends JFrame implements Runnable {
// private PanneauHaut panneauHaut;
// private PanneauBas panneauBas;
@Override
public void run() {
System.out.println("Thread started");
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// setExtendedState(JFrame.MAXIMIZED_BOTH);
// this.panneauHaut = new PanneauHaut();
// this.panneauBas = new PanneauBas();
JPanel mainPanel = new JPanel();
JTextField kooltxt = new JTextField("hehehe");
mainPanel.setLayout(new BorderLayout());
mainPanel.add(kooltxt);
// mainPanel.add(panneauHaut, BorderLayout.NORTH);
// mainPanel.add(panneauBas.getPanel(), BorderLayout.SOUTH);
this.setContentPane(mainPanel);
pack();
setLocationRelativeTo(null);
this.setVisible(true);
}
}
}
Upvotes: 3
Reputation: 180151
it seems to ignore the frame's run method
Well of course it does. You have instantiated an anonymous subclass of Thread
whose run()
method does nothing but instantiate a Cadre
via its default constructor. Nothing there would cause the new Cadre
's run()
method to run.
You could instead instantiate a stock Thread()
via the constructor that accepts a Runnable
:
new Thread(new Cadre()).start();
... but that seems pretty pointless.
Be aware in particular that Swing itself does all its work in yet a different thread, the "Event-Dispatch Thread", and that Swing and standard Swing components are not thread-safe.
Better, then, would be
SwingUtilities.invokeAndWait(new Cadre());
(or invokeLater(new Cadre())
), but that will cause the Cadre
's run()
method to run on the Event-Dispatch thread, not on some random other thread of your choosing. In fact, that's probably what you should do, since the method in question constructs and displays a Swing GUI, but it's not what you seem to think you want to do.
Upvotes: 1