Java:升级到单个窗口

时间:2014-12-03 04:55:30

标签: java swing user-interface

所以我几个月来一直在编写Java代码,而且我一直在使用JOptionPane在我的游戏中显示文本和变量。我想像普通游戏一样升级到单个窗口,但我只想关注屏幕上的简单按钮和文本。我尝试过学习JFrameActionListsner,但我没有完全弄明白。 JFrame让我很困惑。

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

4 个答案:

答案 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. 创建监听器
  2. 将其添加到组件
  3. 如果您在飞行中创建了监听器"可能为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的内容,如JMenuItemJButtonJRadioButton等,都会支持ActionListenerJTextField也支持它,即使它不是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,以确保您始终有足够的空间来满足您的需求。

    <强>集装箱

    JFrameContainer。容器只是容纳其他组件的组件。所有容器都应该有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
        }
    }
    

    您也可以使用

    从框架中抓取contentPane
    Container 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个按钮,我们想把它们放在一起。您可以调整约束的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);
    

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

    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并进入高级图形,精灵表,动画,更好的游戏。我现在理解布局的重要性,所以这对我来说是一个很好的学习经历,回答我的问题的答案非常糟糕。