Java 卡片布局问题
我有一张卡片布局,第一张卡片是菜单 我选择第二张卡,并执行一些操作。我们将通过单击按钮来添加JTextField。如果我回到菜单卡,然后回到第二张卡,我第一次添加的JTextField仍然会在那里Java 卡片布局问题,java,swing,jpanel,cardlayout,Java,Swing,Jpanel,Cardlayout,我有一张卡片布局,第一张卡片是菜单 我选择第二张卡,并执行一些操作。我们将通过单击按钮来添加JTextField。如果我回到菜单卡,然后回到第二张卡,我第一次添加的JTextField仍然会在那里 我希望第二张卡在每次访问时都与我最初构建的卡一样,使用按钮,但不使用文本字段。确保您试图重置的面板上有代码将其恢复到“原始构建”状态。然后,当您处理导致您更改卡片的任何事件时,调用该代码以恢复原始状态,然后再显示卡片。这是最终的排序版本,要移除卡片,在对其进行更改后,请查看,使用重新验证()和重新绘制
我希望第二张卡在每次访问时都与我最初构建的卡一样,使用按钮,但不使用文本字段。确保您试图重置的面板上有代码将其恢复到“原始构建”状态。然后,当您处理导致您更改卡片的任何事件时,调用该代码以恢复原始状态,然后再显示卡片。这是最终的排序版本,要移除卡片,在对其进行更改后,请查看,使用
重新验证()
和重新绘制()
与往常一样的方法:-)
如果您只是想删除对卡所做的最新编辑
,请尝试以下代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ApplicationBase extends JFrame
{
private JPanel centerPanel;
private int topPanelCount = 0;
private String[] cardNames = {
"Login Window",
"TextField Creation"
};
private TextFieldCreation tfc;
private LoginWindow lw;
private JButton nextButton;
private JButton removeButton;
private ActionListener actionListener = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource() == nextButton)
{
CardLayout cardLayout = (CardLayout) centerPanel.getLayout();
cardLayout.next(centerPanel);
}
else if (ae.getSource() == removeButton)
{
TextFieldCreation.topPanel.remove(TextFieldCreation.tfield);
TextFieldCreation.topPanel.revalidate();
TextFieldCreation.topPanel.repaint();
}
}
};
private void createAndDisplayGUI()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
centerPanel = new JPanel();
centerPanel.setLayout(new CardLayout());
lw = new LoginWindow();
lw.createAndDisplayGUI();
centerPanel.add(lw, cardNames[0]);
tfc = new TextFieldCreation();
tfc.createAndDisplayGUI();
centerPanel.add(tfc, cardNames[1]);
JPanel bottomPanel = new JPanel();
removeButton = new JButton("REMOVE");
nextButton = new JButton("NEXT");
removeButton.addActionListener(actionListener);
nextButton.addActionListener(actionListener);
bottomPanel.add(removeButton);
bottomPanel.add(nextButton);
add(centerPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
pack();
setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ApplicationBase().createAndDisplayGUI();
}
});
}
}
class TextFieldCreation extends JPanel
{
private JButton createButton;
private int count = 0;
public static JTextField tfield;
public static JPanel topPanel;
public void createAndDisplayGUI()
{
topPanel = new JPanel();
topPanel.setLayout(new GridLayout(0, 2));
createButton = new JButton("CREATE TEXTFIELD");
createButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
tfield = new JTextField();
tfield.setActionCommand("JTextField" + count);
topPanel.add(tfield);
topPanel.revalidate();
topPanel.repaint();
}
});
setLayout(new BorderLayout(5, 5));
add(topPanel, BorderLayout.CENTER);
add(createButton, BorderLayout.PAGE_END);
}
}
class LoginWindow extends JPanel
{
private JPanel topPanel;
private JPanel middlePanel;
private JPanel bottomPanel;
public void createAndDisplayGUI()
{
topPanel = new JPanel();
JLabel userLabel = new JLabel("USERNAME : ", JLabel.CENTER);
JTextField userField = new JTextField(20);
topPanel.add(userLabel);
topPanel.add(userField);
middlePanel = new JPanel();
JLabel passLabel = new JLabel("PASSWORD : ", JLabel.CENTER);
JTextField passField = new JTextField(20);
middlePanel.add(passLabel);
middlePanel.add(passField);
bottomPanel = new JPanel();
JButton loginButton = new JButton("LGOIN");
bottomPanel.add(loginButton);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(topPanel);
add(middlePanel);
add(bottomPanel);
}
}
如果“原样”表示“空白/无组件”,那么添加新卡似乎更有意义。只需使用,从
布局中删除当前卡,在上一个按钮上单击,然后使用[addLayoutComponent(…)](,java.lang.Object)),添加卡的新实例。@andrewhompson也许我不清楚。。。我的第二张卡片上会有按钮,当单击这些按钮时,会出现一个文本字段,如果我返回到第一张卡片,然后再次返回到第二张卡片,文本字段仍然会在那里。我希望第二张卡在每次访问时都与我最初构建的卡一样,带有按钮,没有Textfield@Peddler:我正在做这件事,我刚在测试时意识到了你的问题:-)如果你能创建并发布一个,那就太好了。如果你不从CardLayout中删除组件怎么办,而是将其从容器本身(中心面板)中移除?@HovercraftFullOfEels:是的,直接从中心面板中移除它,效果很好。所以在某个地方,CardLayout
的性能没有达到应有的水平:-)感谢您花时间查看代码。这不是一个bug,这是一个用户错误(依我看,可能是我不太理解:)从父组件中删除组件的方法总是调用父组件。删除(…)它在内部向layout.removeLayoutComponent发送消息,该组件会自行清理。因此,如果应用程序代码调用后者,则组件仍在父级的子树中,这可能会或可能不会混淆某些协作者@气垫船好的捕获物:-)但是问题出现了,当这些事情是用手来做的时候,我的意思是手动,那么这两种方法是用来做什么的,它们确实会移除,有时,天知道,它们在做它们的工作时似乎是喜怒无常的:-)。这肯定是一个bug,否则为什么要使用CardLayout
为什么不使用旧式,当我们必须在移除卡片时执行revalidate()
和repaint()
时,为什么不在添加卡片时执行相同的操作。它们是供框架本身使用的,也就是由容器使用,而不是供应用程序代码使用。所有的布局经理都有这些方法,但你从来没有使用过它们——那么,在CardLayout的情况下,你为什么认为你应该使用这些方法呢。。不要这样做
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ApplicationBase extends JFrame
{
private JPanel centerPanel;
private int topPanelCount = 0;
private String[] cardNames = {
"Login Window",
"TextField Creation"
};
private TextFieldCreation tfc;
private LoginWindow lw;
private JButton nextButton;
private JButton removeButton;
private ActionListener actionListener = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource() == nextButton)
{
CardLayout cardLayout = (CardLayout) centerPanel.getLayout();
cardLayout.next(centerPanel);
}
else if (ae.getSource() == removeButton)
{
TextFieldCreation.topPanel.remove(TextFieldCreation.tfield);
TextFieldCreation.topPanel.revalidate();
TextFieldCreation.topPanel.repaint();
}
}
};
private void createAndDisplayGUI()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
centerPanel = new JPanel();
centerPanel.setLayout(new CardLayout());
lw = new LoginWindow();
lw.createAndDisplayGUI();
centerPanel.add(lw, cardNames[0]);
tfc = new TextFieldCreation();
tfc.createAndDisplayGUI();
centerPanel.add(tfc, cardNames[1]);
JPanel bottomPanel = new JPanel();
removeButton = new JButton("REMOVE");
nextButton = new JButton("NEXT");
removeButton.addActionListener(actionListener);
nextButton.addActionListener(actionListener);
bottomPanel.add(removeButton);
bottomPanel.add(nextButton);
add(centerPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
pack();
setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ApplicationBase().createAndDisplayGUI();
}
});
}
}
class TextFieldCreation extends JPanel
{
private JButton createButton;
private int count = 0;
public static JTextField tfield;
public static JPanel topPanel;
public void createAndDisplayGUI()
{
topPanel = new JPanel();
topPanel.setLayout(new GridLayout(0, 2));
createButton = new JButton("CREATE TEXTFIELD");
createButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
tfield = new JTextField();
tfield.setActionCommand("JTextField" + count);
topPanel.add(tfield);
topPanel.revalidate();
topPanel.repaint();
}
});
setLayout(new BorderLayout(5, 5));
add(topPanel, BorderLayout.CENTER);
add(createButton, BorderLayout.PAGE_END);
}
}
class LoginWindow extends JPanel
{
private JPanel topPanel;
private JPanel middlePanel;
private JPanel bottomPanel;
public void createAndDisplayGUI()
{
topPanel = new JPanel();
JLabel userLabel = new JLabel("USERNAME : ", JLabel.CENTER);
JTextField userField = new JTextField(20);
topPanel.add(userLabel);
topPanel.add(userField);
middlePanel = new JPanel();
JLabel passLabel = new JLabel("PASSWORD : ", JLabel.CENTER);
JTextField passField = new JTextField(20);
middlePanel.add(passLabel);
middlePanel.add(passField);
bottomPanel = new JPanel();
JButton loginButton = new JButton("LGOIN");
bottomPanel.add(loginButton);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(topPanel);
add(middlePanel);
add(bottomPanel);
}
}