【问题标题】:How to Contract Card Layout如何签约卡片布局
【发布时间】:2012-09-30 08:16:04
【问题描述】:

我有一个带有 VerticalLayout (org.jdesktop.swingx.VerticalLayout)ma​​inPanel。主面板有几个子面板。其中之一是根据用户选择动态变化的面板。因此,我将其布局设置为 CardLayout,我认为这是实现这一目标的最简单(也许是最好的?)方式。

我将该面板称为 elasticPanel。顾名思义,它应该是有弹性的。这意味着,它应该能够扩展和收缩。假设它的行为是这样的。如果用户选择1elasticPanel 应该显示一个,比如JComboBox。如果用户选择2 那么,两个JComboBoxs...

好的,到目前为止它运行良好。现在,当elasticPanel 显示两个JComboBoxs 时,用户再次选择1。我现在需要做的是elasticPanel 应该显示一个JComboBox,它的大小是正常的。但是由于elasticPanel 已经展开,所以会发生什么是它显示JComboBox 被拉伸以适应它的大小。所以它给人一种奇怪的感觉。


以下屏幕截图显示了我的界面遇到的问题。

在选择之前。 NONE 被选中。

一个元素被选中

NONE 再次被选中

我需要最后一个屏幕截图中的elasticPanel故障位置)与第一个屏幕截图中的一样。这只是一个简单的案例。想象一下在显示大约 5、6 个子组件后返回 NONE 时的样子。

我已经尝试过setSize() 方法。它没有做任何事情..那么如何解决这个问题?

感谢任何帮助。谢谢!

【问题讨论】:

  • 如需更好的帮助,请尽快发帖SSCCE
  • (不太了解 CardLayout 部分..)无论如何:a)调用 setSize 总是错误(这是 LayoutManager 的任务,不会有任何效果) b) 如果大小在 之前 显示第二行时没问题,那么 再次隐藏它之后应该没问题,前提是它的父级得到重新验证

标签: java swing jframe jpanel cardlayout


【解决方案1】:

很难说你指的是CardLayout 是什么东西。由于CardLayout 以不同的方式工作。你可以做的是简单地放置一个JPanelbasePanelGridLayout(0, 1) 并将这个JPanel 放在另一个JPanel 上面说 contentPanel,然后现在设置这作为 JFrame 的内容窗格,并在您从视图中添加或删除元素时调用 pack()。这是一个向您展示我的意思的示例。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ElasticPanel
{
    private JFrame frame;
    private JPanel contentPane;
    private JPanel basePanel;
    /*
     * Array to hold the JComboBox
     * elements.
     */
    private JComboBox[] prodCombo;  
    private JComboBox[] temp;
    /* 
     * Counter to keep track
     * of the number of JComboBox 
     * present.
     */
    private int counter;  
    /*
     * Data for each JComboBox
     */
    private String[] data = {
                                "None",
                                "Sub Category"
                            };

    private ActionListener comboAction =
            new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            JComboBox cbox = (JComboBox) ae.getSource();
            String command = (String) ae.getActionCommand();
            int index = Integer.parseInt(command);
            String selection = (String) cbox.getSelectedItem();

            if (selection.equals("None"))
            {
                /*
                 * i = index + 1, because, we want to
                 * remove all JComboBox after this one.
                 */
                for (int i = (index + 1); i < prodCombo.length; i++)
                {
                    temp = new JComboBox[prodCombo.length];
                    for (int j = 0; j < prodCombo.length; j++)
                        temp[j] = prodCombo[j];
                    basePanel.remove(prodCombo[i]); 
                }
                prodCombo = new JComboBox[index + 1];
                for (int i = 0; i <= index; i++)
                {                   
                    prodCombo[i] = temp[i];
                }
                counter = prodCombo.length;
                System.out.println("Item Removed\nCounter : " + counter);
            }
            else if (selection.equals("Sub Category"))
            {
                counter++;
                temp = new JComboBox[counter];
                for (int i = 0; i < prodCombo.length; i++)
                {
                    temp[i] = prodCombo[i];
                }
                temp[counter - 1] = new JComboBox(data);
                temp[counter - 1].setActionCommand("" + (counter - 1));
                temp[counter - 1].addActionListener(this);
                prodCombo = new JComboBox[counter];
                for (int i = 0; i < counter; i++)
                    prodCombo[i] = temp[i];
                basePanel.add(prodCombo[counter - 1]);  
                System.out.println("Item Added\nCounter : " + counter);
            }

            //basePanel.revalidate();
            //basePanel.repaint();
            frame.pack();
        }
    };

    public ElasticPanel()
    {
        prodCombo = new JComboBox[1];
        counter = 1;
    }

    private void displayGUI()
    {
        frame = new JFrame("Elastic Panel Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        contentPane = new JPanel();

        basePanel = new JPanel(new GridLayout(0, 1, 5, 5));

        prodCombo[counter - 1] = new JComboBox(data);
        prodCombo[counter - 1].setActionCommand("" + (counter - 1));
        prodCombo[counter - 1].addActionListener(comboAction);

        basePanel.add(prodCombo[counter - 1]);
        contentPane.add(basePanel);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new ElasticPanel().displayGUI();
            }
        });
    }
}

