Resizing JPanel when JFrame is maximized - java

Alright, so the following code shows a JPanel within a JFrame when the program is first run. If the window is re-sized by dragging one of the sides or corners of the frame, the JPanel re-sizes itself and maintains the aspect ratio of the monitor.
NOTE: The JPanel is set to remain within the bounds of the window on a 1920x1080 resolution monitor only. On any other monitor size, the JPanel may get cut off. See my comment above setPreferredSize() in the updatePanelSize() method.
public class Frame extends JFrame {
Panel panel = new Panel();
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Frame();
}
});
}
// Setup the window, add the panel, and initialize a "window" listener.
public Frame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1280, 720);
setLocationRelativeTo(null);
setVisible(true);
setTitle("Frame");
setLayout(new GridBagLayout());
add(panel);
initListeners();
}
public void initListeners() {
/** When the window is resized, the panel size is updated. */
addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent e) {
panel.updatePanelSize();
}
#Override
public void componentHidden(ComponentEvent evt) {}
#Override
public void componentShown(ComponentEvent evt) {}
#Override
public void componentMoved(ComponentEvent evt) {}
});
}
}
public class Panel extends JPanel {
public Panel() {
setBackground(new Color(100, 0, 0));
setPreferredSize(new Dimension(1052, 592));
}
// Resizes the JPanel while maintaining the same aspect ratio
// of the monitor.
public void updatePanelSize() {
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
float monitorWidth = gd.getDisplayMode().getWidth();
float monitorHeight = gd.getDisplayMode().getHeight();
// Aspect ratio of the monitor in decimal form.
float monitorRatio = monitorWidth / monitorHeight;
JComponent parent = (JComponent) getParent();
float width = parent.getWidth();
float height = parent.getHeight();
width = Math.min(width, height * monitorRatio);
height = width / monitorRatio;
// I am subtracting the width and height by their respected aspect ratio
// coefficients (1920x1080 -> 16:9 (width:height)) and multiplying them
// by some scale (in this case 10) to add a "padding" to the JPanel.
// The ratio coefficients and scale will need to be edited based upon the
// resolution of your monitor.
setPreferredSize(new Dimension((int)width - (16 * 10), (int)height - (9 * 10)));
System.out.println("PanelRes: " + ((int)width - (16 * 10)) + "x" + ((int)height - (9 * 10)));
System.out.println("PanelRatio: " + getWidth() / getHeight());
}
}
The problem I am having is that if I maximize the window by double clicking the window toolbar (or whatever the correct term for the top of the window would be) or by clicking the maximize button, the JPanel does not re-size like it ought to. The Overridden componentResized() method is called when the window is maximized, but the JPanel doesn't resize. Any help on solving this issue would be great.

On resize the panel is immediately accepting the new preferred dimensions in updatePanelSize(), but on maximize/restore the panel is apparently ignoring the new preferred dimensions.
I've added a call to revalidate(), to force the panel to update in those cases where it hasn't applied the new preferred dimensions.
public void updatePanelSize() {
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice();
float monitorWidth = gd.getDisplayMode().getWidth();
float monitorHeight = gd.getDisplayMode().getHeight();
// Aspect ratio of the monitor in decimal form.
float monitorRatio = monitorWidth / monitorHeight;
JComponent parent = (JComponent) getParent();
float width = parent.getWidth();
float height = parent.getHeight();
width = Math.min(width, height * monitorRatio);
height = width / monitorRatio;
// I am subtracting the width and height by their respective aspect ratio...
int paddedWidth = (int) width - (16 * 10);
int paddedHeight = (int) height - (9 * 10);
setPreferredSize(new Dimension(paddedWidth, paddedHeight));
int resultWidth = getWidth();
int resultHeight = getHeight();
if (paddedWidth != resultWidth && paddedHeight != resultHeight) {
revalidate(); // preferred dimensions not applied, so force them
}
System.out.println("PreferredSize: " + paddedWidth + "x" + paddedHeight);
System.out.println("PanelRes: " + resultWidth + "x" + resultHeight);
System.out.println("PanelRatio: " + (float)resultWidth / resultHeight);
}

