java - 如何在 jpanel 之间切换?

标签 java swing jframe jpanel awt

我对 Java 编程还是很陌生,所以请帮助我纠正我可能忽略的任何错误,或者提供有关如何改进此程序的提示。

好吧,很多问题都解决了,现在我有了一个 CardLayout,但我仍然对如何让我的管道显示在里面有疑问。

当我尝试添加刷新率计时器和速度计时器时,我遇到了关于如何声明和初始化 boolean 变量的问题。

此外,当我编译并运行这个游戏时,我得到了诸如 Game$1.class 之类的文件。有没有办法让我清理它,有人可以解释为什么会这样吗?这些对成品有影响吗? (当游戏被编译并打包成 JAR 时。)

我想在单击播放按钮时将 playerIsReady 设置为 true。然后,当 if 语句为真时,切换到显示管道的面板,并开始在屏幕上移动管道。最好是该管道的 3 个实例,每个实例都在不同的时间开始,但您可以提供任何帮助。

部分代码需要修改,所以我注释掉了一些部分并留下了注释。

我关于这个游戏的其他问题可以找here .

这是我的当前代码

游戏.java

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import javax.swing.SwingUtilities;

public class Game {

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {             
                // the GUI as seen by the user (without frame)
                final CardLayout cl = new CardLayout();
                final JPanel gui = new JPanel(cl);
                // remove if no border is needed
                gui.setBorder(new EmptyBorder(10,10,10,10));

                JPanel menu = new JPanel(new GridBagLayout());
                JButton playGame = new JButton("Play!");
                ActionListener playGameListener = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        cl.show(gui, "game");
                    }
                };
                playGame.addActionListener(playGameListener);
                Insets margin = new Insets(20, 50, 20, 50);
                playGame.setMargin(margin);
                menu.add(playGame);
                gui.add(menu);
                cl.addLayoutComponent(menu, "menu");

                final JPanel pipes = new Pipes();
                gui.add(pipes);
                cl.addLayoutComponent(pipes, "game");

                JFrame f = new JFrame("Pipes Game");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See https://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);

                /*if (playerIsReady) { 
                    Timer speed = new Timer(10, new ActionListener() {  //pipe speed
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            pipes.move();
                        }
                    });
                    speed.start();

                    Timer refresh = new Timer(30, new ActionListener() {    //refresh rate
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            pipes.repaint();
                        }
                    });
                    refresh.start();
                }*/
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

管道.java

// What import(s) do I need for ArrayList?
public class Pipes {
    List<Pipe> pipes = new ArrayList<Pipe>();

    public Pipes() {
        pipes.add(new Pipe(50, 100));
        pipes.add(new Pipe(150, 100));
        pipes.add(new Pipe(250, 100));
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        for ( Pipe pipe : pipes ){
            pipe.drawPipe(g);
        }
    }
}

管道对象.java

import java.awt.Graphics;

public class PipeObject {
    //Declare and initialiaze variables
    int x1 = 754;               //xVal start
    int x2 = 75;                //pipe width
                                //total width is 83
    int y1 = -1;                //yVal start
    int y2 = setHeightVal();    //pipe height
    int gap = 130;              //gap height

    public void drawPipe(Graphics g) {

        g.clearRect(0,0,750,500);                       //Clear screen
        g.drawRect(x1,y1,x2,y2);                        //Draw part 1
        g.drawRect(x1-3,y2-1,x2+6,25);                  //Draw part 2
        g.drawRect(x1-3,y2+25+gap,x2+6,25);             //Draw part 3
        g.drawRect(x1,y2+25+gap+25,x2,500-y2-49-gap);   //Draw part 4
    }

    public void move() {
        x1--;
    }

    public int getMyX() {   //To determine where the pipe is horizontally
        return x1-3;
    }

    public int getMyY() {   //To determine where the pipe is vertically
        return y2+25;
    }

    public int setHeightVal() {     //Get a random number and select a preset height
        int num = (int)(9*Math.random() + 1);
        int val = 0;
        if (num == 9)
        {
            val = 295;
        }
        else if (num == 8)
        {
            val = 246;
        }
        else if (num == 7)
        {
            val = 216;
        }
        else if (num == 6)
        {
            val = 185;
        }
        else if (num == 5)
        {
            val = 156;
        }
        else if (num == 4)
        {
            val = 125;
        }
        else if (num == 3)
        {
            val = 96;
        }
        else if (num == 2)
        {
            val = 66;
        }
        else
        {
            val = 25;
        }
        return val;
    }
}

最佳答案

解决此问题的最佳方法是使用 CardLayout

enter image description here

enter image description here

注意事项

  • 带有ActionListener 的按钮比矩形上的MouseListener 要好得多。
    • 当鼠标指向该按钮或通过键盘切换到该组件时,该按钮将显示焦点。
    • 该按钮可通过键盘访问。
    • 该按钮具有支持多个内置图标的功能(例如“初始外观”、聚焦、按下等)
  • 通过添加 EmptyBorder
  • 在菜单面板和游戏周围提供 GUI 中的空白区域
  • 通过设置边距使按钮变大。
  • 根据需要调整边距、边框和首选尺寸。这些尺寸是我设置的,以免屏幕截图太大。
  • 在代码注释中查看更多提示。

代码

这是 MCTaRE (最小的完整测试和可读示例)生成上述屏幕截图。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class PipesGame {

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                // the GUI as seen by the user (without frame)
                final CardLayout cl = new CardLayout();
                final JPanel gui = new JPanel(cl);
                // remove if no border is needed
                gui.setBorder(new EmptyBorder(10,10,10,10));

                JPanel menu = new JPanel(new GridBagLayout());
                JButton playGame = new JButton("Play!");
                ActionListener playGameListener = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        cl.show(gui, "game");
                    }
                };
                playGame.addActionListener(playGameListener);
                Insets margin = new Insets(20, 50, 20, 50);
                playGame.setMargin(margin);
                menu.add(playGame);
                gui.add(menu);
                cl.addLayoutComponent(menu, "menu");

                JPanel pipes = new Pipes();
                gui.add(pipes);
                cl.addLayoutComponent(pipes, "game");

                JFrame f = new JFrame("Pipes Game");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See https://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

class Pipes extends JPanel {

    Pipes() {
        setBackground(Color.BLACK);
        setForeground(Color.WHITE);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString("Pipes game appears here..", 170, 80);
    }

    @Override 
    public Dimension getPreferredSize() {
        // adjust to need
        return new Dimension(500,150);
    }
}

关于java - 如何在 jpanel 之间切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21592492/

相关文章:

java - 如何实现java awt/swing应用程序

java - 我是否正确使用了 Java swing 和图形?

Java - 加载 JTabbedPane 一个又一个选项卡

java - Swing 组件未居中

java - 从 JMenuItem java 打开一个弹出窗口

java - 将全滚动合成导出到图像

java - 了解有关 serialVersionUID 字段的 FindBugs 警告

java - XML解析器: How to avoid null pointer exception

java - 在单独的窗口中打开一个新的 jframe 以搜索信息的 clickbutton 事件

java - 在java中使用stacks(LinkedList)实现表达式树如下,但有错误