简体   繁体   English

如何使用Swing JPanel在Java中强制重绘?

[英]How do I force a repaint in Java using Swing JPanel?

Why won't my image repaint for a simple animation? 为什么不为简单的动画重新绘制图像? I call repaint() from two different methods and one causes repaint but the other doesn't. 我从两种不同的方法调用repaint(),一种导致重新绘制,而另一种则没有。 The method that does force the repaint is generated from an event listener. 确实重绘的方法是从事件侦听器生成的。 The one that doesn't is a timed animation thread. 没有的是定时动画线程。 I know the animation thread is running correctly, and as long as I continuously slide the slider, it displays perfectly. 我知道动画线程正在正确运行,并且只要我不断滑动滑块,它就可以完美显示。 Help please! 请帮助!
PS yes, I've seen many similar problems here, and I've tried validate, revalidate, and using paint vs paintComponent. PS:是的,我在这里看到了许多类似的问题,并且尝试了验证,重新验证以及使用paint vs paintComponent。 Four classes that comprise the code follow: 组成代码的四个类如下:

import javax.swing.*;

public class gutz{

    public static int windowWidth = 640;
    public static int windowHeight = 480;

    public static void main(String[] args){

        hBod hb1 = new hBod(50, 30, 21, 111, 7, -11);   //mass, radius, xpos, ypos, xvel, yvel
        Thread t1 = new Thread(hb1);

        windowmakr w = new windowmakr();
        w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        w.setSize(windowWidth, windowHeight);
        w.setVisible(true);

        t1.start();
    }
}

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;

public class windowmakr extends JFrame {

    private JSlider slider;
    private drawr panel;

    public windowmakr(){
        super("Orbit Explorer");
        panel = new drawr();
        panel.setBackground(Color.BLACK);

        slider = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 10);
        slider.setMajorTickSpacing(10);
        slider.setPaintTicks(true);

        slider.addChangeListener(
                new ChangeListener(){
                    public void stateChanged(ChangeEvent e){
                        panel.setSpeed(slider.getValue());
                    }
                }
        );

        add(slider, BorderLayout.SOUTH);
        add(panel, BorderLayout.CENTER);

    }

}

import java.awt.*;
import javax.swing.*;

public class drawr extends JPanel{

    private int diameter = 10;
    private static int rad;
    private static int xpos;
    private static int ypos;

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.ORANGE);
        g.fillOval((gutz.windowWidth-diameter)/2, ((gutz.windowHeight-diameter)/2)-40, diameter, diameter);
        g.setColor(Color.CYAN);
        g.fillOval(xpos, ypos, rad, rad);

    }

/*  public void paint(Graphics g){
        super.paint(g);
        g.setColor(Color.ORANGE);
        g.fillOval((gutz.windowWidth-diameter)/2, ((gutz.windowHeight-diameter)/2)-40, diameter, diameter);
        g.setColor(Color.CYAN);
        g.fillOval(xpos, ypos, rad, rad);   
    }
*/  
    public void setSpeed(int newD){
        diameter = (newD >= 0 ? newD : 10);
        repaint();
    }

    public void renderImage(int r, int xp, int yp){
        rad=r;
        xpos=xp;
        ypos=yp;
        repaint();
    }

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

    public Dimension getMinimumSize(){
        return getPreferredSize();
    }
}

public class hBod implements Runnable{

    private int mass;
    private int rad;
    private int xpos;
    private int ypos;
    private double xvel;
    private double yvel;

    public drawr render;

    public hBod(int m, int r, int xp, int yp, double xv, double yv){
        mass=m;
        rad=r;
        xpos=xp;
        ypos=yp;
        xvel=xv;
        yvel=yv;

        render = new drawr();
    }

    public void run(){
        try{
            while(true){
                xpos+=xvel;
                ypos+=yvel;
                yvel+=1;
                System.out.printf("rad - %d, xpos - %d, ypos - %d\n", rad, xpos, ypos);
                render.renderImage(rad, xpos, ypos);

                Thread.sleep(1000);
            }
        }catch(Exception e){}
    }
}