Related

Java after adding background, why program will be slower?

So if I add a background picture, then I click the button lots of times, my program will be slower and slower. But if I don't add that background picture, it won't get slower. Can anyone tell me why? Thanks!
here is my JFrame class:
public class test extends JFrame implements ActionListener {
private Container contentPane;
public test() throws FileNotFoundException {
// set the position of the GUI related with screen size
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
this.setBounds((int) width / 4, (int) height / 4, (int) width / 2, (int) height / 2);
//set background
ImageIcon img = new ImageIcon("background.jpeg");
// get the container
contentPane = this.getContentPane();
//contentPane.setLayout(new GridLayout(3, 1));
/*
*background panel
*/
JPanel backgroundPanel = new JPanel(){
{
this.setOpaque(false);
}
public void paintComponent(Graphics g) {
img.setImage(img.getImage().getScaledInstance(this.getWidth(), this.getHeight(), Image.SCALE_AREA_AVERAGING));
g.drawImage(img.getImage(), 0, 0, this);
super.paintComponent(g);
}
};
contentPane.add(backgroundPanel);
backgroundPanel.setLayout(new GridLayout(3, 1));
/*
* second area
*/
JPanel secondPanel = new JPanel();
secondPanel.setOpaque(false);
// display button
makeButton(secondPanel, "Display", this);
backgroundPanel.add(secondPanel);
}
private void makeButton(JPanel p, String name, ActionListener target) {
JButton b = new JButton(name);
b.setFont(new Font(null, Font.PLAIN, 20));
// add it to the specified JPanel and button group and make the JPanel listen
p.add(b);
b.addActionListener(target);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String command = e.getActionCommand();
// Load button
// Display button
if (command.equals("Display")) {
// check is there any document has been loaded
// pop-up window
JOptionPane.showMessageDialog(null, "Please load a document first!", "Error",JOptionPane.PLAIN_MESSAGE);
}
// show states button
}
}
here is the main method:
public class DocumentViewer {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
JFrame frm = new test();
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
}
}
Here:
public void paintComponent(Graphics g) {
img.setImage(img.getImage().getScaledInstance(this.getWidth(), this.getHeight(), Image.SCALE_AREA_AVERAGING));
g.drawImage(img.getImage(), 0, 0, this);
super.paintComponent(g);
}
You're doing resource-hungry calculations within a painting method, a method that contributes greatly to user-perceived program responsiveness. Don't do this. Scale the image once, and store it in a variable, and then only draw the image within the paintComponent method.
If you need the image to resize with the GUI, then do the resizing within a ComponentListener, and again not within a painting method.

Aren't Graphics/JPanel dimensions measured in pixels?