*最新更新:*

通过添加更多组件并将弹性面板放置在其他位置而不是内容窗格顶部来获得更多洞察力。

import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.*;

public class VirtualViewGUI extends JFrame
{
    private JPanel rightPanel;
    private ElasticPanel elasticPanel;

    public VirtualViewGUI()
    {
        super("Virtual View");

        JMenuBar jmenuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenu helpMenu = new JMenu("Help");
        JMenu feel = new JMenu("Look & Feel");

        JMenu layOutMenu = new JMenu("ConfigureCells");
        JMenuItem add_files = new JMenuItem("Select Directory.."); 
        JMenuItem minCellSize = new JMenuItem("height 260 X  width 260"); 
        JMenuItem moderateCellSize = new JMenuItem("height 320 X  width 320"); 
        JMenuItem maxCellSize = new JMenuItem("height 360 X  width 360"); 
        JMenuItem exit = new JMenuItem("Exit");
        JMenuItem help = new JMenuItem("Help Content");

        fileMenu.add(add_files);
        fileMenu.add(exit);
        layOutMenu.add(minCellSize);
        layOutMenu.add(moderateCellSize);
        layOutMenu.add(maxCellSize);
        helpMenu.add(help);

        jmenuBar.add(fileMenu);
        jmenuBar.add(layOutMenu);
        jmenuBar.add(helpMenu);

        ImageIcon myImage = null;
        try
        {
            myImage = new ImageIcon(
                new URL("http://gagandeepbali.uk.to/" + 
                        "gaganisonline/images/swing/" + 
                        "stackoverflow/cow-cartoon.jpg"));
        }
        catch(MalformedURLException mue)    
        {
            mue.printStackTrace();
        }

        JLabel icon = new JLabel(myImage);
        icon.setIcon(myImage);
        setJMenuBar(jmenuBar); 

        rightPanel = new JPanel();
        elasticPanel = new ElasticPanel(this);
        rightPanel.add(elasticPanel);

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout(5, 5));
        contentPane.add(icon, BorderLayout.CENTER);
        contentPane.add(rightPanel, BorderLayout.LINE_END);

        setContentPane(contentPane);
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);    
        setVisible(true);
        System.out.println("File Separator is : " + System.getProperty("file.separator"));
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new VirtualViewGUI();
            }
        });
    }
}

class ElasticPanel extends JPanel
{
    private JFrame frame;
    private JPanel contentPane;
    /*
     * Array to hold the JComboBox
     * elements.
     */
    private JComboBox[] prodCombo;  
    private JComboBox[] temp;
    /* 
     * Counter to keep track
     * of the number of JComboBox 
     * present.
     */
    private int counter;  
    /*
     * Data for each JComboBox
     */
    private String[] data = {
                                "None",
                                "Sub Category"
                            };

    private ActionListener comboAction =
            new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            JComboBox cbox = (JComboBox) ae.getSource();
            String command = (String) ae.getActionCommand();
            int index = Integer.parseInt(command);
            String selection = (String) cbox.getSelectedItem();

            if (selection.equals("None"))
            {
                /*
                 * i = index + 1, because, we want to
                 * remove all JComboBox after this one.
                 */
                for (int i = (index + 1); i < prodCombo.length; i++)
                {
                    temp = new JComboBox[prodCombo.length];
                    for (int j = 0; j < prodCombo.length; j++)
                        temp[j] = prodCombo[j];
                    remove(prodCombo[i]);   
                }
                prodCombo = new JComboBox[index + 1];
                for (int i = 0; i <= index; i++)
                {                   
                    prodCombo[i] = temp[i];
                }
                counter = prodCombo.length;
                System.out.println("Item Removed\nCounter : " + counter);
            }
            else if (selection.equals("Sub Category"))
            {
                counter++;
                temp = new JComboBox[counter];
                for (int i = 0; i < prodCombo.length; i++)
                {
                    temp[i] = prodCombo[i];
                }
                temp[counter - 1] = new JComboBox(data);
                temp[counter - 1].setActionCommand("" + (counter - 1));
                temp[counter - 1].addActionListener(this);
                prodCombo = new JComboBox[counter];
                for (int i = 0; i < counter; i++)
                    prodCombo[i] = temp[i];
                add(prodCombo[counter - 1]);    
                System.out.println("Item Added\nCounter : " + counter);
            }

            //revalidate();
            //repaint();
            frame.pack();
        }
    };

    public ElasticPanel(JFrame frame)
    {
        this.frame = frame;
        prodCombo = new JComboBox[1];
        counter = 1;

        setLayout(new GridLayout(0, 1, 5, 5));

        prodCombo[counter - 1] = new JComboBox(data);
        prodCombo[counter - 1].setActionCommand("" + (counter - 1));
        prodCombo[counter - 1].addActionListener(comboAction);

        add(prodCombo[counter - 1]);        
    }
}

【讨论】:

  • 非常感谢您的代码。这正是我想要的。但问题是在我的情况下,弹性面板不是唯一的面板。它是 basePanel 的子面板。其他面板不变。所以你说我还是应该更新整个框架?实际上,以前我正在尝试做类似的事情。但是每个人都说我应该选择cardLayout,这是最好的方法..
  • 从来不知道使用零行(和列)初始化gridlayout,谢谢!这非常方便。找到more info here
  • 我曾尝试对代码进行更多修改,以便您了解您的 弹性面板 需要位于另一个 JPanel 内实际上按照您想要的方式工作,而不会干扰其他组件的布局。请查看更新的答案 :-) CardLayout 恕我直言,适用于您拥有多个 JPanel 并且需要在它们之间交换视图的情况。在这种情况下,您一开始并不知道用户想要多少个 JComboBox,所以 CardLayout 在任何意义上都不是一个好方法。
  • 如果您可以访问最新的Java 7 API,那就更好了。对于其余的,您最欢迎并保持微笑:-) 虽然如果您想在添加新组件时保持框架大小不变,您可以取消注释 actionPerformed() 方法末尾的行并注释 frame.pack() .
  • 谢谢!!你真好。感谢您的宝贵努力。你解决了我的问题...
【解决方案2】:

如果我理解正确,您有 2 个不同的面板,您可以使用 CardLayout 在这两个面板之间切换。 CardLayout 的问题在于它占用了最大面板的大小。

因此,使用CardLayout,您将无法缩小容器的大小,但您可以通过使用BorderLayout 将面板包裹在另一个面板内并将面板放入BorderLayout.NORTH

【讨论】:

    猜你喜欢
    • 2021-08-08
    • 2019-12-24
    • 2011-12-14
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多