2017-05-26 44 views
1

这里是我的代码:重绘的不使用javax工作

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 
import javax.swing.SwingUtilities; 

public class Main { 
// code main 
public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setSize(460, 500); 
    frame.setTitle("Circles generator"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 


    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      frame.setVisible(true); 

     } 

    }); 

    String input = JOptionPane.showInputDialog("Enter n:"); 
    CustomComponents0 component = new CustomComponents0(); 
    frame.add(component); 
    frame.getContentPane().validate(); 
     System.out.println("work before"); 
    frame.getContentPane().repaint(); 
     System.out.println("work"); 

    frame.getContentPane().repaint(); 
     System.out.println("work after"); 

} 

// why is not JComponent 
static class CustomComponents0 extends JLabel { 

    private static final long serialVersionUID = 1L; 

    @Override 
    public Dimension getMinimumSize() { 
     return new Dimension(200, 100); 

    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(300, 200); 

    } 

    @Override 
    public void paintComponent(Graphics g) { 
     System.out.println("paint"); 
     int margin = 10; 
     Dimension dim = getSize(); 
     super.paintComponent(g); 
     g.setColor(Color.red); 
     g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2); 

    } 

} 

这里是代码,我想运行工作之前,重绘和运行工作后重绘。 当我运行它,它应该打印

work before 
paint 
work 
paint 
work after 

但只有一个油漆和下班后它的,这是为什么发生?我该如何解决这个问题?

谢谢。

+2

为什么?什么需要修复?为什么要担心精确的何时和如果绘画发生?理解你只能请求一幅不需要的绘画(大部分)。 –

+3

这不是绘画的方式。 “repaint()”只是绘制组件的请求。当你连续有两个请求时,它们被整合到一个请求中。这个逻辑的重点是什么?如果在绘画之间需要一段时间,则可以使用“Swing Timer”。阅读[如何使用Swing定时器](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)上的Swing教程部分。 – camickr

回答

1

must结构和操作的Swing GUI对象仅在event dispatch thread。由于你的程序不正确的同步,任何结果都是可能的。这部分取决于initial thread在启动EventQueue之前得到的距离。此外,println()本身may be synchronized,“发布到EventQueue的事件可以合并。”

下面的变化可靠地显示以下输出,因为事件被分派“按照它们入队的相同顺序。”请特别注意repaint()的呼叫是如何合并的。虽然这种方法是说明性的,但对于您的可能目标来说这是不必要的麻烦。请使用javax.swing.Timer来调整动画,如here所示。

控制台:

paint 
work before 
work 
work after 
paint 

代码:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 

/** @see https://stackoverflow.com/a/44212328/230513 */ 
public class Main { 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      JFrame frame = new JFrame(); 
      frame.setTitle("Circles generator"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      CustomComponent component = new CustomComponent(); 
      frame.add(component); 
      frame.pack(); 
      frame.setLocationRelativeTo(null); 
      frame.setVisible(true); 
      EventQueue.invokeLater(() -> { System.out.println("work before"); }); 
      EventQueue.invokeLater(() -> { frame.repaint(); }); 
      EventQueue.invokeLater(() -> { System.out.println("work"); }); 
      EventQueue.invokeLater(() -> { frame.repaint(); }); 
      EventQueue.invokeLater(() -> { System.out.println("work after"); }); 
     }); 
    } 

    static class CustomComponent extends JLabel { 

     private static final int N = 10; 

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

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      System.out.println("paint"); 
      g.setColor(Color.red); 
      g.fillRect(N, N, getWidth() - N * 2, getHeight() - N * 2); 
     } 
    } 
}