如何在 jpanel 之间切换? [英] How can I switch between jpanels?

查看:58
本文介绍了如何在 jpanel 之间切换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

另外,当我编译和运行这个游戏时,我会得到像 Game$1.class 这样的文件.有没有办法让我清理这个,有人可以解释为什么会发生这种情况吗?这些对成品有影响吗?(当游戏被编译并打包成 JAR 时.)

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

其中一些代码需要工作,所以我已经注释掉了一些部分并留下了注释.

我关于这个游戏的其他问题可以找到 (最小完整测试和可读示例).

import java.awt.*;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 javax.swing.*;导入 javax.swing.border.EmptyBorder;公共类 PipesGame {公共静态无效主要(字符串[]参数){可运行 r = new Runnable() {@覆盖公共无效运行(){//用户看到的 GUI(没有框架)最终 CardLayout cl = new CardLayout();最后的 JPanel gui = new JPanel(cl);//如果不需要边框,则删除gui.setBorder(new EmptyBorder(10,10,10,10));JPanel 菜单 = new JPanel(new GridBagLayout());JButton playGame = new JButton("Play!");ActionListener playGameListener = new ActionListener() {@覆盖公共无效actionPerformed(ActionEvent e){cl.show(gui, "游戏");}};playGame.addActionListener(playGameListener);插图边距 = 新插图(20、50、20、50);playGame.setMargin(保证金);menu.add(playGame);gui.add(菜单);cl.addLayoutComponent(菜单,菜单");JPanel 管道 = 新管道();gui.add(管道);cl.addLayoutComponent(管道,游戏");JFrame f = new JFrame("管道游戏");f.add(gui);//确保 JVM 在帧关闭后关闭//所有非守护线程都结束了f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//有关演示,请参见 https://stackoverflow.com/a/7143398/418556.f.setLocationByPlatform(true);//确保框架是它需要的最小尺寸//为了显示其中的组件f.pack();//应该最后完成,以避免闪烁,移动,//调整工件的大小.f.setVisible(true);}};//应在 EDT 上创建和更新 Swing GUI//http://docs.oracle.com/javase/tutorial/uiswing/concurrencySwingUtilities.invokeLater(r);}}类管道扩展 JPanel {管道(){设置背景(颜色.黑色);设置前景(颜色.白色);}@覆盖公共无效paintComponent(图形g){super.paintComponent(g);g.drawString("管道游戏出现在这里..", 170, 80);}@覆盖公共维度 getPreferredSize() {//根据需要调整返回新维度(500,150);}}

I'm still very new to java programming, so please help me to correct any mistakes I might have overlooked or give tips on how to improve this program.

Okay, so a lot of problems have been solved, and now I have a CardLayout, but I still have questions about how I should make my pipes show inside it.

When I tried to add in my refresh rate timer and my speed timer, I have problems about how I need to declare and initialize boolean variables.

Also, when I compile and run this game, I get files such as Game$1.class. Is there a way for me to clean this up, and could someone explain why this happens? Do these have an affect on the finished product? (When the game is compiled and packaged into a JAR.)

I want to set playerIsReady to true when the play button is clicked. And from there, when the if statement is true, then switch to a panel that displays the pipes, and start moving the pipe across the screen. Preferably 3 instances of that pipe, each starting at different times, but whatever you can help with is fine.

Some of this code needs work, so I have commented some parts out and left notes.

My other questions about this game can be found here.

This is my current code

Game.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);
    }
}

Pipes.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);
        }
    }
}

PipeObject.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;
    }
}

解决方案

The best way to approach this is using a CardLayout.

Notes

  • A button with an ActionListener is far better than a MouseListener over a rectangle.
    • The button will show focus when the mouse is pointed at it, or the component is tabbed to via the keyboard.
    • The button is keyboard accessible.
    • The button has facility to support multiple icons built in (e.g. for 'initial look', focused, pressed etc.)
  • White space in the GUI is provided around the menu panel and game by adding an EmptyBorder
  • The button is made larger by setting a margin.
  • Adjust margins, borders and preferred size according to need. These sizes were set by me so as not to make the screenshots too large.
  • See more tips in the code comments.

Code

Here is the MCTaRE (Minimal Complete Tested and Readable Example) that produced the above screenshots.

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);
    }
}

这篇关于如何在 jpanel 之间切换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