繁体   English   中英

如何从 JFrame 中删除 JPanel?

[英]How can I remove a JPanel from a JFrame?

最近我在这里问如何向 JFrame 添加新的 JPanel 答案帮助我获得了一个工作代码。 但不是我有一个相关的问题:“如何删除旧的 JPanel”。 由于以下问题,我需要它。

当我想要时会出现一个新的 JPanel(超过时间限制或用户按下“提交”按钮)。 但是在几秒钟内,旧 JPanel 的某些元素与新 JPanel 的组件一起出现。 我不明白为什么会这样。

我认为这是因为我必须更新窗口的其他线程。 但是第一个线程只添加了一次旧面板(因此,它应该完成)。 在第二个线程中,我有一个坏了的循环(因此,它也应该完成)。

这是我的代码:

private Thread controller = new Thread() {
    public void run() {
        // First we set the initial pane (for the selection of partner).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().add(generatePartnerSelectionPanel());
                frame.invalidate();
                frame.validate();
            }
        });
        // Update the pane for the selection of the parnter.
        for (int i=40; i>0; i=i-1) {
            final int sec = i;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    timeLeftLabel.setText(sec + " seconds left.");
                }
            });
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) { }

            if (partnerSubmitted) {
                break;
            }
        }
        // For the given user the selection phase is finished (either the time is over or form was submitted).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().add(generateWaitForGamePanel());
                frame.invalidate();
                frame.validate();
            }
        });

    }
};

从容器(框架)中删除组件(面板)的最简单方法是保留对它的引用,然后调用Container.remove(Component)即:

private Thread controller = new Thread() {
public void run() {

        final Component panel1 = generatePartnerSelectionPanel();

        // First we set the initial pane (for the selection of partner).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().add(panel1);
                frame.invalidate();
                frame.validate();
        }
        });
        // Update the pane for the selection of the parnter.
        for (int i=40; i>0; i=i-1) {
            final int sec = i;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    timeLeftLabel.setText(sec + " seconds left.");
                }
            });
            try {Thread.sleep(1000);} catch (InterruptedException e) {}
            if (partnerSubmitted) {break;}
        }
        // For the given user the selection phase is finished (either the time is over or form was submitted).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().remove(panel1);
                frame.getContentPane().add(generateWaitForGamePanel());
                frame.invalidate();
                frame.validate();
        }
        });

}
};

我还没有测试过这段代码,但它应该可以工作。

无论您在可见 GUI 上添加还是删除组件,都是一样的:

panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();

我在TextField上的requestFocusInWindow也有问题。 诀窍是不要在JPanel构造函数中构造组件。 但是,创建一个构建方法并在将其添加到框架后执行以下代码。

这对我有用:

frame.getContentPane().removeAll(); //or .remove(previousPanel);
frame.getContentPane().add(newPanel);
panel.buildPanel(); // panel needs a builder method
frame.revalidate(); // in- and validate in one !! 
frame.pack(); // 

如果你想调整大小,你需要preferredSize(); 在面板上或使用repaint()如果您不需要调整框架大小。

Roman,这个问题可以这样解决:

  1. run方法的开头执行此操作:

final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();

  1. 然后做这个

frame.getContentPane().add(partnerSelectionPanel);

  1. 在添加新面板之前,请执行以下操作:

partnerSelectionPanel.setVisible(false);

有用。 我不知道这是否是一个安全和/或优雅的解决方案,但它有效。

    panel.invalidate();
    panel.setVisible(false);
    panel.removeAll();
    frame.getContentPane().remove(panel);
    panel = null;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM