Java Swing CardLayout:多张卡片似乎同时显示
Java Swing CardLayout: multiple cards seem to be displayed simultaneously
我目前正在使用 Eclipse(Luna,Win 8.1)开发一个简短的 Java Swing 项目。目的是显示包含菜单的框架。菜单有不同的页面(主页面、选项等),由带有按钮、标签等的 JPanel 实现。这些 JPanel 由 CardLayout 组织,调用 CardLayout.show(..) 方法的方式在不同的菜单页面之间切换。当我两天前停止编程时,一切都运行良好。然而,当我昨天早上想继续时,我的代码似乎完全忽略了 CardLayout:当将鼠标光标移动到它们的位置上时,位于其他卡片中的按钮会从第一张卡片的背景中弹出。我试图连续 17 个小时解决这个问题(研究、使用备份等)。问题仍然存在,我现在非常绝望=/。以下 SSCCE 显示了相同的行为(将鼠标移到左下角可以看到 "Option" 卡的 "Back" 按钮弹出)。
package sscce;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
private CardLayout mainWindowLayout;
// mainPanel will be used as the MainFrame's main unit to manage Components
private JPanel mainPanel;
// Constructor
public MainFrame() {
setTitle("sscce");
setPreferredSize(new Dimension(800, 600));
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
mainPanel = new JPanel();
mainPanel.setPreferredSize(getSize());
mainWindowLayout = new CardLayout();
mainPanel.setLayout(mainWindowLayout);
buildMainMenu();
buildOptions();
getContentPane().add(mainPanel);
mainPanel.setVisible(true);
// starting application it will "show" (container,
// contentIdentifier(String))
mainWindowLayout.show(mainPanel, "2");
pack();
setVisible(true);
}// Constructor
private void buildMainMenu() {
JPanel panelMainMenu = new JPanel(new GridBagLayout());
panelMainMenu.setBackground(Color.orange);
// 1 Button (centered) to go to Options-Card
JButton bnOptions = new JButton("Options");
// Button Functionality
bnOptions.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
mainWindowLayout.show(mainPanel, "2");
}
});
panelMainMenu.add(bnOptions);
panelMainMenu.setOpaque(true);
// container content identifier(String)
mainPanel.add(panelMainMenu, "1");
panelMainMenu.setVisible(true);
}// buildMainMenu
private void buildOptions() {
JPanel panelOptions = new JPanel();
panelOptions.setLayout(new GridBagLayout());
// standardized margins for all Elements:
final Insets gbcInsets = new Insets(5, 5, 5, 5);
panelOptions.setBackground(Color.white);
JPanel fillerRight = new JPanel();
JPanel fillerTop = new JPanel();
JButton bnOptBack = new JButton("Back");
bnOptBack.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
mainWindowLayout.show(mainPanel, "1");
}
});
// add filler panels to keep button in position
fillerRight.setBackground(Color.red);
fillerRight.setOpaque(true);
panelOptions.add(fillerRight, new GridBagConstraints(1, 1, 1, 2, 1, 0,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
fillerRight.setVisible(true);
fillerTop.setBackground(Color.pink);
fillerTop.setOpaque(true);
panelOptions.add(fillerTop, new GridBagConstraints(0, 0, 2, 1, 0, 1,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
fillerTop.setVisible(true);
// 1 Button in lower left hand corner, sends you back to MainMenu-card
panelOptions.add(bnOptBack, new GridBagConstraints(0, 1, 1, 1, 0, 0,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
bnOptBack.setVisible(true);
panelOptions.setOpaque(true);
// container content identifier(String)
mainPanel.add(panelOptions, "2");
panelOptions.setVisible(true);
}// buildOptions
public static void main(String[] args) {
MainFrame m = new MainFrame();
}// main
}// MainFrame
非常感谢任何帮助。
提前致谢 :)
编辑: 我想您不必仔细研究 "buildMainMenu" 和 "buildOptions" 方法,单个菜单页面的设置似乎工作正常。
当我注释掉以下两行时,它在我的机器上按预期工作
panelOptions.setVisible(true);
和
panelMainMenu.setVisible(true);
当使用 CardLayout
时,您只需添加组件并使用 CardLayout#show
来决定显示哪个组件。首先调用 setVisible
似乎会导致问题(无论出于何种原因)。
确保在 EDT 上触发 Swing 代码也是一个好主意:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MainFrame m = new MainFrame();
}
});
我目前正在使用 Eclipse(Luna,Win 8.1)开发一个简短的 Java Swing 项目。目的是显示包含菜单的框架。菜单有不同的页面(主页面、选项等),由带有按钮、标签等的 JPanel 实现。这些 JPanel 由 CardLayout 组织,调用 CardLayout.show(..) 方法的方式在不同的菜单页面之间切换。当我两天前停止编程时,一切都运行良好。然而,当我昨天早上想继续时,我的代码似乎完全忽略了 CardLayout:当将鼠标光标移动到它们的位置上时,位于其他卡片中的按钮会从第一张卡片的背景中弹出。我试图连续 17 个小时解决这个问题(研究、使用备份等)。问题仍然存在,我现在非常绝望=/。以下 SSCCE 显示了相同的行为(将鼠标移到左下角可以看到 "Option" 卡的 "Back" 按钮弹出)。
package sscce;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
private CardLayout mainWindowLayout;
// mainPanel will be used as the MainFrame's main unit to manage Components
private JPanel mainPanel;
// Constructor
public MainFrame() {
setTitle("sscce");
setPreferredSize(new Dimension(800, 600));
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
mainPanel = new JPanel();
mainPanel.setPreferredSize(getSize());
mainWindowLayout = new CardLayout();
mainPanel.setLayout(mainWindowLayout);
buildMainMenu();
buildOptions();
getContentPane().add(mainPanel);
mainPanel.setVisible(true);
// starting application it will "show" (container,
// contentIdentifier(String))
mainWindowLayout.show(mainPanel, "2");
pack();
setVisible(true);
}// Constructor
private void buildMainMenu() {
JPanel panelMainMenu = new JPanel(new GridBagLayout());
panelMainMenu.setBackground(Color.orange);
// 1 Button (centered) to go to Options-Card
JButton bnOptions = new JButton("Options");
// Button Functionality
bnOptions.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
mainWindowLayout.show(mainPanel, "2");
}
});
panelMainMenu.add(bnOptions);
panelMainMenu.setOpaque(true);
// container content identifier(String)
mainPanel.add(panelMainMenu, "1");
panelMainMenu.setVisible(true);
}// buildMainMenu
private void buildOptions() {
JPanel panelOptions = new JPanel();
panelOptions.setLayout(new GridBagLayout());
// standardized margins for all Elements:
final Insets gbcInsets = new Insets(5, 5, 5, 5);
panelOptions.setBackground(Color.white);
JPanel fillerRight = new JPanel();
JPanel fillerTop = new JPanel();
JButton bnOptBack = new JButton("Back");
bnOptBack.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
mainWindowLayout.show(mainPanel, "1");
}
});
// add filler panels to keep button in position
fillerRight.setBackground(Color.red);
fillerRight.setOpaque(true);
panelOptions.add(fillerRight, new GridBagConstraints(1, 1, 1, 2, 1, 0,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
fillerRight.setVisible(true);
fillerTop.setBackground(Color.pink);
fillerTop.setOpaque(true);
panelOptions.add(fillerTop, new GridBagConstraints(0, 0, 2, 1, 0, 1,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
fillerTop.setVisible(true);
// 1 Button in lower left hand corner, sends you back to MainMenu-card
panelOptions.add(bnOptBack, new GridBagConstraints(0, 1, 1, 1, 0, 0,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
bnOptBack.setVisible(true);
panelOptions.setOpaque(true);
// container content identifier(String)
mainPanel.add(panelOptions, "2");
panelOptions.setVisible(true);
}// buildOptions
public static void main(String[] args) {
MainFrame m = new MainFrame();
}// main
}// MainFrame
非常感谢任何帮助。 提前致谢 :) 编辑: 我想您不必仔细研究 "buildMainMenu" 和 "buildOptions" 方法,单个菜单页面的设置似乎工作正常。
当我注释掉以下两行时,它在我的机器上按预期工作
panelOptions.setVisible(true);
和
panelMainMenu.setVisible(true);
当使用 CardLayout
时,您只需添加组件并使用 CardLayout#show
来决定显示哪个组件。首先调用 setVisible
似乎会导致问题(无论出于何种原因)。
确保在 EDT 上触发 Swing 代码也是一个好主意:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MainFrame m = new MainFrame();
}
});