所以我几个月来一直在编写Java代码,而且我一直在使用JOptionPane
在我的游戏中显示文本和变量。我想像普通游戏一样升级到单个窗口,但我只想关注屏幕上的简单按钮和文本。我尝试过学习JFrame
和ActionListsner
,但我没有完全弄明白。 JFrame
让我很困惑。
我的问题是:JFrame
旁边是否有一种更简单的方法就是拥有一个窗口,我可以使用简单的文字,按钮和TextFields
而无需打开麻烦一堆带JOptionPane
的窗口,用ActionListener
制作JFrame
的垃圾,或者不得不进入GUI?如果没有,我在哪里可以找到有关如何使用JFrame
制作游戏的帮助?
答案 0 :(得分:5)
您应该使用JFrame
。相信我,他们并不难以使用。使用JFrame
,您可以创建多个面板,并使用CardLayout
在它们之间切换。
由于您说您不确定JFrame
的工作原理,因此我在本文末尾给出了对它们的简短介绍。但首先,我们先谈谈如何解决您的问题。
通过CardLayout切换面板
当您想要完全切换在窗口中查看的内容时,您将需要一个完全不同的面板用于该特定目的(例如,一个用于主菜单,一个用于游戏)。为此创建了CardLayout
。
你指定一个"套牌"面板。此面板将容纳您想要切换的所有其他面板(卡片):
CardLayout layout = new CardLayout();
JPanel deck = new JPanel();
deck.setLayout(layout);
您需要维护对布局的引用(通过变量),以便您可以在面板之间切换。
现在我们有一个" deck"面板,我们需要添加一些卡片。我们通过创建更多JPanels并在将它添加到框架时指定名称(约束)来实现此目的:
JPanel firstCard = new JPanel();
JPanel secondCard = new JPanel();
deck.add(firstCard, "first");
deck.add(secondCard, "second");
添加到套牌的第一张牌将始终是第一张显示的牌。
添加完所有卡片后,您可以通过拨打layout.show(deck, "second");
进行切换。这是您使用CardLayout
管理容器中多个面板的方法。
创建听众
没有更简单的方法来管理它。它只会变得更难(绑定 - 我强烈建议你look into them)。对于听众来说,有两个步骤:
如果您在飞行中创建了监听器"可能为1"使用lambda:
JButton button = new JButton();
//Java 8+
button.addActionListener(event -> {
//whenever you click the button, code in here triggers
});
对于那些不使用Java 8的用户,您需要使用匿名类:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//whenever you click the button, code in here triggers
}
});
只有部分组件支持ActionListener
。任何扩展AbstractButton
的内容,如JMenuItem
,JButton
,JRadioButton
等,都会支持ActionListener
。 JTextField
也支持它,即使它不是AbstractButton
。但是,每个组件都支持KeyListener
,它也可用于侦听来自用户的输入事件。
如果您对此有任何疑问,请与我联系,我很乐意回答。
使用Swing组件
<强>的JFrame 强>
您初始化JFrame
:
JFrame frame = new JFrame();
然后,您需要设置defaultCloseOperation
,以确定窗口关闭时会发生什么:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
有不同的选项,但EXIT_ON_CLOSE
会在关闭窗口后终止您的程序。 如果您未设置defaultCloseOperation
,则您的窗口将关闭,但您的程序仍将运行。大不了。如果您不想在关闭相框时退出整个程序,请使用DISPOSE_ON_CLOSE
。
完成关闭操作后,您可能想要设置大小。 这是不好的做法。您的框架应根据其内部的尺寸来确定尺寸。为此,您需要将组件添加到框架中,然后调用pack()
:
JButton button = new JButton("Button");
frame.add(button);
//add other components
frame.pack();
这将确保您的框架尺寸适合其内部。您应该始终从内到外设计GUI,以确保您始终有足够的空间来满足您的需求。
<强>集装箱强>
JFrame
是Container
。容器只是容纳其他组件的组件。所有容器都应该有LayoutManager
来管理组件的布局方式,如果需要,还可以管理大小。 JFrame
不是唯一的容器。 JPanel
实际上是一个容器,意味着要添加到另一个容器(或窗口)。您可以向JPanel
添加内容,然后将该面板添加到另一个容器中。这就是你整洁有序的方式。容器非常简单,所以谈论起来并不多。
内容窗格
当您创建JFrame
时,会出现名为contentPane
的内容。它是嵌套在JFrame中的JPanel
。当您执行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
}
}
您也可以使用
从框架中抓取contentPaneContainer pane = frame.getContentPane();
contentPane为Container
形式的原因是为了确保强大的API(如果不再使用JPanels,我们不必担心更改方法类型的getContentPane)。虽然,因为它是一个JPanel,你可以把它重新塑造成它的原始形式:
JPanel pane = (JPanel) frame.getContentPane();
虽然通常不需要它。将它用作Container
往往可以正常工作。
<强>布局强>
默认情况下, JFrame
使用BorderLayout
,但您可以通过调用容器的setLayout
方法来更改此内容:
FlowLayout layout = new FlowLayout();
frame.setLayout(layout);
在进入布局之前,我想提一下JPanel
使用FlowLayout
作为默认设置,除了框架的默认contentPane ,你也可以做frame.setContentPane(...)
改变。 contentPane使用BorderLayout
作为默认值。
现在,让我们谈谈一对,从JFrame
默认值开始:BorderLayout
。
某些布局需要所谓的约束,它告诉布局如何处理要添加的特定组件。将组件添加到容器时指定这些约束:
frame.add(button, BorderLayout.SOUTH);
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);
即使我们没有调整约束,我们仍然必须在向容器添加组件时指定它。
假设我们有4个按钮,我们想把它们放在一起。您可以调整约束的gridx
和gridy
值:
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);
我们可以使用相同的约束对象,只要我们在需要时重置值。
GridBagLayout
开始居中,并从中心开始工作,除非您另有说明。您也不能跳过网格空间。此外,正如您所注意到的,您的所有按钮都会触及。如果您希望在每个组件之间留出一点空间,则可以设置约束的insets
:
int top = 5, left = 5, bottom = 1, right = 1;
gbc.insets.set(top, left, bottom, right);
这种布局还有很多,遗憾的是我觉得这不是解释所有内容的最佳位置,看看它是如何记录的(我甚至添加了链接) )。
还有很多其他布局。尽可能多地熟悉,然后找到适合您需求的那些。定位应始终依赖于LayoutManager
正在使用的{{1}}。至于尺寸,这有点取决于你正在使用的布局。
答案 1 :(得分:1)
我强烈建议使用JavaFX。它是一个非常好用的相当容易使用的GUI系统,具有漂亮的外观和可自定义的控件。 JavaFX事件(基本上是ActionListeners)也非常简单。
这应该让你开始:http://docs.oracle.com/javase/8/javafx/get-started-tutorial/get_start_apps.htm#JFXST804
答案 2 :(得分:0)
我相信CardLayout正是您所寻找的。有了它,程序员可以选择在JFrame中可见的JPanel。在用户交互时,您可以切换JFrame的内容,而不会弹出新的JFrame或JOptionPanes。
比简单游戏使用Swing更简单吗? Swing有一个学习曲线,但通过正确的资源和实践,您可以学习如何快速构建简单的GUI应用程序。
答案 3 :(得分:-3)
我发现我可以这样做:
frame.setLayout(null);
然后每当我创建一个要添加到Frame的对象时,我都可以将位置设置为我想要的任何位置。我认为现在这些布局是一个拐杖。设置对象的位置并不困难,所以我会坚持下去! :)
<强>更新强>
这种定位事物的方法是一个坏主意。这个问题非常草率的解决方案。用它定位事物是一种痛苦。幸运的是,我已经开始使用Canvas并进入高级图形,精灵表,动画,更好的游戏。我现在理解布局的重要性,所以这对我来说是一个很好的学习经历,回答我的问题的答案非常糟糕。