如何使用Swing JPanel在Java中强制重新绘制?
为什么不为一个简单的动画重新绘制我的图像?我从两个不同的方法调用repaint(),其中一个导致repaint,但另一个没有。强制重新绘制的方法是从事件侦听器生成的。没有的是定时动画线程。我知道动画线程正在正确运行,只要我不断滑动滑块,它就会完美地显示。救命啊如何使用Swing JPanel在Java中强制重新绘制?,java,swing,jpanel,repaint,Java,Swing,Jpanel,Repaint,为什么不为一个简单的动画重新绘制我的图像?我从两个不同的方法调用repaint(),其中一个导致repaint,但另一个没有。强制重新绘制的方法是从事件侦听器生成的。没有的是定时动画线程。我知道动画线程正在正确运行,只要我不断滑动滑块,它就会完美地显示。救命啊 是的,我在这里看到了许多类似的问题,我尝试过验证、重新验证以及使用paint vs paintComponent。构成代码的四个类如下所示: import javax.swing.*; public class gutz{ p
是的,我在这里看到了许多类似的问题,我尝试过验证、重新验证以及使用paint vs paintComponent。构成代码的四个类如下所示:
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){}
}
}
正如我前面所说,问题在于这行
render=newdrawr()代码>在hBod
构造函数内。在gutz
类中创建单个实例,如private drawr panel=new drawr()
,并使用其构造函数将其传递给其他两个类,如hBod hb1=new hBod(50,30,21,111,7,-11,panel)
和windowmakr w=new windowmakr(panel)
并简单地使用此引用指向面板。渲染(…)
内部hBod
类和面板。设置速度(…)
来自windowmakr
类
以下是修改后的代码,请学习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()方法您是否尝试过使用SwingUtilities调用repaint
调用(从动画线程)。invokeLater
因为Swing/AWT不是线程安全的?为了更快地获得更好的帮助,即使我找不到重复的,这类问题已经被回答了好几次了:用fast,发布的代码是如何成为SSCCE的?代码可以编译吗?为了它的价值,JComponent重绘方法应该是线程安全的。太酷了!!!非常感谢。(我正在使用jAVA编码约定。但是进展很慢。就像我说的:我只是一个穴居人!再次感谢大家。但是,我想请你们稍微改变一下逻辑,而不是使用线程来重复一项任务,试着使用线程来完成这项任务,如图所示。请随意问任何问题,这仍然不清楚。对于别客气,保持微笑:-)我要离开几天,回来后再试试。(忍不住笑了;这真的很有趣!)仅供参考——我试图比较前后的差异,但您对JAVa编码约定所做的所有更改都受到了干扰。最后我不得不取消你所有的额外工作效果很好。即使没有SwingUtilities.invokeLater的环绕。。。