Like I said before, the problem lies in this line render = new drawr(); 就像我之前说的,问题出在这一行render = new drawr(); inside the hBod constructor. hBod构造函数中。 Create a single instance like private drawr panel = new drawr() inside the gutz class and pass it to other two classes using their constructor, like hBod hb1 = new hBod(50, 30, 21, 111, 7, -11, panel) and windowmakr w = new windowmakr(panel) and simply use this reference to point to panel.renderImage(...) inside hBod class and panel.setSpeed(...) from windowmakr class. gutz类中创建一个像private drawr panel = new drawr()gutz ,然后使用其构造函数将其传递给其他两个类,例如hBod hb1 = new hBod(50, 30, 21, 111, 7, -11, panel)windowmakr w = new windowmakr(panel)和简单地使用该引用指向panel.renderImage(...)hBod类和panel.setSpeed(...)windowmakr类。

Here is the modified code, Please learn Java Coding Conventions : 这是修改后的代码,请学习Java编码约定:

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;

public class Gutz {

    public static int windowWidth = 640;
    public static int windowHeight = 480;

    public static void main(String[] args){
        Drawr panel = new Drawr();
        panel.setBackground(Color.BLACK);
        HBod hb1 = new HBod(50, 30, 21, 111, 7, -11, panel);   //mass, radius, xpos, ypos, xvel, yvel
        Thread t1 = new Thread(hb1);

        WindowMakr w = new WindowMakr(panel);
        w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        w.setSize(windowWidth, windowHeight);
        w.setVisible(true);

        t1.start();
    }
}

class WindowMakr extends JFrame {

    private JSlider slider;
    private Drawr panel;    

    public WindowMakr(Drawr p){
        super("Orbit Explorer");
        final Drawr panel = p;        

        slider = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 10);
        slider.setMajorTickSpacing(10);
        slider.setPaintTicks(true);

        slider.addChangeListener(
                new ChangeListener(){
                    public void stateChanged(ChangeEvent e){
                        panel.setSpeed(slider.getValue());
                    }
                }
        );

        add(slider, BorderLayout.SOUTH);
        add(panel, BorderLayout.CENTER);

    }

}

class Drawr extends JPanel{

    private int diameter = 10;
    private static int rad;
    private static int xpos;
    private static int ypos;

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.ORANGE);
        g.fillOval((Gutz.windowWidth-diameter)/2, ((Gutz.windowHeight-diameter)/2)-40, diameter, diameter);
        g.setColor(Color.CYAN);
        g.fillOval(xpos, ypos, rad, rad);

    }

    public void setSpeed(int newD){
        diameter = (newD >= 0 ? newD : 10);
        repaint();
    }

    public void renderImage(int r, int xp, int yp){
        rad=r;
        xpos=xp;
        ypos=yp;
        repaint();
    }

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

    public Dimension getMinimumSize(){
        return getPreferredSize();
    }
}

class HBod implements Runnable{

    private int mass;
    private int rad;
    private int xpos;
    private int ypos;
    private double xvel;
    private double yvel;

    public Drawr render;

    public HBod(int m, int r, int xp, int yp, double xv, double yv, Drawr panel){
        mass=m;
        rad=r;
        xpos=xp;
        ypos=yp;
        xvel=xv;
        yvel=yv;

        render = panel;
    }

    public void run(){
        try{
            while(true){
                xpos+=xvel;
                ypos+=yvel;
                yvel+=1;
                System.out.printf("rad - %d, xpos - %d, ypos - %d\n", rad, xpos, ypos);
                render.renderImage(rad, xpos, ypos);

                Thread.sleep(1000);
            }
        }catch(Exception e){}
    }
}

您可以在JFrame类中使用getContentPane()。repaint()方法

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

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