简体   繁体   English

JFrame repaint(); 错误

[英]JFrame repaint(); error

So, I'm currently working on making a ball that moves on keyboard command. 因此,我目前正在制作一个可以通过键盘命令移动的球。 My problem is that when I call repaint(); 我的问题是当我调用repaint(); , it gives me an error saying that it "Cannot make a static reference to the non-static method repaint() from the type Component." ,这给了我一个错误,说它“无法对Component类型的非静态方法repaint()进行静态引用”。 What am I doing wrong? 我究竟做错了什么?

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

public class App extends JFrame{

    JFrame f = new JFrame();
    public static int keyVal = 0, x = 10, y = 10;
    public static void main(String[] args) {
        new App();   
        Ball();
        while(true){
        System.out.println(keyVal);
        try{
            Thread.sleep(50);
        }
        catch(Exception e){}

        }
    }

    public static void Ball(){
        while(true){
            if(keyVal == 65){
            x = x -1;
            }
            else if(keyVal == 68){
            x = x + 1;
            }
        repaint();
        //repaint(x, y, 10, 20);
        }
    }

    public App(){
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setTitle("Pong");
        f.setSize(30,40);

        f.setLocationRelativeTo(null);

        f.addKeyListener(new KeyListener(){
            public void keyPressed(KeyEvent e){
                keyVal = e.getKeyCode();
            }

            public void keyReleased(KeyEvent e){
                keyVal = 0;
            }

            public void keyTyped(KeyEvent e){}
        });
        f.add(new MyPanel());
        f.pack();
        f.setVisible(true);
    }

    class MyPanel extends JPanel {
        public MyPanel() {
            setBorder(BorderFactory.createLineBorder(Color.black));
        }

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

        public void paintComponent(Graphics g) {
            super.paintComponent(g);       
            System.out.println("test");
            g.setColor(Color.orange);
            g.fillRect(x, y, 10, 20);
        }  
    }    
}
  1. Your class is already a JFrame subclass. 您的类已经是JFrame子类。 There's no need to create another JFrame . 无需创建另一个JFrame Take out the JFrame f = new JFrame() and all the f.method(..) just use method(..) 取出JFrame f = new JFrame()和所有f.method(..)只需使用method(..)

  2. Don't use while(true) or Thread.sleep() . 不要使用while(true)Thread.sleep() You will run into problem. 您会遇到问题。 Instead look into How to use a Swing Timer . 而是研究如何使用Swing计时器 Here is a simple example . 这是一个简单的例子 You could also find many other examples just doing a simple google search on how to use Swing Timer 您还可以找到许多其他示例,就如何使用Swing Timer做一个简单的Google搜索

  3. No need to setSize() to the frame, you already pack() it. 无需将setSize()设置为框架,您已经将其pack()了。

  4. You should look into How to use Key Bindings . 您应该研究如何使用键绑定 If not now, you will come to find that there are focus issues, among other things, with using a KeyListener . 如果不是现在,您将发现使用KeyListener会带来焦点问题。

  5. Run your program from the Event Dispatch Thead , like this 像这样从Event Dispatch Thead运行程序

     public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { new App(); } }); } 

Freebie 赠品

A simple implementation of a javax.swing.Timer would be something like this 一个javax.swing.Timer简单实现就是这样

public App() {
    ...
    Timer timer = new Timer(50, new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            // do something
        }
    });
}

Here is the basic construct of the Timer 这是Timer的基本结构

Timer( int dalay, ActionListener listener )

The delay it the amount of milliseconds delayed for each time the event is fired. 延迟是每次触发事件时延迟的毫秒数。 So in the above code, for every 50 milliseconds, something will happen. 因此,在上面的代码中,每隔50毫秒就会发生一些事情。 This will achieve what you are trying to do with the Thread.sleep . 这将实现您正在尝试使用Thread.sleep You can call the repaint() from inside the actionPerformed 您可以从actionPerformed内部调用repaint()


Here's a simple refactor of your code, that you can test out 这是代码的简单重构,您可以测试一下

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class App extends JFrame {

    private MyPanel panel = new MyPanel();
    public static int keyVal = 0, x = 10, y = 10;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new App();
            }
        });
    }

    public App() {
        Timer timer = new Timer(50, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                    x = x + 5;

                panel.repaint();
            }
        });
        timer.start();

        add(panel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Pong");
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    class MyPanel extends JPanel {

        public MyPanel() {
            setBorder(BorderFactory.createLineBorder(Color.black));
        }

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

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println("test");
            g.setColor(Color.orange);
            g.fillRect(x, y, 10, 20);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM