Swing - JFrame is sometimes bigger than preffered size - java

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.

Related

How to add an Image to a JFrame

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);
}
});
}
}

JFrame appears with different size

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)

How to make JFrame look and feel aware

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.

JFrame background color not working

My code
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("Flappy bird");
frame.setSize(1200, 800);
FlappyBird game = new FlappyBird();
frame.getContentPane().setBackground(Color.YELLOW);
frame.add(game);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
while (true) {
game.moveBall();
game.gameOver();
game.moveRect();
game.repaint();
Thread.sleep(14);
}
}
Why isn't the frame.getContentPane().setBackground(Color.YELLOW); working?
I've tried to rearrange the order, like setting the color after making the frame visible.
It works alright, but you cannot see the background color because your FlappyBird instance is drawn on top of it. You can easily verify this by replacing your game class with an empty canvas like so:
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("Flappy bird");
frame.setSize(1200, 800);
//FlappyBird game = new FlappyBird();
Canvas game = new Canvas();
frame.getContentPane().setBackground(Color.YELLOW);
frame.add(game);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
// while (true) {
// game.moveBall();
// game.gameOver();
// game.moveRect();
// game.repaint();
// Thread.sleep(14);
// }
}
There are two things you can try:
Setting the background color not of the frame's content pane but of game:
//frame.getContentPane().setBackground(Color.YELLOW);
game.setBackground(Color.YELLOW);
Making sure that the frame's background color shows through the game instance by making the latter transparent:
game.setOpaque(false);
Removing the lines related to game, I was able to run this with the expected yellow result. The issue must be within the while loop
while (true) {
game.moveBall();
game.gameOver();
game.moveRect();
game.repaint();
Thread.sleep(14);
}
or
frame.add(game);
Without the FlappyBird class it's impossible to say exactly what is causing the issue, but based on the method names I'd look at repaint().

how to set window size without extending JFrame?

i just started studying gui in java. i am now able to create windows with specific sizes while extending JFrame. however, i came to read posts from here that it is better not to extend JFrame. then i tried to create a window by setting the size in the JPanel instead, but the setSize doesn't seem to work (my code must lack something)
here's my code for my frame
import javax.swing.JFrame;
public class MyFrame{
private JFrame mainFrame;
private MyPanel mainPanel;
public MyFrame(){
mainFrame = new JFrame();
mainPanel = new MyPanel(50, 50);
mainFrame.add(mainPanel);
mainFrame.setVisible(true);
}
}
and here's my code for my panel
import javax.swing.JPanel;
public class MyPanel extends JPanel{
public MyPanel(int i, int j){
setSize(i, j);
}
}
i tried adding frame.pack() in my Frame class, because i thought the frame, not having it's size set, is too small for the panel to be seen -i was wrong
what's lacking in my code?
what's lacking in my code?
A preferred size for the custom component (Panel) for starters. #Override getPreferredSize() to return a logical value.
Then pack() the frame to ensure it is the smallest size needed to display the panel and any other components.
So, something like this:
import javax.swing.*;
public class Application {
private JFrame frame;
private CustomPanel panel;
public Application() {
frame = new JFrame();
// next 2 lines, just a good idea
frame.setLocationByPlatform(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// at 50x50, the title bar on Windows is wider!
panel = new CustomPanel(200, 200);
frame.add(panel);
// make the frame smallest it can be and still show components
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new Application();
}
};
SwingUtilities.invokeLater(r);
}
}
class CustomPanel extends JPanel {
public CustomPanel(int w, int h) {
setPreferredSize(new java.awt.Dimension(w, h));
}
}

Categories

Resources