When I draw [drawRect(x, y, width, height)] a rectangle on an JPanel inside a JFrame, that has a width of e.g. 500, it is actually wider than 500 Pixels on my Screen. How is this measured?
Whilst messing around with a drawing Rectangles on an JPanel and the size of the JFrame around this, i recognized, that 500 "width" are different things, when it comes to JFrame and JPanel.
A JFrame that is created with a width of 1920 Pixels is exactly 1920 Pixels wide, means, as wide as my screen (1920x1080).
If i draw a rectangle with a width of 1920 on a JPanel, that is inside the JFrame, it extends my screen by exactly 385 Pixels. Respectively: a drawn rectangle as wide as my screen needs a width of 1535.
import javax.swing.*;
import java.awt.*
public class Main {
public static void main(String[] args){
JFrame window = new JFrame();
window.setSize(1920,1080); //Window as wide as the screen
window.add(new Canvas());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
public class Canvas extends JPanel {
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawRect(0, 0, 1920, 500); //Paints a rectangle on the JPanel
}
}
The window that opens is exactly as wide as my screen, but the rectangle inside extends it.
If I change the width of the rectangle to 1535 [drawRect(0, 0, 1535, 500)], it is as wide as the JFrame/screen. Why is that?
Edit: Since the Windows 10 Frame has no decorations at the side, just the standard menu-bar on top, I don't think this is the problem (as far as I understand decorations).
The short answer: Yes they are.
The explanation: Let us look deeper!
Running Java Swing on MacOS (tested with Metal LAF), the JFrame has insets of zero for left and right. This is similar to rendering for certain themes on Windows 10. I have included code below; the gap between the content pane and the panel's fill rectangle should remain 8 pixels. When the program is running, resize it, and check for yourself. Feel free to comment if this is not the behaviour you experience.
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
final String name;
name = javax.swing.plaf.metal.MetalLookAndFeel.class.getName();
try {
UIManager.setLookAndFeel(name);
}
catch (Throwable e) {
e.printStackTrace();
}
createAndShowWindow();
});
}
private static void createAndShowWindow() {
final int width = 1920;
final int height = 800;
final int padding = 8;
JFrame window = new JFrame();
window.setTitle("Hello World.");
window.setPreferredSize(new Dimension(width, height));
window.setSize(width, height); //Window as wide as the screen
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Canvas canvas = new Canvas(padding);
window.add(canvas, BorderLayout.CENTER);
window.pack();
window.setVisible(true);
System.out.println("w: " + window.getSize());
System.out.println("c: " + window.getContentPane().getSize());
System.out.println("p: " + canvas.getSize());
System.out.println("i: " + window.getInsets());
}
public static class Canvas extends JPanel {
private final int padding;
public Canvas(int padding) {
this.padding = padding;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(180, 120, 16));
//Paints a rectangle on the JPanel
int x = padding;
int y = padding;
int w = getWidth() - 2 * padding;
int h = getHeight() - 2 * padding;
g.fillRect(x, y, w, h);
}
}

Why is my Component repainted over and over without any changes happening?

I have a beginner Swing/AWT question for you.
I am doing custom painting of a BoxPanel Object that extends JPanel.
I have n of these BoxPanels that are then drawn in a JFrame called FormSolutionViewer using a FlowLayout.
Now the issue I am having is that after the JFrame is created and made visible, it is repainted in an infinite loop, without any changes happening to the components. Can someone explain to me why this is and how to fix it so that it only gets repainted when the window is resized or some of the data actually changes?
public class BoxPanel extends JPanel {
private Box box;
private int scaleFactor;
public BoxPanel(Box box, int scaleFactor) {
super();
this.box = box;
this.scaleFactor = scaleFactor;
this.setLayout(null); // Use null layout for absolute positioning
}
/**
* Need to override getPreferredSize() when using a FlowLayout
*/
#Override
public Dimension getPreferredSize() {
return new Dimension(this.box.getLength() * this.scaleFactor, this.box.getLength() * this.scaleFactor);
}
/**
* Paint the box border, background and its rectangles
* #param g
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.white);
// Display no. of rectangles contained in tooltip
this.setToolTipText("Box contains " + this.box.getRectangles().size() + " rectangles");
// Draw border of box
this.setBorder(BorderFactory.createLineBorder(Color.black));
/* Draw rectangles contained in box */
int i = 1;
for (Rectangle rect : box.getRectangles()) {
System.out.println("Rectangle " + i + ": " + rect.toString());
g.setColor(Color.BLACK); // Set color for border
g.drawRect(rect.getPos().getX() * this.scaleFactor, rect.getPos().getY() * this.scaleFactor,
rect.getWidth() * this.scaleFactor, rect.getHeight() * this.scaleFactor);
i++;
}
}
}
public class FormSolutionViewer extends JFrame {
private JPanel contentPane;
private FeasibleSolution solution;
int scaleFactor = 40;
int spacing = 5;
/**
* Create the frame.
*/
public FormSolutionViewer(FeasibleSolution solution, int x, int y, int dpi) {
this.solution = solution;
this.scaleFactor = (int) Math.round(dpi / 2.4);
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
setBounds(x, y, 800, 600);
setTitle("Initialized Solution of " + solution.getInstance().toString());
this.setBackground(new Color(250, 250, 250));
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(spacing, spacing, spacing, spacing));
FlowLayout layout = new FlowLayout(FlowLayout.LEADING, 5, 5);
contentPane.setLayout(layout);
this.setContentPane(contentPane);
/* Place the boxes */
int boxNo = 0;
int rowCount = 0;
for (Box box : solution.getBoxes()) {
boxNo++;
BoxPanel boxPanel = new BoxPanel(box, scaleFactor);
contentPane.add(boxPanel);
contentPane.setSize(this.getWidth(), 500);
boxPanel.setVisible(true);
}
}
}
this.setBackground(Color.white);
...
this.setToolTipText("Box contains " + this.box.getRectangles().size() + " rectangles");
...
this.setBorder(BorderFactory.createLineBorder(Color.black));
Don't set a property of the component in the painting method. When a property of a component is changed, Swing invokes revalidate()/repaint() on the component to reflect the new state of the component.
The point of a painting method is to paint the component in its current state, not change its state.

