[英]Can't get the buttons to be on the center right position
I'm trying to figure out how to position my buttons in the center right position. 我试图弄清楚如何将按钮定位在右中位置。 I added what Ive done so far and I'll add a drawing of how I want it to be. 我添加了到目前为止我所做的事情,并添加了我想要的样子的图纸。
I'm trying to understand how to determine the position I want in Swing, can't really understand the advantages of each layout. 我试图了解如何确定我想要在Swing中的位置,但我真的无法理解每种布局的优势。
My code so far: 到目前为止,我的代码:
package Game;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.Timer;
public class MainWindow extends JFrame implements ActionListener {
private JButton exit;
private JButton start_Game;
private ImageIcon puzzleBackground;
// private JLabel back_Label;
// private GridBagConstraints grid = new GridBagConstraints();
private JPanel menu;
public MainWindow()
{
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(450,300);
setLocationRelativeTo(null);
this.setLayout(new FlowLayout(FlowLayout.RIGHT));
menu = new JPanel();
menu.setLayout(new BorderLayout());
//setResizable(false);
//===== Background =====
puzzleBackground = new ImageIcon("MyBackground.jpg");
setContentPane(new JLabel(puzzleBackground));
exit = new JButton("Exit");
menu.add(exit, BorderLayout.CENTER);
exit.addActionListener(this);
start_Game = new JButton("Start to play");
menu.add(start_Game, BorderLayout.SOUTH);
exit.addActionListener(this);
start_Game.addActionListener(this);
//
// back_Label = new JLabel(puzzleBackground);
// back_Label.setLayout(new BorderLayout());
//===== Buttons =====
// back_Label.add(exit,BorderLayout.CENTER);
//
// back_Label.add(start_Game,BorderLayout.EAST);
//
add(menu);
setVisible(true);
}
public static void main(String args[])
{
MainWindow a = new MainWindow();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == exit)
{
System.exit(0);
}
else
{
//open start up window.
}
}
}
So, your basic problem boils down the following lines... 因此,您的基本问题归结为以下几行...
this.setLayout(new BorderLayout());
//...
//===== Background =====
puzzleBackground = new ImageIcon("MyBackground.jpg");
setContentPane(new JLabel(puzzleBackground));
Can you tell me what the layout manager in use actually is now? 您能告诉我现在实际使用的布局管理器是什么吗? Wrong. 错误。 The layout manager is now null
, because JLabel
doesn't actually have a default layout manager. 布局管理器现在为null
,因为JLabel
实际上没有默认的布局管理器。
So, the "simple" answer would be to move the setLayout
call to below the setContentPane
call, but this would be a short sighted answer, as JLabel
calculates it's preferred based on the icon and text properties only, not it's contents of child components. 因此,“简单”的答案是将setLayout
调用移到setContentPane
调用之下,但这是一个短视的答案,因为JLabel
仅根据icon和text属性而不是子组件的内容来计算它的优先级。
A better solution would be to do something demonstrated in How to set a background picture in JPanel (see the second example) 更好的解决方案是执行如何在JPanel中设置背景图片中演示的操作(请参见第二个示例)
This means that if the image is smaller then the required space, the components will disappear off the screen. 这意味着,如果图像小于所需的空间,则组件将从屏幕上消失。
I went through and cleaned up the code slightly, only with the intention of getting the layout to work 我仔细检查并清理了代码,只是为了使布局正常工作
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainWindow extends JFrame implements ActionListener {
private JButton exit;
private JButton start_Game;
private JPanel menu;
public MainWindow() {
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
menu = new JPanel();
menu.setLayout(new GridBagLayout());
exit = new JButton("Exit");
exit.addActionListener(this);
start_Game = new JButton("Start to play");
exit.addActionListener(this);
start_Game.addActionListener(this);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = gbc.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(exit, gbc);
menu.add(start_Game, gbc);
// This is just a filler, it can be removed, but it helps prove the point
add(new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
add(menu, BorderLayout.EAST);
pack();
setVisible(true);
}
public static void main(String args[]) {
MainWindow a = new MainWindow();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
} else {
//open start up window.
}
}
}
I'd also like to point out that extending directly from JFrame
is also short sighted, it's locking you into a single use container and you're not actually adding any new functionality to the class. 我还想指出,直接从JFrame
扩展也是近距离的,它将您锁定在一个一次性容器中,并且实际上并没有向该类添加任何新功能。
The following is a simple example of a possibly better structure. 以下是一个可能更好的结构的简单示例。 It's missing the concept of a "controller", which controls stuff and "model" which maintains the state information which is used by the UI to display "stuff", but gives a starting point 它缺少“控制器”的概念,该概念控制东西和“模型”来维护用户界面用来显示“东西”的状态信息,但是提供了一个起点
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String args[]) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Welcome");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
setLayout(new BorderLayout());
// This is just a filler, it can be removed, but it helps prove the point
add(new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
add(new MenuPane(), BorderLayout.EAST);
}
}
public class MenuPane extends JPanel {
private JButton exit;
private JButton start_Game;
private JPanel menu;
public MenuPane() {
menu = new JPanel();
menu.setLayout(new GridBagLayout());
ActionHandler actionHandler = new ActionHandler();
exit = new JButton("Exit");
exit.addActionListener(actionHandler);
start_Game = new JButton("Start to play");
start_Game.addActionListener(actionHandler);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = gbc.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(exit, gbc);
menu.add(start_Game, gbc);
}
public class ActionHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
} else {
//open start up window.
// This should be used to notifiy a controller class
// that some new action needs to take place, the controller
// is then responsible for making it happen
}
}
}
}
}
A better way to add a BG image is to use a custom painted JPanel
. 添加BG图像的更好方法是使用自定义绘制的JPanel
。 Then set the layout of the panel and add other panels or components to it. 然后设置面板的布局,并向其添加其他面板或组件。 Note that here the buttons are not appearing largely because they are being added to a JLabel
. 请注意,此处的按钮主要是因为已添加到JLabel
中而没有出现。
Here is an alternative that works along the same lines, with the red panel being the panel which custom paints the background image and the menu
panel being set to transparent (look for the opaque
method). 这是一种沿相同方向工作的替代方法,红色面板是自定义绘制背景图像的面板, menu
面板设置为透明(寻找opaque
方法)。
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
public class MainWindow extends JFrame {
private JPanel menu;
private JPanel contentPane = new JPanel(new BorderLayout(4,4));
public MainWindow() {
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//setSize(450, 300); // use pack() instead
setContentPane(contentPane);
contentPane.setBorder(new EmptyBorder(8,8,8,8));
contentPane.setBackground(Color.RED);
contentPane.add(new JLabel(new ImageIcon(
new BufferedImage(400,200,BufferedImage.TYPE_INT_RGB))));
menu = new JPanel(new GridLayout(0,1,10,10));
menu.add(new JButton("Exit"), BorderLayout.CENTER);
menu.add(new JButton("Start to play"), BorderLayout.SOUTH);
JPanel menuCenterPanel = new JPanel(new GridBagLayout());
menuCenterPanel.add(menu);
add(menuCenterPanel, BorderLayout.LINE_END);
pack();
setLocationRelativeTo(null); // do AFTER pack()
setMinimumSize(getSize());
setVisible(true);
}
public static void main(String args[]) {
MainWindow a = new MainWindow();
}
}
Doing UI in Java is not advised, but ignoring that. 不建议在Java中使用UI,但请忽略这一点。
You get (calculate) the height and width of the screen. 您将获得(计算)屏幕的高度和宽度。 Then start drawing buttons depending on that. 然后根据需要开始绘制按钮。 Drawing a button on screens 50% of pixel value width and 50% of pixel value of height will center the button. 在屏幕上画一个按钮,其像素值宽度的50%和像素值高度的50%将使按钮居中。
Simply crate buttons with variable location that is calculated from main screen px size and place them where ever you want. 只需将根据主屏幕px尺寸计算出的位置可变的按钮包装起来,然后将它们放置在所需的位置即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.