2014-10-22 56 views
0

当实例化我修改的JPanel类时,我通过构造函数传入一个文件。文件(XML)被读取,稍后在paint方法中我将使用该数据。但是,在解析数据后,我同时调用了repaint()revalidate(),但我的GUI看起来完全一样。我将这些方法称为JFrame的主类和JPanel的面板类。为什么我的JFrame不像我告诉的那样重新绘制?

当我选择从我JFileChooser一个XML文件中,drawPanel类获取与它的其它构造函数实例,同时在文件中,并解析它,然后调用repaintrevalidate。我省略了大部分代码以节省您的时间。

这里的主类的代码:

public class myCode extends JFrame { 
    public myCode() { 
    super("Roadway Simulator"); 

    setSize(800, 600); 
    setLocationRelativeTo(null); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setLayout(null); 
    drawie = new drawPanel(); 
    drawie.setSize(new Dimension(width - 200, height)); 
    drawie.setMinimumSize(new Dimension(width - 200, height)); 
    drawie.setMaximumSize(new Dimension(width - 200, height)); 
    drawie.setLocation(0, 0); 
    add(drawie); 

    setVisible(true); 

    try{Thread.sleep(500);revalidate();repaint();}catch(InterruptedException eeee){} 
} 
    public static void main(String[] args){new myCode();} 
} 

这里是我的drawPanel类:

class drawPanel extends JPanel { 
    boolean drawRoad = false; 
    public drawPanel() { 
    super(); 
    } 
    public drawPanel(Document doc){ 
    super(); 
    //the change in my paint method 
    drawRoad = true; 
    revalidate(); 
    repaint(); 
    } 
    public paint(Graphics g){ 
    super.paint(g); 
    if(drawRoad){ 
     g.setColor(Color.BLACK); 
     g.fillRect(0,0,600,600); 
    } 
    } 
} 

我的代码是上面一样,只是多了很多细节。为什么不是我的JFrame重新绘制?

+1

避免使用'null'布局,像素完美的布局是现代UI设计中的幻想。影响组件的个体大小的因素太多,其中没有一个可以控制。 Swing旨在与布局经理一起工作,放弃这些将导致问题和问题的终结,您将花费越来越多的时间来尝试纠正 – MadProgrammer 2014-10-22 01:23:12

+0

[我是否应避免使用set(Preferred | Maximum | Minimum)在Java Swing中的大小方法?](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi) - 但在你的情况,因为你''使用'null'布局,它们将无效...... – MadProgrammer 2014-10-22 01:23:42

回答

4

这里:

try{Thread.sleep(500);revalidate();repaint();}catch(InterruptedException eeee){} 

了解什么Thread.sleep(...)做一个Swing GUI的Swing事件线程中调用时 - 它把当前线程这恰好是Swing事件线程,该负责所有绘制一个和用户交互,入睡。换句话说,你把你的整个应用程序完全睡觉。

解决方案 - 请勿在事件线程上将此永远调用。除此之外,将每个方法调用放在自己的行上并没有任何代价,也没有任何理由让您发布那条长行,因为除了混淆之外,它没有任何其他用途。

+0

我们可以**大胆** **永远**,这就像我今天解决的唯一问题... – MadProgrammer 2014-10-22 01:22:46

+0

@MadProgrammer :当然,我们看到了很多。 – 2014-10-22 01:23:32

4

try{Thread.sleep(500);revalidate();repaint();}catch(InterruptedException eeee){}很可能会阻止事件分派线程,阻止处理事件队列并使其看起来像您的程序已挂起。

Concurrency in Swing了解更多详情...

它也建议不要覆盖Swing组件的paint,而使用paintComponent,看到Performing Custom Painting更多细节

在你的情况,我会建议使用javax.swing.Timer代替Thread.sleep,看到How to use Swing Timers更多细节

更新

我没有看到你的代码的任何地方,将来自false改变drawRoadtrue,所以你paint方法是画...没有...所以我猜你帧画正是你告诉它的方式。 ..

你可能也想看看Initial Threads,你可能想通过Code Conventions for the Java TM Programming Language有一读,它将使人们更容易阅读您的代码,供您阅读别人

更新

既然你的例子是不完整的,将无法编译,当我重建它,这将工作...

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import org.w3c.dom.Document; 

public class TestDraw extends JFrame { 

    public TestDraw() { 
     super("Roadway Simulator"); 

     setSize(800, 600); 
     setLocationRelativeTo(null); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     DrawPanel drawie = new DrawPanel(null); 
     add(drawie); 

     setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       new TestDraw(); 

      } 
     }); 
    } 

    class DrawPanel extends JPanel { 

     boolean drawRoad = false; 

     public DrawPanel() { 
      super(); 
     } 

     public DrawPanel(Document doc) { 
      super(); 
      drawRoad = true; 
      revalidate(); 
      repaint(); 
     } 

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

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (drawRoad) { 
       g.setColor(Color.BLACK); 
       g.fillRect(0, 0, getWidth(), getHeight()); 
      } 
     } 
    } 
} 

如果我改变DrawPanel drawie = new DrawPanel(null);DrawPanel drawie = new DrawPanel();它仍然绘画,但不执行您的自定义绘画。

另一个问题是,正如已经强调的,是用null布局避免使用null布局

,像素完美的布局是现代的UI设计中的错觉。影响组件的个体大小的因素太多,其中没有一个可以控制。 Swing旨在与布局经理一起工作,放弃这些将导致无法结束的问题和问题,您将花费越来越多的时间来尝试纠正。

看一看Why is it frowned upon to use a null layout in SWING?了解更多详情...

现在,话虽如此,当你添加drawie,你从来没有给它一个尺寸,Swing是足够聪明,不画0x0大小的组件...

+0

即使没有Thread.sleep(500);我的GUI仍然不更新 – 2014-10-22 01:24:27

+0

@JonathanAllenGrant为什么它应该''drawRoad'是'false' ... – MadProgrammer 2014-10-22 01:25:20

+0

@JonathanAllenGrant:的确,你永远不会调用改变状态的构造函数。您只能调用默认构造函数,即不带参数的构造函数。那个不会改变drawRoad。 – 2014-10-22 01:28:00

相关问题