Recently I asked here how to add a new JPanel to JFrame. The answer helped me to get a working code. But not I have a related question: "How can I remove an old JPanel". I need that because of the following problem.
最近我问这里如何将新的JPanel添加到JFrame。答案帮助我获得了一个有效的代码。但不是我有一个相关的问题:“我怎样才能删除旧的JPanel”。因为以下问题我需要它。
A new JPanel appears appears when I want (either time limit is exceeded or user press the "Submit" button). But in several seconds some element of the old JPanel appears together with the component of the new JPanel. I do not understand why it happens.
当我想要时出现一个新的JPanel(超出时间限制或用户按下“提交”按钮)。但是在几秒钟内,旧JPanel的一些元素与新JPanel的组件一起出现。我不明白为什么会这样。
I thought that it is because I have to other threads which update the window. But the first thread just add the old panel once (so, it should be finished). And in the second thread I have a loop which is broken (so, it also should be finished).
我认为这是因为我必须更新窗口的其他线程。但是第一个线程只添加一次旧面板(因此,它应该完成)。在第二个线程中,我有一个被破坏的循环(因此,它也应该完成)。
Here is my code:
这是我的代码:
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();
}
});
}
};
5 个解决方案
#1
7
the easiest way to remove a component (panel) from a container (frame) is to keep a reference to it, and then call Container.remove(Component)
ie:
从容器(框架)中删除组件(面板)的最简单方法是保持对它的引用,然后调用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();
}
});
}
};
i haven't tested this code but it should work.
我没有测试过这段代码,但它应该可行。
#2
8
Its the same whether you do add or remove a component on a visible GUI:
无论是在可见GUI上添加或删除组件,都是一样的:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
#3
1
I had problems with requestFocusInWindow
on TextField
too. The trick is to not construct the components in the JPanel
constructor. But, make a build method and execute following code after it has been added to the frame.
我在TextField上也遇到了requestFocusInWindow的问题。诀窍是不在JPanel构造函数中构造组件。但是,创建一个构建方法并在将代码添加到框架后执行以下代码。
This worked for me:
这对我有用:
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(); //
if you want to resize, you need preferredSize();
on panel or use repaint()
if you don't need to resize frame.
如果你想调整大小,你需要preferredSize();在面板上或使用repaint()如果您不需要调整框架大小。
#4
0
Roman, the problem can be solved like that:
罗马,这个问题可以这样解决:
- Do this in the beginning of your
run
method: - 在run方法的开头执行此操作:
final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();
最终JPanel partnerSelectionPanel = generatePartnerSelectionPanel();
- Then do this
- 然后这样做
frame.getContentPane().add(partnerSelectionPanel);
frame.getContentPane()添加(partnerSelectionPanel)。
- Before you add the new panel do this:
- 在添加新面板之前,请执行以下操作:
partnerSelectionPanel.setVisible(false);
partnerSelectionPanel.setVisible(假);
It works. I do not know if it is a safe and/or elegant solution but it works.
有用。我不知道它是否是一个安全和/或优雅的解决方案,但它的工作原理。
#5
0
panel.invalidate();
panel.setVisible(false);
panel.removeAll();
frame.getContentPane().remove(panel);
panel = null;
#1
7
the easiest way to remove a component (panel) from a container (frame) is to keep a reference to it, and then call Container.remove(Component)
ie:
从容器(框架)中删除组件(面板)的最简单方法是保持对它的引用,然后调用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();
}
});
}
};
i haven't tested this code but it should work.
我没有测试过这段代码,但它应该可行。
#2
8
Its the same whether you do add or remove a component on a visible GUI:
无论是在可见GUI上添加或删除组件,都是一样的:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
#3
1
I had problems with requestFocusInWindow
on TextField
too. The trick is to not construct the components in the JPanel
constructor. But, make a build method and execute following code after it has been added to the frame.
我在TextField上也遇到了requestFocusInWindow的问题。诀窍是不在JPanel构造函数中构造组件。但是,创建一个构建方法并在将代码添加到框架后执行以下代码。
This worked for me:
这对我有用:
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(); //
if you want to resize, you need preferredSize();
on panel or use repaint()
if you don't need to resize frame.
如果你想调整大小,你需要preferredSize();在面板上或使用repaint()如果您不需要调整框架大小。
#4
0
Roman, the problem can be solved like that:
罗马,这个问题可以这样解决:
- Do this in the beginning of your
run
method: - 在run方法的开头执行此操作:
final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();
最终JPanel partnerSelectionPanel = generatePartnerSelectionPanel();
- Then do this
- 然后这样做
frame.getContentPane().add(partnerSelectionPanel);
frame.getContentPane()添加(partnerSelectionPanel)。
- Before you add the new panel do this:
- 在添加新面板之前,请执行以下操作:
partnerSelectionPanel.setVisible(false);
partnerSelectionPanel.setVisible(假);
It works. I do not know if it is a safe and/or elegant solution but it works.
有用。我不知道它是否是一个安全和/或优雅的解决方案,但它的工作原理。
#5
0
panel.invalidate();
panel.setVisible(false);
panel.removeAll();
frame.getContentPane().remove(panel);
panel = null;