package data;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JFrame implements Runnable {
private JPanel contentPane;
private JPanel pp = new JPanel();
Thread page = new Thread();
public void run() {
while (!Thread.interrupted()) {
}
}
public Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 640 + 16, 480 + 39);
contentPane = new JPanel();
contentPane.setBounds(0, 0, 640, 480);
contentPane.setLayout(null);
setContentPane(contentPane);
pp.setBounds(0, 0, 640, 480);
pp.setBackground(Color.BLACK);
contentPane.add(pp);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main frame = new Main();
frame.setVisible(true);
frame.setResizable(false);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
The above code works but setResizable causes an issue: http://i.stack.imgur.com/hQxPU.png
If I were to remove the setResizable then the grey at the bottom and right would be black like it's meant to. How can I disable resizing without causing this issue?
You're using an absolute layout (no LayoutManager set), and the black panel has fixed bounds. And that's exactly the reason the black panel won't fill its parent's bounds when the parent is resized.
Solution: use a LayoutManager which automatically recalculates the bounds of your content so it fills the available space.
// BorderLayout is your friend
contentPane.setLayout(new BorderLayout());
...
// delete this line, no need to set fixed bounds
// pp.setBounds(0, 0, 640, 480);
More on how to use layout managers in AWT/Swing:
The Java™ Tutorials - Using Layout Managers
Layout Managers have two purposes:
calculate the min/max/preferred size of a container
layout components by setting their bounds within the container.
If you want the black panel to have a size of 640x480, and the window to be non-resizable, you can set the preferred size and then pack the window, causing its size to become appropriate for the content's preferred dimensions:
pp.setPreferredSize(new Dimension(640, 480));
...
pack();
Related
Full image of my window
The grey border of JFrame visible
Problem:
I want my application to run on full screen (maximized) by default (but the maximum resolution varies by default from laptop to laptop). I am using a background image which scales according to size and width of user's computer on a JPanel.
But with the decorations and the resize features "ON" JPanel isn't completely filling the JFrame.
I wanted my application to:
Allow user to resize it as per use and the image to scale along with it
In the maximized view (by default: setExtendedState(JFrame.MAXIMIZED_BOTH);) the image covers the entire JFrame (Note: Happy with any solution that works on all devices with or without using the JFrame.)
My components if possible get resized too
I am using NetBeans, JFrame is in "absolute layout". I tried with JPanel both on absolute layout as well as BorderLayout (not working), tried pack() (also not working), jPanel1.setSize(WIDTH,HEIGHT) with the dimensions of the screen is also not working. Setting JPanels layout to NULL is also not resolving the issue :(
Sign_Up.java (JFrame)
public class Sign_Up extends javax.swing.JFrame {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
/**
* Creates new form Sign_Up
*/
public Sign_Up() {
initComponents();
Seticon();
btnSave.setEnabled(false);//save button
setExtendedState(JFrame.MAXIMIZED_BOTH);
//setSize(1920,1080);
setLocationRelativeTo(null);//makes aligned at center of screen
//jPanel1.setSize((int)width, (int)height);
//pack();
}
PanelScale.java
public class PanelScale extends JPanel {
Image iconbg;
public PanelScale() {
iconbg = new ImageIcon(getClass( ).getResource("/images/largesignup.png")).getImage( );
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D gd = (Graphics2D)g.create();
gd.drawImage(iconbg, 0, 0, getWidth(), getHeight(), this);
gd.dispose();
}
}
Custom Creation Code in JPanel : new Panel.PanelScale();
The only thing that I found working was explicitly stretching the JPanel over the JFrame to some extra height (in NetBeans) but that resulted in my application window not at the center of the screen but shifted to the right.
Stretching the Jpanel Over JFrame to some more height
But when I try to do that using
setsize(new Dimension(width, height+40));
for the JPanel, it doesn't work.
Also I could have done this using JLabel but I want my image to cover the JFrame to full area while working in maximized or resized view on any device (larger or smaller Laptop like 1920x1080 resolution, 1280x720, etc.)
I would be grateful if any solution is provided, even some alternative way with or without JPanel.
Even if the application is able to work on Full Screen on any device with the image covering it full I will be satisfied, resizing feature can be sacrificed for the time being
Expected
BorderLayout (which is set by default for JFrame) will do exactly what you want automatically, you just then need to resize/position the background based on your needs.
null ("absolute") layouts really aren't a good idea.
Start by taking a look at How to Use BorderLayout. I would also recommend looking at Working with Images and the JavaDocs for Graphics2D which will provide you with the information you need on how to resize the image to your needs
Runnable example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage backgroundImage;
public BackgroundPane() throws IOException {
backgroundImage = ImageIO.read(getClass().getResource("/images/Mando01.jpeg"));
}
#Override
public Dimension getPreferredSize() {
if (backgroundImage == null) {
return new Dimension(400, 400);
}
return new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImage == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
}
}
Instead of using JPanel.setSize(), set the LayoutManager of the JFrame to null. Every time the window size is changed, resize the JPanel with the method JPanel.setBounds(0,0,windowWidth,windowHeight). You may have to call the repaint() method to redraw the components on the screen.
// Create a window with a size of 300x200
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(300, 200);
frame.setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(0, 0, 300, 200);
panel.setBackground(Color.BLACK);
frame.add(panel);
frame.setVisible(true);
// Resize the window to 600x400
frame.setSize(600, 400);
panel.setBounds(0, 0, 600, 400); // Update panel size
panel.repaint(); // Repaint the components
The result of the code is this:
If you remove the last two lines of the code, you'll notice that the size does not change.
I'm trying to draw a normal blue rectangle on to a JFrame, when I press play no window appears at all (with no blue rectangle)
I know that there are tutorials online showing how to draw a rectangle to a JFrame, but I would like to know the problem with the following code and why it does not work.
public class Window extends JFrame {
public Window() {
initialize();
}
private void initialize() {
JFrame frame = new JFrame();
frame.setBounds(100, 100, 600, 600);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.getContentPane().add(new Display());
}
public static void main(String[]args) {
Window window = new Window();
}
}
public class Display extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 100, 100);
}
public void reDraw() {
repaint();
}
}
Overall, I want to know the problems of the code above and how to fix it so that a blue rectangle is drawn on to a window when the program is played.
Thanks for reading : )
Your main issues are:
frame.getContentPane().setLayout(null); - This is generally a bad idea to start with. There are so many issues with this approach that it's difficult to list them all.
null layouts require you take full responsibility for the container's children's locations and sizes. They don't take into consideration different platform rendering systems and traits
You'll find it difficult to accurately size the parent window, as the available content size is the frame size MINIUS the frame borders, so while you're setting the frame to 600x600, the actual available content space is going to be smaller
A component's default size and position is 0x0 - so unless you're willing to take control of this (which is what layout managers do anyway), it will never be displayed (Swing's not dumb, but it is lazy ;))
Not calling setVisible on the JFrame
Not providing a sizing hint for the Display panel
Extending JFrame ... and not making any use of it. Extending JFrame is generally discouraged, but in your case, it's just adding unwanted noise
Work example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {//extends JFrame {
public Test() {
initialize();
}
private void initialize() {
JFrame frame = new JFrame();
//frame.setBounds(100, 100, 600, 600);
//frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.getContentPane().setLayout(null);
frame.getContentPane().add(new Display());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
Test window = new Test();
}
public class Display extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 100, 100);
}
// Not sure what benefit this provides
//public void reDraw() {
// repaint();
//}
}
}
You might want to take a look at Laying Out Components Within a Container to get a better understanding of the layout managers and what they do and how they work (and why you should use them ;))
So I've got a JFrame which uses setLayout(null) so I can position my elements by hand.
However, when accessing the content pane and getting the size for the frame, it says its height is 1.0.
Does anyone know how I can fix this?
Here is the code:
import javax.swing.*;
import java.awt.*;
public class Launcher extends JFrame
{
public Launcher(String title) {
super(title);
setLayout(null);
pack();
setSize(new Dimension(LauncherUtil.LAUNCHER_WIDTH, LauncherUtil.LAUNCHER_HEIGHT));
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
displayComponents();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Launcher launch = new Launcher(LauncherUtil.LAUNCHER_TITLE);
launch.setVisible(true);
}
});
}
private void displayComponents() {
Dimension size = getContentPane().getSize();
JButton launchButton = new JButton("Launch Game");
System.out.println(size.getHeight());
launchButton.setBounds(0, (int)size.getHeight() - 60, (int)size.getWidth(), 60);
add(launchButton);
}
}
may be if you try to get the screen size by using Toolkit would be work like you want
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
it brings you the screen size where java program is running. Hope it helps.
The content pane is a JPanel whose default size is 1x1px. Since you did not put any components into the content pane and have not set a preferred size for the panel, the content pane's size remains 1x1px.
One way to fix this is to call these three methods in the following order:
setLayout(null);
setPreferredSize(new Dimension(300, 400));
pack();
However, you should be using a layout manager instead of managing
the size and position of your components by hand.
So I've made a class WindowDisp which extends JFrame:
public class WindowDisp extends JFrame{
private static final long serialVersionUID = 3245091489595286109L;
private int height, width;
private JPanel panel;
private JLabel mainPane;
public WindowDisp(int a, int b, int pw, int ph){
height = a;
width = b;
Container c = getContentPane();
c.setPreferredSize(new Dimension(width, height));
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
mainPane = new JLabel();
mainPane.setPreferredSize(new Dimension(pw, ph));
mainPane.setFont(new Font("Monospaced", Font.PLAIN, 10));
panel = new JPanel();
panel.setPreferredSize(getSize());
panel.add(mainPane);
add(panel);
setVisible(true);
pack();
}
public static void main(String[] args){
WindowDisp win = new WindowDisp(400, 400, 400, 400);
}
}
From my Main class, I declare a WindowDisp where its height and width are equal to its ph and pw. The problem, however, is that, upon running my program, white 'bars' appear around the default background colored JPanel in the frame. They appear to be padding the panel from the right and the bottom, as though there is space in the frame that the panel is not occupying, although, if my coding is correct, the panel should be the same size as the frame's ContentPane, should it not?
I've found that removing either of the two pack(); commands does not remove these bars, although removing the first one changes them to black, and removing the second widens the one on the right. Of course, removing both of them causes the frame not to be the same size as its ContentPane. Furthermore, removing the add(panel); altogether has no effect.
I can't figure out what in this code is causing that seemingly empty space to appear in my frame, and, again, in my program, all four values being passed to the Window constructor are equal. What seems really strange is that, even if I just remove the add(panel);, nothing at all changes visa vi the white padding. In fact, I can comment out everything from mainPane =... to add(panel); and that doesn't affect it at all.
I can't seem to replicate the issue exactly, but I think I can replicate the desired results...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class WindowDisp extends JFrame {
private static final long serialVersionUID = 3245091489595286109L;
private JPanel panel;
private JLabel mainPane;
public WindowDisp(int width, int height) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
mainPane = new JLabel();
mainPane.setBorder(new LineBorder(Color.BLUE));
mainPane.setFont(new Font("Monospaced", Font.PLAIN, 10));
panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
};
panel.setLayout(new BorderLayout());
panel.setBorder(new EmptyBorder(4, 4, 4, 4));
panel.add(mainPane);
add(panel);
pack();
setLocationRelativeTo(null);
setVisible(true);
System.out.println(getSize());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
WindowDisp win = new WindowDisp(400, 400);
}
});
}
}
Things that jump out at me (as been of issue)...
panel.setPreferredSize(getSize()); - The size of the window is generally larger than the window size, this is because the window has decorations which are painted WITHIN the frame boundaries. pack uses the layout information (and preferredSize of the components indirectly) to ensure that the content has the amount of space that it asks for, it then sizes the window around this to accommodate the frame decorations. By calling getContentPane().setPreferredSize you are superseding any information that the layout manager might provide and ignoring the requirements of the other components. This is one of the (many) reasons why we recommend that you NEVER call setPreferredSize, ever...
To reiterate...
Container c = getContentPane();
c.setPreferredSize(new Dimension(width, height));
Forces the viewable space of the window to be set to the width/height values (400x400). This container will no longer be able to react to changes to it's content and will ALWAYS prefer to be 400x400
mainPane.setPreferredSize(new Dimension(pw, ph));
Sets the preferred size of the mainPane to 400x400 (based on your example). Again, it will ALWAYS prefer to be 400x400, but the simple fact of setting the content pane, means that this value is actually ignored...
panel.setPreferredSize(getSize());
Now, the nail in the coffin. This sets the panel to be the same size of the frame, BUT, the frame is larger than the contentPane (400x400 + frame decorations), it is also offset within frame (it won't be positioned at 0x0, but will be offset so that it appears below the frame's title and right border), but could expand beyond the frames boundaries
This combination of issues are all working against you. Instead of worrying about the frame size, worry about the size needs/requirements of the what the frame displays.
Each OS uses different frame decorations, so the actual, physical, frame size will be different on different OSs, but if you focus on the requirements of the content, you won't care
See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? (Yes.)
Instead use layout padding and borders for white space. Finally, call pack() to ensure the frame is exactly as large as (the smallest size) it needs to be in order to display the components and white space.
import java.awt.Font;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class WindowDisp extends JFrame {
private JPanel panel;
private JLabel mainLabel;
public WindowDisp(int t, int l, int b, int r, String title) {
super(title);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setResizable(false);
setLocationByPlatform(true);
mainLabel = new JLabel("Hello Padding!");
mainLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 10));
mainLabel.setBorder(new EmptyBorder(t, l, b, r));
panel = new JPanel();
panel.add(mainLabel);
add(panel);
pack();
setVisible(true);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new WindowDisp(50, 150, 50, 150, "Window 1");
new WindowDisp(50, 100, 50, 100, "Window 2");
}
};
SwingUtilities.invokeLater(r);
}
}
So far the best patch for this annoying issue is the following. Doesn't matter where you call the setResizable(false) method. Just add this piece of code after you setVisible(true).
private void sizeBugPatch() {
while (frame.getWidth() > yourWidth) {
frame.pack();
}
}
Where yourWidth is the width you've set in any of the possible ways, either manually or by overriding setPreferredSize methods. The explanation is quite easy, frame.pack() seems to reset frame.setResizable(boolean b) somehow. You could use an if instead of the while loop but I prefer while to exclude the case the window would still be extra-sized even after a second pack().
One thing I have learned from swing days is to never mix setPreferred... with pack(). You either use one or the other.
Try this code:
import javax.swing.*;
import java.awt.*;
public class WindowDisp extends JFrame {
private int height, width;
private JPanel panel;
private JLabel mainPane;
public WindowDisp(int a, int b, int pw, int ph){
height = a;
width = b;
Container c = getContentPane();
// c.setPreferredSize(new Dimension(width, height));
mainPane = new JLabel("Hello from Pane");
mainPane.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 10));
panel = new JPanel();
// panel.setPreferredSize(new Dimension(pw, ph));
panel.add(mainPane);
c.add(panel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
public static void main(String[] args){
WindowDisp win = new WindowDisp(400, 400, 400, 400);
}
}
Output:
This is my code:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame();
JPanel jp = new JPanel();
jp.setMinimumSize(new Dimension(200, 200));
jp.setPreferredSize(new Dimension(200, 200));
//frame.getContentPane().setMinimumSize(new Dimension(200, 200));
//frame.getContentPane().setPreferredSize(new Dimension(200, 200));
frame.getContentPane().add(jp);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
It behaves exactly the way I want. User can resize the JFrame but it'll always be large enough to hold 200px x 200px JPanel. But when I remove:
JFrame.setDefaultLookAndFeelDecorated(true);
user can resize JFrame to any size.
Why does default look and feel decoration affect resizing? How can i make it work without setDefaultLookAndFeelDecorated(true)? I know I can set frames minimum size manually (JFrame#setMinimumSize(new Dimension dim)) and I will if there is no smarter solution.
I'm using jdk 1.7 on Windows 7.
This use to be a bug, the page speaks of work arounds like:
override setSize() and check if the new size is less than the desired
inside paint(Graphics g) of JFrame check height and width and "re-create" frame to new minimum size
however a person claims it to be fixed as the original example issued for the bug proposal omitted the call to setMinimumSize(...), this is needed because JFrame does not enforce minimum size
Here is the snippet which shows that persons' code:
import java.awt.Dimension;
import javax.swing.*;
public class JavaApplication118 {
private final Dimension m_dim = new Dimension(200, 150);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication118().createAndShowUI();
}
});
}
private void createAndShowUI() {
// JFrame.setDefaultLookAndFeelDecorated(true);
final JFrame frame = new JFrame("Test") {
#Override
public Dimension getMinimumSize() {
return m_dim;
}
};
frame.setMinimumSize(m_dim);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
// frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(JFrame frame) {
JPanel jp = new JPanel();
jp.setMinimumSize(new Dimension(200, 200));
jp.setPreferredSize(new Dimension(400, 400));//for testing
frame.getContentPane().add(jp);
}
}
EDIT
The snippet overrode getMinimumSize() though this seems redundant after calling setMinimumSize(..), I kept it included as that's how I found the snippet (I did remove the overridden getPreferredSize() method of the JFrame which the snippet included).
Why does default look and feel decoration affect resizing?
Because then the window sizing is under the complete control of the LAF while dragging: The mouseHandler installed by (f.i.) MetalRootPaneUI doesn't resize the window below the min returned by the LayoutManager. Without setting the frame's minimumSize, you can still decrease its size programatically.
The only way (unfortunately) to enforce a window's minimum size always is to manually set it. Unfortunate, as that implies keeping track of dynamic changes of that minimum and update it as appropriate.
A snippet to play with (un/comment the defaultDecoration and frame min setting)
JFrame.setDefaultLookAndFeelDecorated(true);
JPanel panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
Dimension m = getMinimumSize();
// visualize the min
g.drawRect(0, 0, m.width - 1, m.height -1);
}
};
// BEWARE: for demonstration only, NEVER do in production code
panel.setMinimumSize(new Dimension(400, 400));
panel.setPreferredSize(panel.getMinimumSize());
final JXFrame frame = new JXFrame("", true);
Action action = new AbstractAction("resize") {
#Override
public void actionPerformed(ActionEvent e) {
frame.setSize(300, 300);
LOG.info("succeeded? " + frame.getSize());
}
};
panel.add(new JButton(action));
frame.add(panel);
frame.pack();
// set minimum is required to enforce the minimum
frame.setMinimumSize(frame.getMinimumSize());
Update
Looking at the Window source, turns out that you can have auto-magic dynamic respect of min size by overriding isMinimumSizeSet and returning true uncondinionally:
final JXFrame frame = new JXFrame("", true) {
#Override
public boolean isMinimumSizeSet() {
return true;
}
};
...
// no longer needed
// frame.setMinimumSize(frame.getMinimumSize());
not tested for side-effects, though