为什么我的JFrame重画不像我告诉它的那样?

时间:2014-10-22 01:18:13

标签: java swing jframe jpanel repaint

在实例化我修改过的JPanel类时,我通过构造函数传入一个文件。后来在paint方法中读取了文件(XML)并使用了数据。但是,在我解析数据之后,我同时调用repaint()revalidate(),但我的GUI看起来完全一样。我在扩展JFrame的主类和扩展JPanel的面板类中调用这些方法。

当我从JFileChooser中选择一个xml文件时,drawPanel类会被其他构造函数实例化,接收文件并解析它,然后调用repaint和{{1 }}。我省略了大部分代码以节省您的时间。

这里是主要班级'代码:

revalidate

这是我的drawPanel类:

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();}
}

我的代码与上面相同,只是有更多细节。为什么我的JFrame重新粉刷?

2 个答案:

答案 0 :(得分:4)

下面:

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

了解在Swing事件线程上调用时,Thread.sleep(...)对Swing GUI的作用 - 它将恰好是Swing事件线程的当前线程(负责所有绘图和用户交互的线程)置于睡眠状态。换句话说,您将整个应用程序完全置于睡眠状态。

解决方案 - 不要在事件线程上调用永远

顺便说一句,将每个方法调用放在自己的行上是没有成本的,没有理由你发布的那条长行没有任何目的,除了混淆。

答案 1 :(得分:4)

try{Thread.sleep(500);revalidate();repaint();}catch(InterruptedException eeee){}最有可能阻止事件调度线程,阻止处理事件队列并使其看起来像程序已挂起。

有关详细信息,请参阅Concurrency in Swing ...

建议不要覆盖paint的Swing组件,而是使用paintComponent,有关详细信息,请参阅Performing Custom Painting

在您的情况下,我建议您使用javax.swing.Timer代替Thread.sleep,有关详细信息,请参阅How to use Swing Timers

<强>更新

我没有看到代码中的任何位置会将drawRoadfalse更改为true,因此您的paint方法正在绘制...没有... 。所以我猜你的画框就像你告诉它的那样......

您可能还想看一下Initial Threads,您可能希望阅读Code Conventions for the Java TM Programming Language,这样可以让人们更轻松地阅读您的代码并让您阅读其他人< / p>

<强>更新

鉴于您的示例不完整且无法编译,当我重建它时,这将有效...

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大小的组件......