2013-10-10 85 views
1

为什么我的图像不能重绘为简单的动画?我从两个不同的方法调用repaint(),一个导致重绘,但另一个不导致重绘。强制重绘的方法由事件侦听器生成。那个不是定时的动画线程。我知道动画线程正常运行,只要我连续滑动滑块,它就会完美显示。请帮助!
PS是的,我在这里看到很多类似的问题,我试过验证,重新验证和使用paint和paintComponent。四个班组成的代码如下:如何强制使用Swing JPanel在Java中进行重绘?

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){} 
    } 
} 
+2

你有没有打过电话了'repaint'调用(从动画线程)使用'SwingUtilities.invokeLater'因为Swing/AWT是_not_线程安全的? – Neet

+1

为了更好地提供帮助,请提供一个[SSCCE](http://sscce.org) –

+1

即使我找不到重复,这个问题已经回答了好几次:[Here](http:/ /stackoverflow.com/questions/15412260/clever-asynchronous-repaint-in-java)和[这里](http://stackoverflow.com/questions/19061351/repainting-a-jpanel-with-data-from-another- (http://stackoverflow.com/search?page=1&tab=relevance&q= [java]%20repaint%20 from%20another%20read) –

回答

3

就像我之前说的,问题就出在这条线的render = new drawr();构造hBod里面。在gutz类中创建一个像private drawr panel = new drawr()一个实例,并使用其构造传给其他两个类,如hBod hb1 = new hBod(50, 30, 21, 111, 7, -11, panel)windowmakr w = new windowmakr(panel),只需使用该引用从windowmakr类指向panel.renderImage(...)hBod类和panel.setSpeed(...)内。

下面是修改后的代码,请学习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){} 
    } 
} 
+0

太酷了!非常感谢。 (我正在工作jAVA coding convENTIONs。但是它很慢,就像我说的:我只是一个穴居人!再次感谢所有人 – user2671186

+2

但是,我想要求你改变逻辑thingy,而不是使用'Thread'重复一个任务,为此尝试使用[javax.swing.Timer](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html),如[这里所示](http://stackoverflow.com/a/13795187/1057230)。请随时提出任何问题,但仍不清楚。对于其余的你最欢迎和保持微笑:-) –

+0

我要离开几天,但会尝试当我回来。 (忍不住笑了,这真的很有趣!) – user2671186

2

可以使用的getContentPane()重绘()方法,在你的JFrame类

+0

很好用。即使没有环绕'SwingUtilities.invokeLater' ... – chris