【问题标题】:box isn't appearing or moving on JPanel.. Java框没有出现或在 JPanel 上移动.. Java
【发布时间】:2017-03-12 09:09:20
【问题描述】:

我正在尝试在我的 Java 面板 1 上创建此框,但屏幕上没有显示任何内容:/ 有什么问题?抱歉,我是 Java 动画的新手,它太难了!另外,我希望该框仅出现在第一个面板上而不是第二个面板上移动。这是我的代码。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class frog extends JPanel implements ActionListener{
    JFrame frame= new JFrame();
    JPanel panel=new JPanel();
    JButton button = new JButton("Hungry");
    JPanel panel2=new JPanel();
    JTextField t;
    Timer tm= new Timer(5, this);
    int x=0, velX=2;
    public void paintComponent(Graphics g){
        super.paintComponents(g);
        g.setColor(Color.RED);
        g.drawRect(100,10,30,40);
        g.fillRect(x,10,20,10);
        tm.start();
    }
    JLabel l= new JLabel("Good");
    frog(){
        panel.setBackground(Color.CYAN);
        panel2.setBackground(Color.GREEN);
        t= new JTextField("Frog is hungry",10);
        panel2.add(t);
        panel2.add(button);
        frame.add(panel,BorderLayout.CENTER);
        frame.add(panel2,BorderLayout.PAGE_END);
        button.addActionListener(this);
        frame.setSize(500,400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        frog f= new frog();

    }


    @Override
    public void actionPerformed(ActionEvent e) {
        t.setText("Now he is full");
        x=x+velX;
        repaint();
    }

}

【问题讨论】:

  • 欢迎来到 Stack Overflow!看起来你可能正在寻求家庭作业帮助。虽然我们对此本身没有任何问题,但请注意这些dos and don'ts,并相应地编辑您的问题。 (即使这不是家庭作业,也请考虑建议。)
  • 当我对您的代码摸不着头脑时,请阅读 Painting in AWT and SwingPerforming Custom Painting 以更好地了解绘画在 Swing 中的工作原理

标签: java arrays swing animation jpanel


【解决方案1】:

让我们停下来看看你做了什么。

你已经创建了一个继承自 JPanel 的类

public class Frog extends JPanel implements ActionListener {

好的。你已经覆盖了paintComponent 来做一些自定义绘画

@Override
public void paintComponent(Graphics g) {
    super.paintComponents(g);
    g.setColor(Color.RED);
    g.drawRect(100, 10, 30, 40);
    g.fillRect(x, 10, 20, 10);
    tm.start();
}

好的,这里有一些问题,但让我们继续。在面板的构造函数中,您创建了两个新面板,您已将这两个面板添加到 JFrame 并使其可见

Frog() {
    panel.setBackground(Color.CYAN);
    panel2.setBackground(Color.GREEN);
    t = new JTextField("Frog is hungry", 10);
    panel2.add(t);
    panel2.add(button);
    frame.add(panel, BorderLayout.CENTER);
    frame.add(panel2, BorderLayout.PAGE_END);
    button.addActionListener(this);
    frame.setSize(500, 400);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

但是等等,Frog 面板永远不会被添加到任何东西,那么它应该如何显示呢?

此外,构造函数有一些非常讨厌的副作用,抛开不相关的面板,它会在调用时创建一个框架,这真是个坏主意。

基本面向对象

使用 OO,您希望将任何对象的功能限制为单一职责,Frog 面板不负责创建其他面板(它们不会向 Frog 面板添加任何功能)或制作框架,它是职责是给青蛙上色和动画,仅此而已。

public class FrogPane extends JPanel {

    private Timer timer;
    int x = 0, velX = 2;

    public FrogPane() {
        timer = new Timer(40, new ActionListener() {
                                        @Override
                                        public void actionPerformed(ActionEvent e) {
                                            x = x + velX;
                                            repaint();
                                        }
                                    });
        setBackground(Color.CYAN);
    }

    public void start() {
        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(Color.RED);
        g2d.drawRect(100, 10, 30, 40);
        g2d.fillRect(x, 10, 20, 10);
        g2d.dispose();
    }

}

好的,FrogPane 非常基本,它描绘了青蛙的表示并通过使用Timer 更新位置。请注意Timer 不是在paintComponent 中启动的,paintComponent 可以由于多种原因被调用,其中许多原因是您无法控制的,所以不要在其中做任何可能改变状态的事情组件或您依赖于执行某些次要任务的组件

接下来我们需要做的是显示它并有一些方法来启动它

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                FrogPane frogPane = new FrogPane();

                JTextField t = new JTextField("Frog is hungry", 10);
                JButton button = new JButton("Hungry");

                JPanel actionPane = new JPanel();
                actionPane.setBackground(Color.GREEN);
                actionPane.add(t);
                actionPane.add(button);
                button.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        t.setText("Run frog run");
                        frogPane.start();
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(frogPane);
                frame.add(actionPane, BorderLayout.PAGE_END);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

所以,你的下一个问题是如何管理不同类之间的状态,这对我来说意味着你需要离开,对Model-View-Controller 做更多的研究,更好地理解职责分离的概念。基本答案是,您使用模型。

【讨论】:

  • 天啊,非常感谢你。真的帮助我理解了一些东西。由于我是 java gui 编程的新手,我肯定会遇到一些问题。希望你能继续帮助我!再次感谢
【解决方案2】:

您正在为frog 类定义动画,但您并未将frog 面板添加到JFrame。您的第一个面板是一个普通的 Jpanel,它没有关联的 paintComponent 覆盖。

你应该:

  1. 删除线

    JPanel panel=new JPanel();
    
  2. 代替

    panel.setBackground(Color.CYAN);
    

    使用

    this.setBackground(Color.CYAN);
    
  3. 代替

    frame.add(panel,BorderLayout.CENTER);
    

    使用

    frame.add(this,BorderLayout.CENTER);
    

现在第一个面板将是当前创建的frog,您应该可以看到动画。

注意事项:

  • 请注意 Java 语言约定。类名应以大写字母开头(Frog 而不是frog)。
  • 请注意,您的actionPerformed 正被计时器和按钮使用。你确定这是你想要的吗?另外,我认为您不太可能希望在每次重新绘制面板时都启动计时器。

【讨论】:

  • 嗨,对不起,我不太明白.. 那我该如何声明面板呢?我很抱歉听起来很愚蠢,但 java gui 对我来说是一个新事物,它令人困惑..
  • @thefeels 我给了你三件事,你必须在源代码中进行更改。您无需声明面板,因为您在 inside 面板中,this 引用就是您的面板。
猜你喜欢
  • 2016-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多