Like the title says, i am looking to center a 800x600 canvas on a 1920x1080 screen
I want the canvas to be centered in the JFrame
public class Window extends JFrame {
private static final long serialVersionUID = 7045103465799258651L;
Dimension d;
public Window(int w, int h, String title,Launcher launch){
setTitle(title);
d = new Dimension(w,h);
setMinimumSize(d);
setMaximumSize(d);
setPreferredSize(d);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setFocusable(true);
setLocationRelativeTo(null);
add(launch);
launch.start();
}
}
One way:
Give your container a GridBagLayout
Add your component, your drawing JPanel (not Canvas), to the container without use of GridBagConstraints. It will add it to the container by default in a centered position.
If you use BorderLayout like many are telling you, your component will fill the container, which does not seem to be what you're aiming for here.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.*;
public class TestCenterLayout extends JPanel{
private static final long serialVersionUID = 1L;
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private static final Color BACKGROUND = Color.pink;
public TestCenterLayout() {
setBorder(BorderFactory.createTitledBorder("800 x 600 Panel"));
setBackground(BACKGROUND);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Test Center Layout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().add(new TestCenterLayout());
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Related
I have a class which extends a Jframe, and i have it centered using setLocationRelativeTo(null);. The layouManager is null aswell.
My JFrame:
mport com.sxf.protocol.chat.util.window.AbstractField;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
public class Field extends AbstractField {
private Container cp;
public Field() {
super("Test");
buildWindow();
}
private void buildWindow() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setPreferredSize(new Dimension(frameWidth, frameHeight));
setResizable(false);
cp = getContentPane();
cp.setLayout(null);
initComponents();
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void initComponents() {
JLabel label = new JLabel("Test", SwingConstants.CENTER);
JLabel border = new JLabel("");
label.setSize(200, 30);
label.setLocation((frameWidth - label.getWidth()) / 2, (frameHeight - label.getHeight()) / 2);
border.setBounds(frameWidth / 2, 0, frameWidth / 2, frameHeight);
label.setBorder(new LineBorder(new Color(0, 0, 0)));
border.setBorder(new LineBorder(new Color(255, 0, 0)));
cp.add(label);
cp.add(border);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Field();
}
});
}
}
I added to border to see if its centered correctly or not.
The AbstractField (only some calculations in it):
public abstract class AbstractField extends JFrame {
private final static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final Dimension frameSize = new Dimension(screenSize.width / 4, screenSize.height / 4);
protected static final int frameWidth;
protected static final int frameHeight;
protected static final int x;
protected static final int y;
static {
frameWidth = frameSize.width;
frameHeight = frameSize.height;
x = (screenSize.width - frameWidth) / 2;
y = (screenSize.height - frameHeight) / 2;
}
public AbstractField(String title) {
super(title);
}
}
But when i try to center my components, e.g. the JLabel, doing
(frame.getWidth - component.getWidth) / 2, and the same for the height, it is not actually centered but a little bit to the right.
Is that due to a native moved beginning of the jframe and can i calculate that?
How to indeed center object in a JFrame?
Indeed add it as the only component added to a JPanel with a GridBagLayout. Use that panel as the content pane.
Example:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class CenteredLabel {
private JComponent ui = null;
CenteredLabel() {
initUI();
}
public final void initUI() {
if (ui!=null) return;
ui = new JPanel(new GridBagLayout());
ui.setBorder(new EmptyBorder(4,4,4,4));
JLabel centeredLabel = new JLabel("Test");
centeredLabel.setBorder(new LineBorder(Color.RED));
ui.add(centeredLabel);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
CenteredLabel o = new CenteredLabel();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
public class FrameTest extends JFrame {
private JPanel contentPane;
private JPanel spielPane;
private JPanel infoPane;
private JButton btnStart;
private JLabel lblRunde;
private Monster monster1;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FrameTest frame = new FrameTest();
frame.setVisible(true);
Monster m = new Monster();
frame.repaintSpielPanel();
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
public FrameTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 600);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(null);
setContentPane(contentPane);
spielPane = new JPanel();
spielPane.setBounds(6, 6, 566, 566);
spielPane.setLayout(null);
spielPane.setBackground(Color.yellow);
contentPane.add(spielPane);
infoPane = new JPanel();
infoPane.setBounds(578, 6, 216, 566);
infoPane.setLayout(null);
infoPane.setBackground(Color.yellow);
contentPane.add(infoPane);
btnStart = new JButton("Start");
btnStart.setBounds(44, 6, 117, 29);
infoPane.add(btnStart);
lblRunde = new JLabel("Runde");
lblRunde.setBounds(77, 47, 61, 16);
infoPane.add(lblRunde);
monster1 = new Monster();
monster1.setVisible(true);
spielPane.add(monster1);
}
private class Monser extends JLabel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(0, 0, 10, 10);
}
}
public void repaintSpielPanel() {
spielPane.repaint();
}
}
I tried to put a Rectangle into my frame, but it isn't there. I'm just starting to program, so probably I just don't know how to get it onto the screen. Pls help!
Don't paint in a JLabel which isn't opaque. Instead do so in a JPanel.
Don't use null layouts and setBounds(...). While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Most important, you never add an instance of your drawing component, here Monser, to anything. To see that this is true, search your code for any calls to new Monser(). If a constructor isn't being called, an instance isn't going to be created.
Also note that you're creating a Monster instance, and this is a class that you've not shown us.
You're adding it to a null layout using JPanel, and so since it has no size, it won't show at all. Again, don't use null layouts.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyTest extends JPanel {
private static final Color BG = Color.yellow;
private static final int GAP = 8;
private JButton btnStart = new JButton("Start");
private JLabel lblRunde = new JLabel("Runde", SwingConstants.CENTER);
private MonsterPanel monsterPanel = new MonsterPanel(600, 600, BG);
public MyTest() {
JPanel buttonPanel = createButtonPanel();
buttonPanel.setBackground(BG);
setLayout(new BorderLayout(GAP, GAP));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
add(monsterPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.LINE_END);
}
private JPanel createButtonPanel() {
JPanel btnPanel = new JPanel();
btnPanel.setBackground(BG);
JPanel gridPanel = new JPanel(new GridLayout(0, 1, 0, 5));
gridPanel.setOpaque(false);
gridPanel.add(btnStart);
gridPanel.add(lblRunde);
btnPanel.add(gridPanel);
return btnPanel;
}
private static void createAndShowGui() {
MyTest mainPanel = new MyTest();
JFrame frame = new JFrame("MyFrameTest");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MonsterPanel extends JPanel {
public static final int MONST_WIDTH = 10;
public static final Color MONST_COLOR = Color.red;
private int prefW;
private int prefH;
private int monstX = 0;
private int monstY = 0;
public MonsterPanel(int prefW, int prefH, Color bkgrnd) {
this.prefW = prefW;
this.prefH = prefH;
setBackground(bkgrnd);
}
public void setMonstXY(int x, int y) {
this.monstX = x;
this.monstY = y;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(MONST_COLOR);
g.fillRect(monstX, monstY, MONST_WIDTH, MONST_WIDTH);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
}
I try to buid JPanels in a separate class to invoke them separately and add different items on it. Please can you tell me what i am doing wrong?
MyFrame.java
import javax.swing.*;
import java.awt.*;
public class MyFrame extends JFrame {
public static void main(String[] args) {
MyFrame frame = new MyFrame();
frame.setVisible(true);
}
public MyFrame() {
setTitle("MyFrame");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
JButton testButton = new JButton("Test");
panel.add(testButton);
}
}
MyPanel.java
import javax.swing.*;
import java.awt.*;
class MyPanel extends JPanel {
public MyPanel() {
this.setOpaque(true);
this.setVisible(true);
}
}
You're not adding your panel variable to your JFrame's contentPane.
Add:
public MyFrame() {
setTitle("MyFrame");
// setSize(300, 200); // let's avoid this
setDefaultCloseOperation(EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
JButton testButton = new JButton("Test");
panel.add(testButton);
add(panel); // *** here
pack(); // this tells the layout managers to do their thing
setLocationRelativeTo(null);
setVisible(true);
}
As a side note:
public MyPanel() {
this.setOpaque(true);
this.setVisible(true);
}
JPanels are opaque and visible by default, so your method calls within the MyPanel constructor do nothing useful.
Side note 2: I rarely if ever extend JFrame or any other top level window (with the exception of JApplet if I'm forced to use one of these), since I rarely change the innate behavior of the window. Better I think to create my top level windows (i.e., my JFrames) when needed.
Side note 3: Always strive to start your Swing GUI's on the Swing event thread. So do...
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame = new MyFrame();
frame.setVisible(true);
}
});
}
Edit
You ask:
You wrote lets avoid setting the size.. can you tell me how i can pack it but set a minimum frame size?
I like to override the JPanel's getPreferredSize() method, and have it return a Dimension that makes sense.
For example, you could do something like this to be sure that your GUI is at lest PREF_W by PREF_H in size:
import java.awt.Dimension;
import javax.swing.*;
public class ShowGetPreferredSize extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
#Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSize;
}
int w = Math.max(superSize.width, PREF_W);
int h = Math.max(superSize.height, PREF_H);
return new Dimension(w, h);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ShowGetPreferredSize");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new ShowGetPreferredSize());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I made a 840 by 400 frame and added a text field. By default, the java app shrinked only to the size of the text field. I want it fixed to the respective size.
I tried setResizable(false), setExtendedState(), setBounds() with no avail.
Best to use a JPanel as your contentPane or add it to the contentPane, and to override its getPreferredSize() method and then usepack()` on the JFrame. For example:
import java.awt.Dimension;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 300;
public MyPanel() {
//...
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
MyPanel myPanel = new MyPanel();
JFrame frame = new JFrame("My GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(myPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
One advantage of this is that other classes cannot change MyPanel's size via setSize(...) or setPreferredSize(...).
Try
setPreferredSize(new Dimension(840,400));
If you named your frame you can do
name.setPreferredSize(new Dimension(840,400));
There is a window in which I want to place a button, and then paint the whole area beneath it. In other words, button should cover a piece of painting.
import java.awt.*;
import javax.swing.*;
class Window
{
private JFrame frame;
private JButton launchButton;
private JPanel pnllaunchButton;
private JPanel paintingPanel;
//width and height of client area
private Rectangle dim;
//w,h - width and height of the whole window
public Window(String title,int w,int h)
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(0,0);
frame.setMinimumSize( new Dimension(110,110));
frame.setSize(w, h);
frame.setVisible(true);
frame.setTitle(title);
frame.setResizable(false);
addLaunchButton();
}
private void addLaunchButton()
{
pnllaunchButton = new JPanel();
launchButton = new JButton("Plot!");
dim = new Rectangle();
frame.getContentPane().getBounds(dim);
pnllaunchButton.setBounds(dim.width-100,dim.height-25,100,25);
launchButton.setBounds(dim.width-100,dim.height-25,100,25);
pnllaunchButton.setLayout(null);
pnllaunchButton.add(launchButton);
frame.getContentPane().add(pnllaunchButton);
frame.getContentPane().setComponentZOrder(pnllaunchButton, new Integer(2));
}
public void drawCoordinateSystem()
{
paintingPanel = new JPanel();
paintingPanel.add(new CoordinateSystem());
frame.getContentPane().add(paintingPanel);
frame.getContentPane().setComponentZOrder(paintingPanel,new Integer(3));
}
}
class CoordinateSystem extends JPanel
{
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Dimension size = this.getSize();
g.setColor(Color.BLACK);
g.drawLine(0,size.height/2,size.width, size.height/2);
g.drawLine(size.width/2, 0, size.width/2, size.height);
}
}
public class GC {
public static void main(String[] args)
{
Window h = new Window("GC",800,600);
h.drawCoordinateSystem();
}
}
This code doesn't fulfill the specification. Program creates an empty window and outputs:
run:
Exception in thread "main" java.lang.IllegalArgumentException: illegal component position
at java.awt.Container.checkAdding(Container.java:504)
at java.awt.Container.setComponentZOrder(Container.java:759)
at Window.addLaunchButton(Window.java:46)
at Window.<init>(Window.java:26)
at GC.main(GC.java:10)
Could you point out my mistake? setComponentZOrder() method doesn't seem to be described precisely in javadoc.
Rename your class. The Window class is already part of the standard core Java libraries, and your class name could cause present or future problems.
Don't us null layouts and setBounds(...). This is bad, bad, bad, and will make it very difficult to maintain or upgrade your application. Instead, learn about and use the layout managers.
Consider making a JLabel the contentPane, make it opaque, give it a layout and an ImageIcon and add your components to it.
The ImageIcon can hold a BufferedImage with a grid.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MyWindow {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private static final Color COLOR0 = Color.red;
private static final Color COLOR1 = Color.blue;
private static final float COLOR_REPEAT_DIST = 30f;
private JLabel backGroundLabel = new JLabel();
public MyWindow() {
backGroundLabel.setOpaque(true);
backGroundLabel.setLayout(new BorderLayout());
int eb = 15;
BufferedImage bkgrndImg = createBkgrndImage();
ImageIcon icon = new ImageIcon(bkgrndImg);
backGroundLabel.setIcon(icon);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout(SwingConstants.RIGHT, eb, eb));
bottomPanel.setOpaque(false);
bottomPanel.add(new JButton("Plot"));
backGroundLabel.add(bottomPanel, BorderLayout.PAGE_END);
}
private BufferedImage createBkgrndImage() {
BufferedImage img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setPaint(new GradientPaint(0f, 0f, COLOR0, COLOR_REPEAT_DIST, COLOR_REPEAT_DIST, COLOR1, true));
g2.fillRect(0, 0, PREF_W, PREF_H);
g2.dispose();
return img;
}
public JComponent getMainPane() {
return backGroundLabel;
}
private static void createAndShowGui() {
MyWindow mainPanel = new MyWindow();
JFrame frame = new JFrame("MyWindow");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel.getMainPane());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which looks like so:
Pass an int instead of an Integer to the setComponentZOrder method.
private void addLaunchButton()
{
pnllaunchButton = new JPanel();
launchButton = new JButton("Plot!");
dim = new Rectangle();
frame.getContentPane().getBounds(dim);
pnllaunchButton.setBounds(dim.width-100,dim.height-25,100,25);
launchButton.setBounds(dim.width-100,dim.height-25,100,25);
pnllaunchButton.setLayout(null);
pnllaunchButton.add(launchButton);
frame.getContentPane().add(pnllaunchButton);
frame.getContentPane().setComponentZOrder(pnllaunchButton, 2);
}