I've created a new project in java with this simple code:
public static void main(String[] args)
{
JFrame frame;
frame = new JFrame("Empty");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
I've noticed that moving the JFrame causing the memory used by the process to increase.
Why is that?
Is there a way to avoid this using the same code above but with some additions?
Are there any better ways to simply display a JFrame?
Seeing memory usage increase does not mean that there's a memory leak. The program may use more memory because it has to create temporary objects for event dispatching or repainting. These temporary objects are short-lived and are removed by the garbage collector in a short period of time; so the memory used by them becomes available for the program again.
You won't see this with process monitoring tools though since the memory is not returned to the OS; the JVM reserves it for future use. You can use tools like VisualVM to monitor the actual memory use of the program.
Are there any better ways to simply display a JFrame?
The code that you post is actually incorrect; you shouldn't create and manipulate GUI objects from the program's main thread. Here's a correct example of displaying a JFrame from the Java Tutorial:
import javax.swing.*;
public class HelloWorldSwing {
/**
* 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.
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Related
Sorry for the very noob question, but I'm having a tremendously difficult time understanding Swing graphics and how to just, well, draw something for goodness sake.
First question is just a snippet question.
When we do this standard code in particular...
public static void main(String[] args) {
Jframe frame= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new MyCustomJPanel());
frame.setSize(500,500);
frame.setVisible(true);
}
...we set the frame pane as a new JPanel object (of class MyCustomJPanel in this case), but we don't directly name that new MyCustomJPanel object...why don't we name it? And without naming it, how can we possibly ever reference that object again?
Second question...as I mentioned, I've been studying swing graphics now for a bit but I simply can't get my mind wrapped around it. Try as I might, I simply cannot conjure up a way to draw a line at runtime on my JPanel in my JFrame. Is there no way to do this? It seems unless the line is hard-coded at compile time in my JPanel's overridden paint(g) method, runtime addition simply can't be done (without resorting to BufferedDrawings or other more advanced topics)...as there's no way to dynamically throw new code into paint(g).
Thanks, and sorry for the noobness. Trying to (re)learn OOP and Java and having a roaringly difficult time of it.
Can't help all that much without seeing the whole code, but I've heard only bad things about IntelliJ's GUI builder. I use Eclipse's Window builder, but there is also Netbeans. Both are popular for Swing, and there is also JavaFX but that's a whole different story.
For your code, when creating your JFrame class, did you write it like:
public class MainFrame extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(false);
frame.setMinimumSize(new Dimension(545, 693));
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public mainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 545, 693);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
//Continue adding components here...
}
Your class extends JFrame, your main method instantiates the frame, and your MainFrame class is where you add your components.
I'm not very good at explaining stuff but hope this helps.
I understand that EventQueue.invokeLater() is a function called to make the Java Swing components Thread-Safe.
Also, I know that the argument to this function is an object with implements Runnable.
However, I am unable to understand the syntax for this function call, i.e. this call -
EventQueue.invokeLater(()-> {
new Screen();
});
Here, Screen() is a class that extends JFrame.
public class Screen extends JFrame
{
Screen()
{
setSize(1000, 1000);
JPanel j1 = new Board();
j1.setBounds(0,0,500, 500);
JPanel j2 = new DiceModel();
j2.setBounds(500, 0, 500, 500);
add(j1);
add(j2);
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(()-> {
new Screen();
});
}
}
This code runs as expected.
Board and DiceModel are two classes I have defined that which extend JPanel.
The invocation
EventQueue.invokeLater( new Screen() );
gives the expected error that Screen is not an object of type Runnable.
So,my question is, what is the meaning of the syntax for the function call for invokeLater() ?
Is it a kind of anonymous function call in Java ?
The complete Swing processing is done in a thread called EDT (Event Dispatching Thread). Therefore you would block the GUI if you would compute some long lasting calculations within this thread.
The way to go here is to process your calculation within a different thread, so your GUI stays responsive. At the end you want to update your GUI, which have to be done within the EDT. Now EventQueue.invokeLater comes into play. It posts an event (your Runnable) at the end of Swings event list and is processed after all previous GUI events are processed.
Also the usage of EventQueue.invokeAndWait is possible here. The difference is, that your calculation thread blocks until your GUI is updated. So it is obvious that this must not be used from the EDT.
Still there is Java code out there that starts a JFrame simple from the main thread. This could cause issues, but is not prevented from Swing. Most modern IDEs now create something like this to start the GUI
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
public static void main(String args[]){
JFrame frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMISED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
I've used this code to maximise a JFrame, but instead of actually maximising the frame, it just sets the window size to that of the screen, without actually changing the state, so clicking the maximize button doesn't actually downscale it again.
Am I using the wrong command or something?
You have an error in frame.setExtendedState(JFrame.MAXIMISED_BOTH);
You should write frame.setExtendedState(JFrame.MAXIMIZED_BOTH); instead
Have you tried this?
f.setExtendedState(f.getExtendedState() | JFrame.MAXIMIZED_BOTH);
Based on your provided example and run on Windows 7...
"Maximised" state (this is cropped version of window as the original is quite large)
"Normal" state
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ExtendedFrame {
public static void main(String[] args) {
new ExtendedFrame();
}
public ExtendedFrame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
// frame.setExtendedState(JFrame.MAXIMISED_BOTH);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
You must want it maximized by default. Because the maximize button works out-of-the-box.
frame.setExtendedState(JFrame.MAXIMIZED_BOTH) works on Linux x64. Here's the program I tested with:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test implements ActionListener {
public static void main(String... args) {
new Test();
}
private JFrame frame;
public Test() {
frame = new JFrame();
frame.add(new JLabel("Hi!"), BorderLayout.CENTER);
JButton button = new JButton("maximize");
button.addActionListener(this);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
This worked for me:
We need to combine the setSize () and setExtendedState together
JFrame frame=new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // aligns itself with windows task bar
// set maximum screen
frame.setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(), (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight());
You should use this when applying changes
frame.setResizable(true);
Seven years late is better than never, right?
The question does not provide an SSCCE presumably because this is not all of the code involved. The tiny fragment of code provided work as it is, so practically all previous answers are saying "works for me". So, the problem certainly lies with the rest of the code, which is not shown.
We cannot be sure what the rest of the code does, but I suspect that it tries to persist the state and bounds of the frame, and to restore that state and bounds later, and that is what fails. The OP did not receive an answer 7 years ago because they did not explain what the actual problem was, but this question will be viewed by many more, so here it goes:
In theory, persisting the state and bounds of a frame should be piece of cake, but in practice it is not.
This is a very common problem in GUI applications, and it is basically due to a common mistake on behalf of the programmer. However, it should be noted that various widely used GUI frameworks (and certainly both Swing and SWT in the Java world) operate in a specific perverse way which makes it a very easy mistake to make.
The problem begins with the fact that these frameworks do not support a 'maximized' event, (duh!) so the only way you can detect that your frame has been maximized is to listen to the 'resized' event. So, you are presumably persisting the state and dimensions of your frame from within your 'resized' event handler.
The problem is further compounded by the fact that once the 'resized' event has occurred as a result of maximizing the frame, the frame bounds are the maximized bounds of your frame, which are irrelevant, and you will be shooting yourself in the foot if you make the mistake of persisting them.
So, the solution is to manually keep track of the "normal state" bounds of your frame, and only persist those. This can be accomplished as follows:
addComponentListener( new ComponentAdapter()
{
#Override public void componentResized( ComponentEvent e )
{
if( (getExtendedState() & MAXIMIZED_HORIZ) == 0 )
normalStateBounds.width = getWidth();
if( (getExtendedState() & MAXIMIZED_VERT) == 0 )
normalStateBounds.height = getHeight();
stateAndOrSizeChanged();
}
#Override public void componentMoved( ComponentEvent e )
{
if( (getExtendedState() & MAXIMIZED_HORIZ) == 0 )
normalStateBounds.x = getX();
if( (getExtendedState() & MAXIMIZED_VERT) == 0 )
normalStateBounds.y = getY();
stateAndOrSizeChanged();
}
} );
...where:
normalStateBounds is defined as private final Rectangle normalStateBounds = new Rectangle(); and contains the bounds of your component when in the "normal" (i.e. not minimized, nor maximized) state
stateAndOrSizeChanged() is your function which handles persisting the state and bounds of your frame, being careful to only persist normalStateBounds instead of the values returned by getX(), getY(), getWidth(), and getHeight().
When loading the state and bounds from persistence, you can simply invoke setBounds() followed by setExtendedState(), and you should do that before invoking setVisible( true ) to avoid the possibility of your frame appearing restored for a blink of an eye before maximizing. The call to setBounds() will set the non-maximized bounds, and the call to setExtendedState() might maximize your frame, but if you then restore it, it will assume the non-maximized bounds that you have set.
It works for me running Java 7 on a WinXP machine.
For the record, this is what an SSCCE should look like:
import javax.swing.*;
public class JFrameExtendedDemo
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
// Then:
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
}
}
What is the best practice way to start a java swing application? Maybe there is another way to do it.
I want to know if i have to use the SwingUtilities class to start the application (secound possibility) or not (first possibility).
public class MyFrame extends JFrame {
public void createAndShowGUI() {
this.setSize(300, 300);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
// add components and stuff
this.setVisible(true);
}
public static void main(String[] args) {
// First possibility
MyFrame mf = new MyFrame();
mf.createAndShowGUI();
// Secound possibility
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame mf = new MyFrame();
mf.createAndShowGUI();
}
});
}
}
Only the second way is correct. Swing components must be created and accessed only in the event dispatch thread. See concurrency in swing. The relevant quote:
Why does not the initial thread simply create the GUI itself? Because almost all code that creates or interacts with Swing components must run on the event dispatch thread. This restriction is discussed further in the next section.
So yes, you need to use invokeLater().
I have one simple question why do I need write code like this with
SwingUtilities.invokeLater(new Runnable(){
If programm create same frame without it?
code with SwingUtilities
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main (String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JFrame frame = new JFrame("Hello world swing");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 400);
}
});
}
}
code without swing utilities.
import javax.swing.JFrame;
public class App {
public static void main (String args[]){
JFrame frame = new JFrame("Hello world swing");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 400);
}
}
Swing is not thread-safe, and is single-threaded. It relies on the Event Dispatch Thread (EDT) for creating, updating and rendering its components.
See http://en.wikipedia.org/wiki/Event_dispatching_thread
SwingUtilities.invokeLater and SwingUtilities.invokeAndWait are utility methods
to basically put your Swing related task into the EDT.
If you don't do it, it may fail eventually. You will see weird results, as your application becomes bigger.
Always do GUI (SWING) related operations on EDT.
Also most GUIs are single-threaded. So is Swing. Therefore, trying to
access Swing from more than one thread will increase the risk of application failing.
Read this
http://codeidol.com/java/java-concurrency/GUI-Applications/Why-are-GUIs-Single-threaded/
In your code, a Swing Operation (creation of JFrame) is being done on main thread, which is not recommended. Use SwingUtilities.invokeLater().