I have the following code
package trtyhard;
import javax.swing.JFrame;
public class TrtyHard {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("TryHard");
//frame.setSize(700, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setSize(700, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Sometimes JFrame appears with diffirent size. Sometimes it has 10 additional mm at the bottom, sometimes 5-7 additional mm at the right side.
How can i fix it?
In addition to making sure the GUI is created on the Event Dispatch Thread EDT) try restructuring the code as follow:
JFrame frame = new JFrame("TryHard");
//frame.setSize(700, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setSize(700, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
The point is to set the frame properties before you do a setSize() or pack() on the frame.
Read the section from the Swing tutorial Initial Thread for more information about the EDT.
The JFrame class has the setBounds(x, y, width, height) method. You can try it. https://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#setBounds(int,%20int,%20int,%20int)
Related
I'm trying to add an image to a JFrame and set its location, I don't know why it just does not add into it, maybe I don't understand how the JFrame class works since a normal text JLabel adds into the JFrame simply without any trouble and a JLabel containing an image simply does not add in.
I would appreciate if someone would explain the error in the code, and maybe even give me a short explanation of why my way does not work. Thanks!
import java.awt.*;
import javax.swing.*;
public class Walk {
public static void main(String[] args) {
JFrame f = new JFrame("Study");
f.setSize(3000,1000);
f.getContentPane().setBackground(Color.white);
f.getContentPane().add(new JLabel("test", JLabel.CENTER) );
JLabel l = new JLabel(new ImageIcon("C:\\Users\\leguy\\OneDrive\\Desktop\\Stuff\\stillsp"));
l.setBounds(100, 100, 100, 100);
l.setVisible(true);
f.add(l);
f.setVisible(true);
}
}
are you using a gui class or you are writing its code into a main class
what is in your code is that you are writing its code so easy way is to just drag and drop try this link for normal jframes gui eclipse gui
about the picture into jframe is easy one all what you have to do is
1. create a label by setting its size as you want on the jframe by dragging and dropping only
2. follow the pictures
then you browser for your picture you want
select the picture and its done
Hope it helps
Make sure the path to your image is valid. All I did was point to a valid image on my PC and the code practically worked. There were a few things added and organized below.
import java.awt.Color;
import javax.swing.*;
public class Walk {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() { // Safety first...
#Override
public void run() {
String path = "C:\\Path\\To\\Image.png"; // Make sure it's correct
JFrame frame = new JFrame("Study");
JLabel label = new JLabel(new ImageIcon(path));
frame.setSize(3000, 1000);
frame.getContentPane().setBackground(Color.white);
frame.getContentPane().add(new JLabel("test", JLabel.CENTER));
label.setBounds(100, 100, 100, 100);
label.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
frame.pack(); // Pack the frame's components.
frame.setVisible(true);
}
});
}
}
To make sure both labels show up, provide a layout and add them accordingly.
import java.awt.*;
import javax.swing.*;
public class Walk {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
String path = "C:\\Path\\To\\Image.png"; // Make sure it's correct
JFrame frame = new JFrame("Study");
Container container = frame.getContentPane();
JLabel imageLbl = new JLabel(new ImageIcon(path));
JLabel textLbl = new JLabel("test");
frame.setLayout(new BorderLayout());
frame.setSize(3000, 1000);
imageLbl.setBounds(100, 100, 100, 100);
imageLbl.setVisible(true);
container.setBackground(Color.WHITE);
container.add(textLbl, BorderLayout.NORTH);
container.add(imageLbl, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
When I set a look and feel through the UIManager.setLookAndFeel the frame's content changes its look and feel as expected. E.g.
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
JFrame frame = new JFrame();
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("Some Button"));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 80);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
But the frame is still painted using the OS default (Windows in my case).
How can I make the frame look and feel aware so that it looks like the e.g. the nimbus look and feel?
Usually look and feel is implemented using the ComponentUI, but a JFrame is not a JComponent so I can't implement an own ComponentUI and set it.
1. Solution
My first thought was to use an undecorated JFrame with a JInternalFrame as its main component.
public class LAFAwareJFrame extends JFrame {
private JInternalFrame lafFrame = new JInternalFrame("", true, true, true, true);
private JDesktopPane desktopPane = new JDesktopPane();
public LAFAwareJFrame() {
super.setUndecorated(true);
desktopPane.add(lafFrame);
lafFrame.setVisible(true);
Container contentPane = super.getContentPane();
contentPane.add(desktopPane);
}
#Override
public void setUndecorated(boolean undecorated) {
throw new UnsupportedOperationException("Can't change the undecorated property for a LAFAwareJFrame");
}
#Override
public void setSize(int width, int height) {
super.setSize(width, height);
lafFrame.setSize(width, height);
}
#Override
public Container getContentPane() {
return lafFrame.getContentPane();
}
#Override
public void setTitle(String title) {
lafFrame.setTitle(title);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
JFrame frame = new LAFAwareJFrame();
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("Some Button"));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 80);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
But then I have a lot to do with event handling and delegation. E.g when the JInternalFrame gets moved I don't really want to move the internal frame. Instead I want to move the undecorated frame.
2. Solution
Use the JInternalFrame only as a renderer. Like a ListCellRender.
Since all solutions require a lot of work I want to ask you first if there is a better solution. E.g. a library or maybe it is already possible with standard Java and I missed something.
EDIT
I tried to use setDefaultLookAndFeelDecorated but it doesn't work with nimbus and not with motif.
I have a simple Swing GUI. (and not only this, all swing GUI I have written). When run it, it doesn't show anything except blank screen, until I resize the main frame, so every components have painted again, and I can show them.
Here is my simple code :
public static void main(String[] args) {
JFrame frame = new JFrame("JScroll Pane Test");
frame.setVisible(true);
frame.setSize(new Dimension(800, 600));
JTextArea txtNotes = new JTextArea();
txtNotes.setText("Hello World");
JScrollPane scrollPane = new JScrollPane(txtNotes);
frame.add(scrollPane);
}
So, my question is : how can when I start this class, the frame will appear all components I have added, not until I resize frame.
Thanks :)
Do not add components to JFrame after the JFrame is visible (setVisible(true))
Not really good practice to call setSize() on frame rather call pack() (Causes JFrame to be sized to fit the preferred size and layouts of its subcomponents) and let LayoutManager handle the size.
Use EDT (Event-Dispatch-Thread)
call JFrame#setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) as said by #Gilbert Le Blanc (+1 to him) or else your EDT/Initial thread will remain active even after JFrame has been closed
Like so:
public static void main(String[] args) {
//Create GUI on EDT Thread
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("JScroll Pane Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea txtNotes = new JTextArea();
txtNotes.setText("Hello World");
JScrollPane scrollPane = new JScrollPane(txtNotes);
frame.add(scrollPane);//add components
frame.pack();
frame.setVisible(true);//show (after adding components)
}
});
}
Your simple code is missing a few things.
You have to invoke SwingUtilities to put the Swing components on the event dispatch thread.
You should call the setDefaultCloseOperation on the JFrame.
You have to call the JFrame methods in the correct order. The setSize or pack method is called, then the setVisible method is called last.
public class SimpleFrame implements Runnable {
#Override
public void run() {
JFrame frame = new JFrame("JScroll Pane Test");
JTextArea txtNotes = new JTextArea();
txtNotes.setText("Hello World");
JScrollPane scrollPane = new JScrollPane(txtNotes);
frame.add(scrollPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(800, 600));
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new SimpleFrame());
}
}
I am writing an a snake game, but there's a small problem. SOMETIMES there's a little gap between the panel and the frame. I really have no idea what could be the problem as it appears so irregularly.
SSCCE:
public class Game {
static JFrame frame = new JFrame("The Snake Game");
static Game game = new Game();
JPanel cards;
static JPanel card1 = new JPanel();
private Game() {
}
public void addComponentToPane(Container pane) {
// CARD 1
card1.setLayout(null);
card1.setPreferredSize(new Dimension(600, 625));
CardLayout cl = new CardLayout();
cards = new JPanel(cl);
cards.add(card1);
pane.add(cards, BorderLayout.CENTER);
}
private static void createAndShowGUI() {
game.addComponentToPane(frame.getContentPane());
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
} // end of main
}
Try calling setResizable AFTER you call pack
For some reason, doing it the other way seems to add about 10-20 pixels to the width and height.
If that doesn't work, call setResizable AFTER the frame has being made visible
I encounter the same problem today. After a little bit of Googling, I couldn't find any good answer. Kuba gave a good hint and the problem is finally resolved. I guess this issue is caused by the delay of the setResizable(false) function and hence it happens occasionally. My solution is adding a short hold after calling setResizable.
setResizable(false);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
Okay, I know this is a disgusting way to do it. But in the question JFrame isResizable(false) sizing issue is said: "You can reset it by call JFrame#pack after the calling JFrame#setResizable". So I thought, why not reset it twice?!
Code:
private static void createAndShowGUI() {
game.addComponentToPane(frame.getContentPane());
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
if(frame.getContentPane().getWidth() > 600){
frame.pack();
}
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
So calling the method pack() for the second time when the width is greater than my preferred size seems to resolve the problem.
I have a simple Swing GUI. (and not only this, all swing GUI I have written). When run it, it doesn't show anything except blank screen, until I resize the main frame, so every components have painted again, and I can show them.
Here is my simple code :
public static void main(String[] args) {
JFrame frame = new JFrame("JScroll Pane Test");
frame.setVisible(true);
frame.setSize(new Dimension(800, 600));
JTextArea txtNotes = new JTextArea();
txtNotes.setText("Hello World");
JScrollPane scrollPane = new JScrollPane(txtNotes);
frame.add(scrollPane);
}
So, my question is : how can when I start this class, the frame will appear all components I have added, not until I resize frame.
Thanks :)
Do not add components to JFrame after the JFrame is visible (setVisible(true))
Not really good practice to call setSize() on frame rather call pack() (Causes JFrame to be sized to fit the preferred size and layouts of its subcomponents) and let LayoutManager handle the size.
Use EDT (Event-Dispatch-Thread)
call JFrame#setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) as said by #Gilbert Le Blanc (+1 to him) or else your EDT/Initial thread will remain active even after JFrame has been closed
Like so:
public static void main(String[] args) {
//Create GUI on EDT Thread
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("JScroll Pane Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea txtNotes = new JTextArea();
txtNotes.setText("Hello World");
JScrollPane scrollPane = new JScrollPane(txtNotes);
frame.add(scrollPane);//add components
frame.pack();
frame.setVisible(true);//show (after adding components)
}
});
}
Your simple code is missing a few things.
You have to invoke SwingUtilities to put the Swing components on the event dispatch thread.
You should call the setDefaultCloseOperation on the JFrame.
You have to call the JFrame methods in the correct order. The setSize or pack method is called, then the setVisible method is called last.
public class SimpleFrame implements Runnable {
#Override
public void run() {
JFrame frame = new JFrame("JScroll Pane Test");
JTextArea txtNotes = new JTextArea();
txtNotes.setText("Hello World");
JScrollPane scrollPane = new JScrollPane(txtNotes);
frame.add(scrollPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(800, 600));
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new SimpleFrame());
}
}