【问题标题】:Swing Timer in main class doesn't repaint JFrame class主类中的 Swing Timer 不会重新绘制 JFrame 类
【发布时间】:2015-10-21 01:44:42
【问题描述】:

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

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

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

我尝试更改计时器运行的时间间隔,将摇摆计时器移至 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,以及对FighterListGUIstatic 引用,不可能知道谁实际引用了谁,这只是一堆紧密耦合的意大利面条代码
  • 这也意味着你至少有两个Timers 正在运行
  • TestingGround中,你创建了TestingGround的另一个实例,所以你Qwq的引用与实际显示在屏幕上的实例无关,同样,你创建JFrame 的新实例与您通过 getFrame 返回的 JFrame 实例完全无关!

标签: java swing repaint


【解决方案1】:
  • 您正在创建qwq 的多个实例,在testingGroundKeyboard 中,它们彼此无关,仅意味着您现在每次创建一个新实例时都在创建一个新的Timer其中
  • 在您的testingGround#createGUI 中创建testingGround 的新实例,该实例将添加到JFrame 的新实例中,因此qwq 必须对testingGround 的引用与该实例无关这实际上是在屏幕上!?此外,您在createGUI 中创建了一个新的JFrame 实例,它与您从getFrame 返回的JFrame 实例无关!?

OO 是关于责任的,谁负责什么。例如,您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 分开很容易,但我很懒

【讨论】:

  • 这部分由主要源代码制作而成:protected void paintComponent(Graphics g) {//Drawing super.paintComponent(g); initComponents();.. 最后一个方法(加载图像)应该从构造函数中调用一次。该方法可能也应该重命名(例如loadImage())。
  • 我也确实添加了“addFighter”方法,所以还是有点乱,但感谢校对
猜你喜欢
  • 2015-08-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
相关资源
最近更新 更多