我的Swing GUI不会更新。为什么?

时间:2013-05-18 18:33:18

标签: java swing jpanel jscrollpane repaint

enter image description here

所以,我正在创建一个GUI,用户可以在其中添加或删除面板。为了模拟这一点,我创建了一个TimerTask,其中包含目标JPanel的名称和包含JPanel的父项。 它倒计数到0,之后它从父节点中删除JPanel并在父节点和祖父节点上调用repaint()

虽然旧面板被删除,但父节点中包含的其他组件却没有取而代之。从图中可以看出,滚动条仍然表示2个组件。

我必须手动向下拖动滚动条以查看它的变化,即下面的组件出现时取而代之。

为什么会这样?

以下是组件嵌套的方式:

JScrollPane (grandparent)
|
|-> JPanel (parent)
    |
    |-> JPanel (target)  

SSCCE是不可能的,因为JPanels填充了来自XML文件的数据并使用JAXB所以..这是不可能的:(但这里是TimerTask的片段

import java.util.TimerTask;
import javax.swing.*;

public class RemoverTask extends TimerTask{
    StudentPanel s;
    JPanel h;
    JScrollPane p;
    public RemoverTask(StudentPanel s,JPanel holder,JScrollPane pane){
        this.s = s;
        h = holder;
        p = pane;
    }

    @Override
    public void run(){
        long x = Integer.MAX_VALUE/2;
        JFrame frame = new JFrame("Counter");
        JTextArea area = new JTextArea();
        JScrollPane pane = new JScrollPane(area);
        pane.setPreferredSize(new java.awt.Dimension(350, 350));
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
        while(x > 100){
            x =  x - 1500;
            area.append("Value of X: " + x + "\n");
        }
        if(!frame.isVisible()){
            frame.dispose();
        }
        h.remove(s);
        h.repaint();
        pane.repaint();
    }
}

1 个答案:

答案 0 :(得分:3)

你仍然可以制作一个sscce,不用担心xml数据等。简化问题,伙计。另外,不要将java.util.Timer与Swing应用程序一起使用,而应使用javax.swing.Timer,Swing Timer。否则,你将对Swing EDT进行Swing更改,这很危险。

问题:您永远不会在容器上调用revalidate()。在对容器进行更改时,通常会在调用容器上的revalidate()之前调用repaint()。 revalidate告诉布局管理器布局他们的组件,这是更改GUI所必需的。