Java:升级到单个窗口

0 java user-interface swing

所以我已经编写Java几个月了,我一直在用JOptionPane我的游戏中显示文本和变量.我想像普通游戏一样升级到单个窗口,但我只想关注屏幕上的简单按钮和文本.我曾试图学习JFrameActionListsner,但我没能completley看着办吧.JFrame我真的很困惑.

我的问题是:是否有一个更简单的方法JFrame就是只有一个窗口,我可以拥有简单的文本,按钮,TextFields没有打开一堆窗口的麻烦JOptionPane,使得ActionListener带有JFrame或不得不进入GUI的垃圾负载?如果没有,我在哪里可以找到有关如何制作游戏的帮助JFrame

Vin*_*igh 5

你应该使用一个JFrame.相信我,他们并不难以使用.使用a JFrame,您可以创建多个面板并使用它们在它们之间切换CardLayout.

既然你说你不确定它是如何JFrame工作的,我在这篇文章的最后给出了一个简短的介绍.但首先,让我们首先谈谈如何解决您的问题.


通过CardLayout切换面板

当你想要完全切换在窗口中查看的内容时,你会想要一个完全不同的面板用于特定目的(例如,一个用于主菜单,一个用于游戏).CardLayout是为此而创建的.

您指定"甲板"面板.此面板将保存您想要切换的所有其他面板(卡片):

CardLayout layout = new CardLayout();
JPanel deck = new JPanel();
deck.setLayout(layout);
Run Code Online (Sandbox Code Playgroud)

您需要维护对布局的引用(通过变量),以便您可以在面板之间切换.

现在我们有了一个"甲板"面板,我们需要添加一些卡片.我们通过创建更多JPanels并在将它添加到框架时指定名称(约束)来实现此目的:

JPanel firstCard = new JPanel();
JPanel secondCard = new JPanel();
deck.add(firstCard, "first");
deck.add(secondCard, "second");
Run Code Online (Sandbox Code Playgroud)

添加到卡组的第一张卡片将始终是第一张显示的卡片.

添加完所有卡后,您可以通过呼叫切换它们layout.show(deck, "second");.这是您使用CardLayout如何管理容器中的多个面板的方法.


创建监听器

没有更简单的方法来管理它.它只会变得更难(绑定 - 我强烈建议你调查它们).对于听众来说,有两个步骤:

  1. 创建监听器
  2. 将其添加到组件中

如果您使用lambda"动态"创建了侦听器,则可以为1:

JButton button = new JButton();

//Java 8+
button.addActionListener(event -> {
    //whenever you click the button, code in here triggers
});
Run Code Online (Sandbox Code Playgroud)

对于那些不使用Java 8的用户,您需要使用匿名类:

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        //whenever you click the button, code in here triggers
    }
});
Run Code Online (Sandbox Code Playgroud)

只有一些组件支持ActionListener.任何伸出AbstractButton,像JMenuItem,JButton,JRadioButton,多会支持ActionListener秒.JTextField也支持它,即使它不是AbstractButton.KeyListener但是,每个组件都支持,它们也可用于侦听来自用户的输入事件.

如果您对此有任何疑问,请告诉我,我很乐意回答.


使用Swing组件

的JFrame

你初始化了一个JFrame:

JFrame frame = new JFrame();
Run Code Online (Sandbox Code Playgroud)

然后,您需要设置defaultCloseOperation,以确定窗口关闭时会发生什么:frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

有不同的选项,但EXIT_ON_CLOSE会在关闭窗口后终止您的程序.如果您没有设置defaultCloseOperation,那么您的窗口将关闭,但您的程序仍将运行.BIG NO NO.如果您不希望在关闭框架时退出整个程序,请使用DISPOSE_ON_CLOSE.

关闭操作后,您可能想要设置大小.这是不好的做法.您的框架应根据其内部的大小来确定尺寸.为此,您将组件添加到框架中,然后调用pack():

JButton button = new JButton("Button");
frame.add(button);
//add other components
frame.pack();
Run Code Online (Sandbox Code Playgroud)

这将确保您的框架尺寸适合其内部.您应该始终从内到外设计GUI,以确保您始终有足够的空间来满足您的需求.

集装箱

JFrame是一个Container.容器只是容纳其他组件的组件.所有容器都应具有LayoutManager管理组件布局的方式,如果需要,还可以管理大小.JFrame虽然不是唯一的容器.JPanel实际上是一个意味着要添加到另一个容器(或窗口)的容器.您可以向a添加内容JPanel,然后将该面板添加到另一个容器中.这就是你整洁有序的方式.容器非常简单,所以没什么可说的.

