代码之家  ›  专栏  ›  技术社区  ›  Turtled

repaint()方法不重新绘制JPanel

  •  0
  • Turtled  · 技术社区  · 10 年前

    好的,所以首先我知道关于这个问题还有很多其他线程,但他们只说尝试使用validate()和validate(),这对我没有任何影响。

    我的问题是——正如标题所示——JPanel的repaint()方法无法重新绘制。我在paintComponent()方法中添加了一些调试消息,下面是控制台输出:

    Debug
    -10 421 010 441
    repainted
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    Moved mouse
    

    请注意,您只看到 debug , (co-ordinates) 和 repainted 有一次,在程序开始时,我调用了repaint();每次移动鼠标时。

    我将我的五个类添加到一个类中,因为我相信出于调试目的,它是首选的:

    package com.trtld.spacewar;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    
    public class GroupClass {
         private static Content content = new Content();
    
        public static void main(String[] args) {
            JFrame window = new JFrame("Spacewar!");
            content.setVisible(true);
            window.setContentPane(content);
            MouseInput listener = new MouseInput();
            content.addMouseMotionListener(listener);
            content.addMouseListener(listener);
            window.setSize(600, 480);
            window.setLocation(100, 100);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.setVisible(true);
            //window.setResizable(false);
            System.out.println("Debug");
        }
    
    
    }
    
     class Target {
    
        private int x1, y1;
        private int x2, y2;
    
        public Target(int x1, int y1, int x2, int y2){
            this.x1 = x1; 
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
    
        }
    
        public int getX1(){
            return x1;
        }
        public int getX2(){
            return x2;
        }
        public int getY1(){
            return y1;
        }
        public int getY2(){
            return y2;
        }
    }
    class Content extends JPanel{
    
            private static Content instance;
            private Target[] targets = new Target[9];   
            private Bullet[] bullets = new Bullet[999];//assuming no more than 1000 bullets are on the screen at
                                                      //once (they'd have to have a really fancy-nice auto-clicker ha ha)
            int spaceShipX = (getWidth()/2); 
    
    
    
    
    
            public Content (){
                int yLevel = (((int)Math.random())*(getHeight() / 4));
                int xPos = ((int)Math.random())*getWidth();
                for(int i = 0;!(i == 9); i++){                                         //Create the randomly located targets
                    targets[i] = new Target(xPos, yLevel, xPos-15, yLevel-10);
                }
            }
    
            public void paintComponent(Graphics g){
                 super.paintComponent(g);  
                 g.setColor(Color.RED);
                 System.out.println(spaceShipX-10 + " " + (getHeight()-20) + " " + spaceShipX+10 + " " + getHeight());
                 System.out.println("repainted");
                 g.fillRect(spaceShipX+50, getHeight()-20 ,spaceShipX+100 , getHeight());
    
                 /**  //commented out for simplicity + needs to be fixed:
                    for(Target t : this.targets){        //paint targets
                        g.drawRect(t.getX1(), t.getY1(), t.getX2(), t.getY2());
                    }
                    for(Bullet b : this.bullets){         //paint bullets and remove invalid ones plus check for hits
                        if(b != null){
    
    
                        g.drawRect(b.getX1(), b.getY1(), b.getX2(), b.getY2());
    
                        if(!(b.checkTargetPresence() == null)){
                            for(Target target : targets){
                                if(b.checkTargetPresence() == target){
                                    target = null;
                                }
                            }
                        }
    
                        if(b.isValid() == false){
                            b = null;
                        }
                    }
                    }*/
            }
    
    
            public static Content getInstance(){
                if(instance == null) {
                    instance = new Content();     //TODO: Singletons are out-dated and not preferred; fix this
                    }
                    return instance;
            }
    
    
        //Getters and setters:
    
            public Bullet[] getBullets(){
                return bullets;
            }
    
            public Target[] getTargets(){
                return targets;
            }
    
            public void setTarget(Target t, int loc){
                this.targets[loc] = t;
            }
    
            public void setBullet(Bullet b){
                int location = -1;
                if(bullets[0] == null){
                this.bullets[0] = b;
                return;
                }
                for(Bullet bullet: bullets){
                    location++;
                if(bullets[location] == null){ //TODO: Messy, clean this up
                    bullets[location] = b;
                    return;
                }   
                }
    
            }
            public int getSpaceShipX(){
            return spaceShipX;
            }
            public void setSpaceShipX(int x){
                spaceShipX = x-10;
                repaint();
    
            }
    
        }
    class Bullet implements ActionListener{
    
        int x1, x2;
        int y1 = 10, y2 = 5;
    
        Timer timer = new Timer(250, this);
    
        public Bullet(int x1, int x2){
            this.x1 = x1;
            this.x2 = x2;
            timer.start();
        }
    
        public void actionPerformed(ActionEvent evt) {
            y1 = y1 + 2;
            y2 += 2;
            Content.getInstance().repaint();
        }
    
        public Target checkTargetPresence(){
            for(Target t : Content.getInstance().getTargets()){
                if(x1 <= t.getX1() && x1 >= t.getX2()){
                    if(y1 <= t.getY1() && y1 >= t.getY2()){
                             //HIT!
                        return t;
                    }
                }
            }
            return null; //TODO
    
        }
    
        public boolean isValid(){//Checks if the bullet is still on the screen
    
            if(y1 >= Content.getInstance().getHeight() || y2 >= Content.getInstance().getHeight()){
                return false;
            }else{
                return true;
            }
    
        }
        public int getX1(){
            return x1;
        }
        public int getX2(){
            return x2;
        }
        public int getY1(){
            return y1;
        }
        public int getY2(){
            return y2;
        }
    }
    class MouseInput implements MouseListener, MouseMotionListener {
    
        public void mouseDragged(MouseEvent arg0) {     
        }
    
        public void mouseMoved(MouseEvent evt) {
            Content.getInstance().setSpaceShipX(evt.getX());
            Content.getInstance().repaint(); // I try to repaint here and in the Content class, but nothing happens.
            System.out.println("Moved mouse");
        }
    
        public void mouseClicked(MouseEvent arg0) {
    
        }
    
        public void mouseEntered(MouseEvent arg0) {     
        }
    
        public void mouseExited(MouseEvent arg0) {      
        }
    
        public void mousePressed(MouseEvent evt) {  
        Content.getInstance().setBullet(new Bullet(evt.getX()-2, evt.getX()+2));
        System.out.println("clicked");
        }
    
        public void mouseReleased(MouseEvent arg0) {    
        }
    
    }
    

    我非常感谢任何帮助,如果我需要不同的格式,请告诉我。 请注意,这是我的第一个GUI程序。

    1 回复  |  直到 10 年前
        1
  •  2
  •   camickr    10 年前

    我认为问题是您创建了一个Content类,然后将其添加到框架中。

    然而,在MouseListener代码中,您调用 getInstance() 方法,并且“instance”变量为空,因此会创建一个新的Content实例(但从未添加到框架中,因此它永远不会被绘制)。

    所以这个基本逻辑是错误的,你不想创建一个新的实例。

    相反,在Content类的构造函数中,您只需执行以下操作:

    instance = this;
    

    然后getInstance()方法将只返回变量,因为它总是有一个值。

    此外,MouseListeners应该是Content类中的内部类。也就是说,您应该创建侦听器并将其添加到类中。当您这样做时,您甚至不需要静态getInstance()方法,因为您可以直接访问实例变量。

    但他们只说尝试使用validate()和validate(),这对我没有任何影响。

    你不应该使用那些方法。这些用于AWT。在Swing中,您可以使用:

    revalidate();
    repaint();
    

    当您在GUI可见后向GUI添加组件时,或者当您更改自定义类中的属性时。revalidate()将调用布局管理器。重新绘制()将绘制组件。在您的类中,您不需要更改任何内容的大小,因此您只需要在setter方法中重新绘制()。

    编辑:

    介意分享你添加的代码吗?

    我添加了一行代码:

        public Content (){
            int yLevel = (((int)Math.random())*(getHeight() / 4));
            int xPos = ((int)Math.random())*getWidth();
            for(int i = 0;!(i == 9); i++)   { 
                 //Create the randomly located targets
                targets[i] = new Target(xPos, yLevel, xPos-15, yLevel-10);
            }
    
            instance = this; // added
        }
    

    一次只做一次改变。一旦您通过添加单行代码验证了我的假设是正确的。然后你可以把班上的其他人收拾一下。如果你一次做了多个更改,你就不知道是哪一个导致了问题。