簡體   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