内容窗格

当你创建一个时JFrame,它会出现一个叫做的东西contentPane.它JPanel嵌套在JFrame中.当你这样做时frame.add(button),你会发现add实际上是指contentPane:

//in Container class
public Component add(Component comp) {
    addImpl(comp, null, -1); //where it's added
    return comp;
}

//In JFrame class (overriding)
protected void addImpl(Component comp, Object constraints, int index) {
    if(isRootPaneCheckingEnabled()) {
        getContentPane().add(comp, constraints, index); //adds to content pane instead
    } else {
        super.addImpl(comp, constraints, index); //if root panes were not supported, which they currently are
    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用从框架中获取contentPane

Container pane = frame.getContentPane();
Run Code Online (Sandbox Code Playgroud)

contentPane的Container形式是为了确保一个强大的API(如果不再使用JPanels,我们就不必担心更改getContentPane的方法类型).虽然,因为它是一个JPanel,你可以把它转换回它的原始形式:

JPanel pane = (JPanel) frame.getContentPane();
Run Code Online (Sandbox Code Playgroud)

虽然通常不需要它.使用它作为一个Container往往工作得很好.

布局

JFrame默认情况下,使用BorderLayout,但您可以通过调用setLayout容器的方法来更改它:

FlowLayout layout = new FlowLayout();
frame.setLayout(layout);
Run Code Online (Sandbox Code Playgroud)

在跳转到布局之前,我想提一下JPanel使用FlowLayout默认值,除了框架的默认contentPane,你也可以通过这样做来改变frame.setContentPane(...).contentPane BorderLayout用作默认值.

现在,让我们谈谈一对,从JFrame默认开始:BorderLayout.

一些布局需要所谓的约束,这些约束告诉布局如何处理正在添加的特定组件.将组件添加到容器时指定这些约束:

frame.add(button, BorderLayout.SOUTH);
Run Code Online (Sandbox Code Playgroud)

BorderLayout很简单.您有5个选项:NORTH,SOUTH,EAST,WEST或CENTER.(还有其他值,如PAGE_START,可以互换.最好只使用更简单的表格)

所有约束BorderLayout都是静态字段变量,您调用的类似于我的方式.BorderLayout实际上是一个易于使用的布局,看看它没有多少.即使它的简单性限制了你可以做的事情(你只能把它放在像NORTH这样的特定位置),你通常会结合布局来获得你想要的结果.与其他布局结合使用时,此布局非常强大.

FlowLayout是非常直接的,以及其他布局.其中一个不那么直截了当GridBagLayout,可以是一个非常灵活的布局.它也可能相当复杂,因为文档甚至指出.

使用时GridBagLayout,需要创建约束对象:GridBagConstraints.要使用GridBagLayout,您可以使用约束对象设置约束,然后将组件和约束添加到容器中:

 frame.setLayout(new GridBagLayout());
 GridBagConstraints gbc = new GridBagConstraints();

 JButton button = new JButton("yoyoyo");
 frame.add(button, gbc);
Run Code Online (Sandbox Code Playgroud)

即使我们不调整约束,我们仍然必须在向容器添加组件时指定它.

让我们说我们有4个按钮,我们想把它们并排放置.您可以调整约束gridxgridy值:

JButton button = new JButton("1");
JButton button2 = new JButton("2");
JButton button3 = new JButton("3");
JButton button4 = new JButton("4");

frame.add(button, gbc);

gbc.gridx = 1; //or gridx += 1, or gridx = 1. gridx starts at 0
frame.add(button2, gbc);

gbc.gridx = 0; //must reset the value back to normal
gbc.gridy = 1;
frame.add(button3, gbc);

gbc.gridx = 1;
//since gridy already == 1, no need to change it
frame.add(button4, gbc);
Run Code Online (Sandbox Code Playgroud)

我们可以使用相同的约束对象,只要我们在需要时重置值.

GridBagLayout除非另有说明,否则开始居中,并从中心开始工作.您也不能跳过网格空间.此外,正如您将注意到的,所有按钮都将触摸.如果您想在每个组件之间留出一点空间,可以设置insets约束:

int top = 5, left = 5, bottom = 1, right = 1; 
gbc.insets.set(top, left, bottom, right);
Run Code Online (Sandbox Code Playgroud)

这个布局还有很多,遗憾的是我觉得这不是解释它的最佳位置,看看它是如何记录的(我甚至添加了链接).

还有很多其他布局.尽可能多地熟悉,然后找到有助于满足您需求的那些.定位应始终依赖于LayoutManager所使用的.至于尺寸,这有点取决于你正在使用的布局.