java - 主类中的 Swing Timer 不会重新绘制 JFrame 类

标签 java swing repaint

我有一个主类,它保存对象的数组列表,并有一个 Swing 计时器,用于重新绘制单独的 JFrame 类。尽管调用了重绘方法,但屏幕并未更新。

应该发生什么: 当按下任意键时,两个对象的 x 位置都会更新。每半秒计时一次的 Swing 计时器调用重绘方法。然后在更新的位置重新绘制图像。

据我所知,图像的位置正在更新,因为当我最小化并重新打开 JFrame 窗口时,图像已移动。

我尝试更改计时器运行的间隔,将 Swing 计时器移至 JFrame 类,将 repaint();在一个线程中。但我仍然不知道为什么 repaint();没有更新屏幕。

这是我的代码草图: JFrame类

public class testingGround extends JPanel {
    private Image image;
    private qwq getter = new qwq();
    protected Keyboard keyboard = new Keyboard(); //KeyListener, imported from Keyboard class
    private JFrame frame = new JFrame(); //JFrame variable

public void createGUI(){
    testingGround panel = new testingGround(); // Creating a new JPanel, for objects to be drawn on
    JFrame frame = new JFrame("Game"); //Creating a new JFrame called frame 
    frame.setSize(600, 600); //Setting the size of the JFrame frame to be 600x600
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Setting so the frame exits on close
    frame.setVisible(true);
    frame.add(panel);// Adding the JPanel panel to the JFrame frame, so it's visible 
    frame.addKeyListener(keyboard); //Adding a KeyListener to detect users input in the JFrame frame
}   
public Frame getFrame() { //Constructor class to get JFrame in other classes
    return frame;
}

public void initComponents(){
    ImageIcon imageIcon = new ImageIcon("C:/Users/destr/workspace/GameWIP3/bin/A2.png");
    image =imageIcon.getImage();
}

protected void paintComponent (Graphics g){//Drawing
    super.paintComponent(g);
    initComponents();
    for (int i=0;i<getter.getFListSize();i++)
    {
    System.out.print("paint called");   
    g.drawImage(image, getter.getFighter(i).getFighterX(), getter.getFighter(i).getFighterY(), null);
    }
}
}

键盘类

public class Keyboard implements KeyListener {

private qwq getter = new qwq();

@Override
public void keyPressed(KeyEvent e) {
    getter.getFighter(0).setFighterX(500);;
    getter.getFighter(1).setFighterX(200);; 
    System.out.print("Updated the x value of two");
}

主类

public class qwq implements ActionListener {
private static ArrayList<Fighter> FighterList = new ArrayList<Fighter>(); // ArrayList                                                                          // of                                                               // Fighters
Timer timer = new Timer(500, this);
private static testingGround GUI = new testingGround();

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

public Fighter getFighter(int i) {
    return FighterList.get(i); // To retrieve a fighter from the Array List
}

public void addFighter(Fighter i) {
    FighterList.add(i); // To add a fighter to the Array list
}

public int getFListSize() {
    return FighterList.size();
}

public static void main(String[] args) {
    GUI.createGUI();
    GUI.getFrame();
    FighterList.add(new Fighter(0, 0));
    FighterList.add(new Fighter(20, 50));
}

@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource() == timer) {
        GUI.repaint();
    }
}
}

对象类别

public class Fighter { 

    private int fighterX;
    private int fighterY;

public Fighter ( int fighterX, int fighterY) {
this.setFighterX(fighterX);
this.setFighterY (fighterY);
}

public int getFighterX (){
return fighterX; //method to get x coordinate of a fighter
}

public int getFighterY (){
return fighterY;//method to get y coordinate of a fighter
}

public void setFighterX(int fighterX) {
this.fighterX = fighterX; //method to set the x coordinate of a fighter
}

public void setFighterY(int fighterY) {
this.fighterY = fighterY; //method to set the y coordinate of a fighter
}
}

最佳答案

  • 您正在创建 qwq 的多个实例,在 testingGroundKeyboard ,这些彼此无关,仅意味着您现在正在创建一个新的 Timer每次创建它的新实例时
  • 在您的testingGround#createGUI中您创建 testingGround 的新实例,它被添加到 JFrame 的新实例中,所以引用qwq必须testingGround与屏幕上实际出现的实例无关!?此外,您创建 JFrame 的新实例在createGUIJFrame 的实例没有关系您从 getFrame 返回!?

面向对象就是责任,谁负责什么。例如,您testingGround类不应该制作框架,这不是它的责任。它应该负责渲染游戏的当前状态。

例如...

import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Qwq {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestingGround());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Keyboard extends KeyAdapter {

        private List<Fighter> fighterList;

        public Keyboard(List<Fighter> fighterList) {
            this.fighterList = fighterList;
        }

        @Override
        public void keyPressed(KeyEvent e) {
            fighterList.get(0).setFighterX(500);
            fighterList.get(1).setFighterX(200);
            System.out.print("Updated the x value of two");
        }
    }

    public class TestingGround extends JPanel {

        private ArrayList<Fighter> fighterList = new ArrayList<>(); 

        private Image image;
        private Keyboard keyboard;

        public TestingGround() {
            loadImages();
            addKeyListener(new Keyboard(Collections.unmodifiableList(fighterList)));
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            });
            timer.start();
        }

        public void loadImages() {
            ImageIcon imageIcon = new ImageIcon("C:/Users/destr/workspace/GameWIP3/bin/A2.png");
            image = imageIcon.getImage();
        }

        protected void paintComponent(Graphics g) {//Drawing
            super.paintComponent(g);
            for (Fighter fighter : fighterList) {
                System.out.print("testing");
                g.drawImage(image, fighter.getFighterX(), fighter.getFighterY(), null);
            }
        }
    }

    public static class Fighter {

        private int fighterX;
        private int fighterY;

        public Fighter(int fighterX, int fighterY) {
            this.setFighterX(fighterX);
            this.setFighterY(fighterY);
        }

        public int getFighterX() {
            return fighterX; //method to get x coordinate of a fighter
        }

        public int getFighterY() {
            return fighterY;//method to get y coordinate of a fighter
        }

        public void setFighterX(int fighterX) {
            this.fighterX = fighterX; //method to set the x coordinate of a fighter
        }

        public void setFighterY(int fighterY) {
            this.fighterY = fighterY; //method to set the y coordinate of a fighter
        }
    }
}

现在,很容易得到 Timer分开,但我太懒了

关于java - 主类中的 Swing Timer 不会重新绘制 JFrame 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33249603/

相关文章:

java - 如何在 Spark Streaming 应用程序中从 Kafka 接收 Java 对象

java - JDK 类中 java.lang.ref.WeakReference 对象的内存泄漏

Java JPanel 平铺背景图像

java - Java 小程序上的paint() 设置为无限循环。我如何避免我的方法做同样的事情?

Java编程-循环链表

java - jackson 动态属性名称

java - 需要设计方案 : Enabling menu item from outside JFrame

java - 在左对齐的 JTabbedPane 上强制水平制表 rune 本

java - 重新绘制 JPanel

java - JFrame Paint() 上的 NullPointerException