Java How to redraw JPanel (re-create object)?

I have a problem that, I need to only redraw/rebuild the drawing area if the "c" key is pressed.
The way I'm doing using repaint(), turns out to be causing the draw area to be of position.
I also notice that, whenever I re-size the frame, the keylistener is no longer working.
Problems:
unable to repaint correctly.
keylistener is not working after frame is re-sized.
Love to attach the display, but seems like it is blocked because I am newbie.
The following code is the main function that call the class "newZone".
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e){
System.out.println("component Rebuild");
frame.getContentPane().removeAll();
frame.getContentPane().invalidate();
JComponent newContentPane = new newZone(frame.getSize());
newContentPane.setOpaque(true);
frame.getContentPane().add(newContentPane);
frame.getContentPane().revalidate();
frame.setContentPane(newContentPane);
}
});
The following is the class of newZone, which contains Paint & keylistener:
public class newZone extends JComponent implements MouseListener, MouseMotionListener, KeyListener {
JPanel panel1;
JTextArea textArea;
JScrollPane scrollPane;
MyDrawingTool Drawing;
static int firsttimer = 0;
static int preposX = 0;
static int preposY = 0;
static int widthPercentage = 80 , heightPercentage = 93;
static int numberOfYboxes,numberOfXboxes;
static Dimension currentPanelSize;
static final String NEWLINE = System.getProperty("line.separator");
static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public newZone(Dimension currentPanelSize1) {
currentPanelSize = currentPanelSize1;
Drawing = new MyDrawingTool();
Drawing.setBackground(Color.WHITE);
Drawing.setBounds( 10, 10,
(int) currentPanelSize.getWidth()*(widthPercentage)/100,
(int) currentPanelSize.getHeight()*(heightPercentage)/100 );
Drawing.setPreferredSize(new Dimension( (int) currentPanelSize.getWidth()*(widthPercentage)/100,
(int) currentPanelSize.getHeight()*(heightPercentage)/100));
Drawing.addMouseListener(this);
Drawing.addMouseMotionListener(this);
add(Drawing);
addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e){
System.out.println( "Key type: "+e.getKeyChar());
if(e.getKeyChar() == 'c'){
Drawing.redraw();
}
}
});
setFocusable(true);
}
class MyDrawingTool extends JPanel{
void redraw(){
repaint();
}
#Override
public void paint(Graphics q){
//super.paint(q);
int j,k, width, height;
int startX = 10, startY = 10;
int boxSize = 50;
width = (int)currentPanelSize.getWidth()*(widthPercentage)/100;
height = (int)currentPanelSize.getHeight()*(heightPercentage)/100;
numberOfYboxes = (height-20)/50;
numberOfXboxes = (width-20)/50;
for ( j = 0; j < numberOfYboxes; j++)
{
startX = 10;
for ( k = 0; k < numberOfXboxes; k++)
{
q.setColor(Color.WHITE);
q.fillRect(startX, startY, boxSize, boxSize);
q.setColor(Color.BLUE); //Set line color
q.drawRect(startX, startY, boxSize, boxSize);
startX+=boxSize;
}
startY+=boxSize;
}
}
}
}
I don't know why you are using a ComponentListener. I don't see any reason to remove/add/invalidate/revalidat and do all the other stuff.
All you need to do is add the panel to the CENTER of a content pane of the frame. The panel will automatically increase/decrease in size as the frame resizes. There is no need for the ComponentListener.
Custom painting should be done in the paintComponent() method and don't forget to invoke super.paintComponent(...) at the start.
The KeyListener doesn't work because focus is now on the JFrame (not the panel) after you resize the frame. You should NOT be using a KeyListener for this. Instead you should be Key Bindings which work even when the panel doesn't have focus.
It seems, you do not need to switch content pane at all.
If you use some layout on default content pane, as #camickr suggested, you won't need to handle resize and other stuff manually.
Good luck there.

How to center a Window in Java?

What's the easiest way to centre a java.awt.Window, such as a JFrame or a JDialog?
From this link
If you are using Java 1.4 or newer,
you can use the simple method
setLocationRelativeTo(null) on the
dialog box, frame, or window to center
it.
This should work in all versions of Java
public static void centreWindow(Window frame) {
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
setLocationRelativeTo(null) should be called after you either use setSize(x,y), or use pack().
Note that both the setLocationRelativeTo(null) and Tookit.getDefaultToolkit().getScreenSize() techniques work only for the primary monitor. If you are in a multi-monitor environment, you may need to get information about the specific monitor the window is on before doing this kind of calculation.
Sometimes important, sometimes not...
See GraphicsEnvironment javadocs for more info on how to get this.
On Linux the code
setLocationRelativeTo(null)
Put my window to random location each time I launched it, in a multi display environment.
And the code
setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - getSize().width) / 2, (Toolkit.getDefaultToolkit().getScreenSize().height - getSize().height) / 2);
"cut" the window in half with placing it to the exact center, which is between my two displays.
I used the following method to center it:
private void setWindowPosition(JFrame window, int screen)
{
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] allDevices = env.getScreenDevices();
int topLeftX, topLeftY, screenX, screenY, windowPosX, windowPosY;
if (screen < allDevices.length && screen > -1)
{
topLeftX = allDevices[screen].getDefaultConfiguration().getBounds().x;
topLeftY = allDevices[screen].getDefaultConfiguration().getBounds().y;
screenX = allDevices[screen].getDefaultConfiguration().getBounds().width;
screenY = allDevices[screen].getDefaultConfiguration().getBounds().height;
}
else
{
topLeftX = allDevices[0].getDefaultConfiguration().getBounds().x;
topLeftY = allDevices[0].getDefaultConfiguration().getBounds().y;
screenX = allDevices[0].getDefaultConfiguration().getBounds().width;
screenY = allDevices[0].getDefaultConfiguration().getBounds().height;
}
windowPosX = ((screenX - window.getWidth()) / 2) + topLeftX;
windowPosY = ((screenY - window.getHeight()) / 2) + topLeftY;
window.setLocation(windowPosX, windowPosY);
}
Makes the window appear right at the center of the first display.
This is probably not the easiest solution.
Works properly on Linux, Windows and Mac.
I finally got this bunch of codes to work in NetBeans using Swing GUI Forms in order to center main jFrame:
package my.SampleUIdemo;
import java.awt.*;
public class classSampleUIdemo extends javax.swing.JFrame {
///
public classSampleUIdemo() {
initComponents();
CenteredFrame(this); // <--- Here ya go.
}
// ...
// void main() and other public method declarations here...
/// modular approach
public void CenteredFrame(javax.swing.JFrame objFrame){
Dimension objDimension = Toolkit.getDefaultToolkit().getScreenSize();
int iCoordX = (objDimension.width - objFrame.getWidth()) / 2;
int iCoordY = (objDimension.height - objFrame.getHeight()) / 2;
objFrame.setLocation(iCoordX, iCoordY);
}
}
OR
package my.SampleUIdemo;
import java.awt.*;
public class classSampleUIdemo extends javax.swing.JFrame {
///
public classSampleUIdemo() {
initComponents();
//------>> Insert your code here to center main jFrame.
Dimension objDimension = Toolkit.getDefaultToolkit().getScreenSize();
int iCoordX = (objDimension.width - this.getWidth()) / 2;
int iCoordY = (objDimension.height - this.getHeight()) / 2;
this.setLocation(iCoordX, iCoordY);
//------>>
}
// ...
// void main() and other public method declarations here...
}
OR
package my.SampleUIdemo;
import java.awt.*;
public class classSampleUIdemo extends javax.swing.JFrame {
///
public classSampleUIdemo() {
initComponents();
this.setLocationRelativeTo(null); // <<--- plain and simple
}
// ...
// void main() and other public method declarations here...
}
below is code for displaying a frame at top-centre of existing window.
public class SwingContainerDemo {
private JFrame mainFrame;
private JPanel controlPanel;
private JLabel msglabel;
Frame.setLayout(new FlowLayout());
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
//headerLabel = new JLabel("", JLabel.CENTER);
/* statusLabel = new JLabel("",JLabel.CENTER);
statusLabel.setSize(350,100);
*/ msglabel = new JLabel("Welcome to TutorialsPoint SWING Tutorial.", JLabel.CENTER);
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
//mainFrame.add(headerLabel);
mainFrame.add(controlPanel);
// mainFrame.add(statusLabel);
mainFrame.setUndecorated(true);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
mainFrame.setVisible(true);
centreWindow(mainFrame);
}
public static void centreWindow(Window frame) {
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, 0);
}
public void showJFrameDemo(){
/* headerLabel.setText("Container in action: JFrame"); */
final JFrame frame = new JFrame();
frame.setSize(300, 300);
frame.setLayout(new FlowLayout());
frame.add(msglabel);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
frame.dispose();
}
});
JButton okButton = new JButton("Capture");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// statusLabel.setText("A Frame shown to the user.");
// frame.setVisible(true);
mainFrame.setState(Frame.ICONIFIED);
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ScreenCaptureRectangle(screen);
}
});
mainFrame.setState(Frame.NORMAL);
}
});
controlPanel.add(okButton);
mainFrame.setVisible(true);
}
public static void main(String[] args) throws Exception {
new SwingContainerDemo().showJFrameDemo();
}
Below is the ouput of above code-snippet:
The following doesn't work for JDK 1.7.0.07:
frame.setLocationRelativeTo(null);
It puts the top left corner at the center - not the same as centering the window. The other one doesn't work either, involving frame.getSize() and dimension.getSize():
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
The getSize() method is inherited from the Component class, and therefore frame.getSize returns the size of the window as well. Thus subtracting half the vertical and horizontal dimensions from the vertical and horizontal dimensions, to find the x,y coordinates of where to place the top-left corner, gives you the location of the center point, which ends up centering the window as well. However, the first line of the above code is useful, "Dimension...". Just do this to center it:
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
JLabel emptyLabel = new JLabel("");
emptyLabel.setPreferredSize(new Dimension( (int)dimension.getWidth() / 2, (int)dimension.getHeight()/2 ));
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
frame.setLocation((int)dimension.getWidth()/4, (int)dimension.getHeight()/4);
The JLabel sets the screen-size. It's in FrameDemo.java available on the java tutorials at the Oracle/Sun site. I set it to half the screen size's height/width. Then, I centered it by placing the top left at 1/4 of the screen size's dimension from the left, and 1/4 of the screen size's dimension from the top. You can use a similar concept.
frame.setLocationRelativeTo(null);
Full example:
public class BorderLayoutPanel {
private JFrame mainFrame;
private JButton btnLeft, btnRight, btnTop, btnBottom, btnCenter;
public BorderLayoutPanel() {
mainFrame = new JFrame("Border Layout Example");
btnLeft = new JButton("LEFT");
btnRight = new JButton("RIGHT");
btnTop = new JButton("TOP");
btnBottom = new JButton("BOTTOM");
btnCenter = new JButton("CENTER");
}
public void SetLayout() {
mainFrame.add(btnTop, BorderLayout.NORTH);
mainFrame.add(btnBottom, BorderLayout.SOUTH);
mainFrame.add(btnLeft, BorderLayout.EAST);
mainFrame.add(btnRight, BorderLayout.WEST);
mainFrame.add(btnCenter, BorderLayout.CENTER);
// mainFrame.setSize(200, 200);
// or
mainFrame.pack();
mainFrame.setVisible(true);
//take up the default look and feel specified by windows themes
mainFrame.setDefaultLookAndFeelDecorated(true);
//make the window startup position be centered
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(mainFrame.EXIT_ON_CLOSE);
}
}
There's something really simple that you might be overlooking after trying to center the window using either setLocationRelativeTo(null) or setLocation(x,y) and it ends up being a little off center.
Make sure that you use either one of these methods after calling pack() because the you'll end up using the dimensions of the window itself to calculate where to place it on screen. Until pack() is called, the dimensions aren't what you'd think thus throwing off the calculations to center the window. Hope this helps.
Example: Inside myWindow() on line 3 is the code you need to set the window in the center of the screen.
JFrame window;
public myWindow() {
window = new JFrame();
window.setSize(1200,800);
window.setLocationRelativeTo(null); // this line set the window in the center of thr screen
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().setBackground(Color.BLACK);
window.setLayout(null); // disable the default layout to use custom one.
window.setVisible(true); // to show the window on the screen.
}
The following code center the Window in the center of the current monitor (ie where the mouse pointer is located).
public static final void centerWindow(final Window window) {
GraphicsDevice screen = MouseInfo.getPointerInfo().getDevice();
Rectangle r = screen.getDefaultConfiguration().getBounds();
int x = (r.width - window.getWidth()) / 2 + r.x;
int y = (r.height - window.getHeight()) / 2 + r.y;
window.setLocation(x, y);
}
You could try this also.
Frame frame = new Frame("Centered Frame");
Dimension dimemsion = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dimemsion.width/2-frame.getSize().width/2, dimemsion.height/2-frame.getSize().height/2);
Actually frame.getHeight() and getwidth() doesnt return values , check it by System.out.println(frame.getHeight()); directly put the values for width and height ,then it will work fine in center. eg: as below
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x=(int)((dimension.getWidth() - 450)/2);
int y=(int)((dimension.getHeight() - 450)/2);
jf.setLocation(x, y);
both 450 is my frame width n height
public class SwingExample implements Runnable {
#Override
public void run() {
// Create the window
final JFrame f = new JFrame("Hello, World!");
SwingExample.centerWindow(f);
f.setPreferredSize(new Dimension(500, 250));
f.setMaximumSize(new Dimension(10000, 200));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void centerWindow(JFrame frame) {
Insets insets = frame.getInsets();
frame.setSize(new Dimension(insets.left + insets.right + 500, insets.top + insets.bottom + 250));
frame.setVisible(true);
frame.setResizable(false);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
The order of the calls is important:
first -
pack();
second -
setLocationRelativeTo(null);
In addition to Donal's answer, I would like to add a small calculation that makes sure that the Java window is perfectly at the center of the window. Not just the "TOP LEFT" of the window is at the center of the window.
public static void centreWindow(JFrame frame, int width, int height) {
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
// calculate perfect center
int perf_x = (int) x - width/2;
int perf_y = (int) y - height/2;
frame.setLocation(perf_x, perf_y);
}
If you want a simple answer for Java NetBeans:
Right click on the JFrame, go to properties, then go to code and select generate center option.
Look image for reference:
[1]: https://i.stack.imgur.com/RFXbL.png
If you want to push center of your app window, you can do solved to follow.
int x = (Toolkit.getDefaultToolkit().getScreenSize().width) - getSize().width) / 2;
int y = (Toolkit.getDefaultToolkit().getScreenSize().height) - getSize().height) / 2;
setLocation(x,y);
getSize() function is app frame size...
getScreenSize() is your pc screen size.
I'd like to modify Dónal's answer to accommodate a multiple display setup:
public static void centerWindow(Window frame) {
Rectangle bounds = frame.getGraphicsConfiguration().getBounds();
Dimension dimension = bounds.getSize();
int x = (int) (((dimension.getWidth() - frame.getWidth()) / 2) + bounds.getMinX());
int y = (int) (((dimension.getHeight() - frame.getHeight()) / 2) + bounds.getMinY());
frame.setLocation(x, y);
}

Categories