在Java中,如何结合CardLayout和GridBagLayout,仍然能够切换面板?
Java新手,Java GUI类新手。我正在制作一个GUI来展示一些游戏,但在切换面板时遇到了困难。我读过关于CardLayout的文章,但是我在实现它时遇到了一个问题,因为我无法让持有不同游戏GUI的JPanel将它们的事件发送回使用CardLayout的类。(这可能是我出错的地方——我不知道该如何正确地构造它。) 这是我的主菜单(称为mainContainer): 这是GUI驱动程序的总体结构:在Java中,如何结合CardLayout和GridBagLayout,仍然能够切换面板?,java,swing,user-interface,Java,Swing,User Interface,Java新手,Java GUI类新手。我正在制作一个GUI来展示一些游戏,但在切换面板时遇到了困难。我读过关于CardLayout的文章,但是我在实现它时遇到了一个问题,因为我无法让持有不同游戏GUI的JPanel将它们的事件发送回使用CardLayout的类。(这可能是我出错的地方——我不知道该如何正确地构造它。) 这是我的主菜单(称为mainContainer): 这是GUI驱动程序的总体结构: public class CasinoDriverGUI { //CardLayout is
public class CasinoDriverGUI {
//CardLayout is here in the main method Container contentPane.add(cardLayout)
public static void main(String[] args) throws IOException
//MainContainer is MenuScreen: GridBagLayout for nice button placement
static class MainContainer extends JPanel implements ActionListener{...}
static class CrapsContainer extends JPanel implements ActionListener{...}
static class PokerContainer extends JPanel implements ActionListener{...}
//Button with custom look
class CButton extends JButton
}//end CasinoDriverGUI
这里是主要的方法:它从网站抓取一个图像,然后将菜单屏幕(mainContainer)添加到contentPane。菜单屏幕使用GridBagLayout,但它是添加按钮组件的地方。因此,我不知道如何让contentPane的CardLayout听菜单屏幕的按钮。我尝试使用ContainerListener,但那似乎是一条死胡同
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
到目前为止,我已经尝试使用“菜单屏幕”(mainContainer)来实例化所有游戏的面板,并在一些按钮上使用ActionListener来简单地调用thisGame.setVisible(true)
。但这会迫使窗口最小化并重新打开,以便检测到任何更改。编辑:修复此问题
关于如何重新构造此代码,以便能够将面板从菜单屏幕切换到不同游戏的面板,有什么建议吗?(代码如下,但骰子和扑克GUI不完整..仅将代码用作占位符
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
static class MainContainer extends JPanel implements ActionListener
{
public BufferedImage gradientImage = null;
public static BufferedImage textureImg; // static for ease
public static boolean loadingFinished = false;
protected JButton pokerJBtn;
protected JButton crapsJBtn;
CrapsContainer crapsContainer;
PokerContainer pokerContainer;
public MainContainer() {
setBorder(new EmptyBorder(50, 50, 50, 50)); // setting the insets
setLayout(new GridBagLayout());
// working with GridBagConstraints
GridBagConstraints labCnst = new GridBagConstraints();
GridBagConstraints txtCnst = new GridBagConstraints();
labCnst.ipady = txtCnst.ipady = 10;
labCnst.fill = GridBagConstraints.HORIZONTAL;
labCnst.gridwidth = 1;
labCnst.weightx = 0.3;
labCnst.gridx = 2;
labCnst.gridy = 2;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
pokerJBtn = new CButton("5-Card Poker");
add(pokerJBtn, labCnst);
labCnst.gridx = 2;
labCnst.gridy = 20;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
crapsJBtn = new CButton("Craps");
add(crapsJBtn, labCnst);
crapsContainer = new CrapsContainer();
pokerContainer = new PokerContainer();
add(crapsContainer);
add(pokerContainer);
crapsContainer.setVisible(false);
pokerContainer.setVisible(false);
//Add Action Listeners
crapsJBtn.addActionListener(this);
pokerJBtn.addActionListener(this);
}
public void changeCompFont(JComponent comp)
{
comp.setForeground(Color.WHITE);
comp.setFont(getFont().deriveFont(Font.BOLD, 13));
}
// To PAINT THE TEXTURE ABOVE THE COMPONENTS
@Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D)g.create(); // cloning
Rectangle2D txRect = new Rectangle2D.Double(0, 0, textureImg.getWidth(), textureImg.getHeight());
TexturePaint txPaint = new TexturePaint(textureImg, txRect);
g2d.setPaint(txPaint);
//make the texture transparent
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.233f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();// disposing the graphics object
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if(gradientImage==null || gradientImage.getHeight() != getHeight() )
{
gradientImage = createGradientImg();
}
g2d.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
public BufferedImage createGradientImg()
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
// background gradient paint, linear gradient paint for the background
// Gradient paint rendering could be made more optimized
LinearGradientPaint lgrPaint = new LinearGradientPaint(0.0f, 0.0f, getWidth(), getHeight(),
new float[] { 0.0f, 0.5f, 0.6f, 1.0f },
new Color[] { new Color(0x0530E),// new Color[] { new Color(0x002AFF),
new Color(0x0A31B),
new Color(0x0A31B),
new Color(0x0530E ) });
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setPaint(lgrPaint);
//g2d.shear(0.2, 0);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
g2d.drawImage(textureImg, 0, 0, getWidth(), getHeight(), null);
return image;
}
@Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == pokerJBtn)
{
pokerContainer.setVisible(true);
}
else if (e.getSource() == crapsJBtn){
this.setVisible(false);
invalidate();
crapsContainer.setVisible(true);
revalidate();
repaint();
}
}
}
//Either Flow, Border, or GridBag Layout
static class CrapsContainer extends JPanel implements ActionListener
{...}
//Either Flow, Border, or GridBag Layout
static class PokerContainer extends JPanel implements ActionListener
{...}
//Custom Button to change aesthetic look
class CButton extends JButton
{...}
}
我无法让持有不同游戏GUI的JPanel将其事件发送回使用CardLayout的类中
-事件不应返回到使用CardLayout的类中。每个游戏都应包含在自己的面板中。@camickr因此,方法可能是将游戏面板嵌套在面板中CardLayout?并始终保持控制CardLayout的按钮在视图中?当然。如果按钮特定于游戏,则它们属于游戏面板。如果它们特定于应用程序中的所有游戏,则它们属于框架。您可以将带有CardLayout的面板添加到框架的中心。然后按钮面板可以转到北or在画面的南部。或者你可以使用一个JMenuBar来交换游戏。现在的一个主要障碍是,我的菜单屏幕本身就是一个使用GridBag布局的面板。我现在要重新构造它。我想我需要以某种方式将这个主菜单屏幕概念“合并”到主方法中。我想保持链接中图片的设计。每个“屏幕”或“视图”应该是一个独立的组件,如果可能的话,甚至是一个独立的类。您可以使用某种控制器来处理来自各种视图的导航请求,然后使用CardLayout
在两者之间切换,