【问题标题】:Why does GridBagLayout provide strange result?为什么 GridBagLayout 会提供奇怪的结果?
【发布时间】:2013-05-17 11:20:50
【问题描述】:

我希望各种组件展开并填满整个窗口。

您尝试过其他方法吗? 是的,我尝试了GridLayout,但按钮看起来很大。我还尝试了pack(),它使窗口变小了。窗口应该是 750x750 :)

我正在尝试的是:

  • 顶部的这 4 个按钮作为细条
  • 带有JPanels 的滚动窗格将包含所有视频转换任务。这样占用空间最大
  • 底部的JPanel 包含JProgressBar 作为细条。
  • 但是好像有什么地方搞砸了。 请帮我解决这个问题

    SSCCE

    import java.awt.*;
    import javax.swing.*;
    import com.explodingpixels.macwidgets.*;
    
    public class HudTest {
        public static void main(String[] args) {
            HudWindow hud = new HudWindow("Window");
            hud.getJDialog().setSize(750, 750);
            hud.getJDialog().setLocationRelativeTo(null);
            hud.getJDialog().setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    
            JPanel buttonPanel = new JPanel(new FlowLayout());
    
    
            JButton addVideo = HudWidgetFactory.createHudButton("Add New Video");
            JButton removeVideo = HudWidgetFactory.createHudButton("Remove Video");
            JButton startAll = HudWidgetFactory.createHudButton("Start All Tasks");
            JButton stopAll = HudWidgetFactory.createHudButton("Stop All Tasks");
    
            buttonPanel.add(addVideo);
            buttonPanel.add(startAll);
            buttonPanel.add(removeVideo);
            buttonPanel.add(stopAll);
    
            JPanel taskPanel = new JPanel(new GridLayout(0,1));
            JScrollPane taskScrollPane = new JScrollPane(taskPanel);
            IAppWidgetFactory.makeIAppScrollPane(taskScrollPane);
            for(int i=0;i<10;i++){
                ColorPanel c = new ColorPanel();
                c.setPreferredSize(new Dimension(750,100));
                taskPanel.add(c);
            }
    
            JPanel progressBarPanel = new JPanel();
    
            JComponent component = (JComponent) hud.getContentPane();
            component.setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            Insets in = new Insets(2,2,2,2);
    
            gbc.insets = in;
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridwidth = 10;
            gbc.gridheight = 1;
            gbc.fill = GridBagConstraints.BOTH;
            component.add(buttonPanel,gbc);
    
            gbc.gridy += 1;
            gbc.gridheight = 17;
            component.add(taskScrollPane,gbc);
    
            gbc.gridy += 17;
            gbc.gridheight = 2;
            component.add(progressBarPanel,gbc);
    
            hud.getJDialog().setVisible(true);
        }
    }
    

    【问题讨论】:

    • com.explodingpixels.macwidgets.*; SSCCE 应该没有外部依赖项。没有第 3 方 API。 :( 你能用标准的JComponent 来说明问题吗?
    • :-) 很好,请问(这个工具栏)可以贴在哪里
    • @Little Child 我不会这样,将逻辑拆分为具有相同或不同 LayoutManager 的容器(JPanel),那么这项工作将尽可能容易....
    • JComboBox, JTable, JScrollPane 无法在内部正确返回其 PreferredSize,如果是则需要覆盖此值,那么是否存在 setPreferredSize 或 setPreferredScrollableViewportSize 或 setPrototypeDisplayValue 或 setPreferredSize 无关紧要,因为其余的都是关于不良做法的,
    • 是的,因为 getPreferredSize 和 setPreferredSize(对于标准 LayoutManagers)没有区别,最好使用 getPreferredSize()

    标签: java swing jpanel grid-layout gridbaglayout


    【解决方案1】:

    使用这个

    gbc.weightx = 1;
    gbc.weighty = 1;
    gbc.fill = GridbagConstraints.BOTH
    

    【讨论】:

    • 请详细说明weightx 的作用。它是否设置每个gridx 等于多少像素?
    • 如果weightx 为1,那么这个特定组件将水平占据其父容器的全部剩余宽度。为什么我说“剩余”是因为可能有一些其他组件共享相同的水平空间。当然,这需要将 gbc.fill 设置为 HORIZONTAL 或 BOTH。
    【解决方案2】:

    为什么不简单地将三个JPanels 放在一个JPanel 上,BorderLayoutLayout Manager,其中中间的JPanel 以及所有具有各自尺寸的自定义面板都可以容纳在JScrollPane 内,如下例所示:

    import javax.swing.*;
    import java.awt.*;
    import java.util.Random;
    
    /**
     * Created with IntelliJ IDEA.
     * User: Gagandeep Bali
     * Date: 5/17/13
     * Time: 6:09 PM
     * To change this template use File | Settings | File Templates.
     */
    public class PlayerBase
    {
        private JPanel contentPane;
        private JPanel buttonPanel;
        private JPanel centerPanel;
        private CustomPanel[] colourPanel;
        private JPanel progressPanel;
    
        private JButton addVideoButton;
        private JButton removeVideoButton;
        private JButton startAllButton;
        private JButton stopAllButton;
    
        private JProgressBar progressBar;
    
        private Random random;
    
        public PlayerBase()
        {
            colourPanel = new CustomPanel[10];
    
            random = new Random();
        }
    
        private void displayGUI()
        {
            JFrame playerWindow = new JFrame("Player Window");
            playerWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    
            contentPane = new JPanel(new BorderLayout(5, 5));
            contentPane.setBorder(
                    BorderFactory.createEmptyBorder(5, 5, 5, 5));
            buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
            addVideoButton = new JButton("Add New Video");
            removeVideoButton = new JButton("Remove Video");
            startAllButton = new JButton("Start all tasks");
            stopAllButton = new JButton("Stop all tasks");
    
            buttonPanel.add(addVideoButton);
            buttonPanel.add(removeVideoButton);
            buttonPanel.add(startAllButton);
            buttonPanel.add(stopAllButton);
    
            contentPane.add(buttonPanel, BorderLayout.PAGE_START);
    
            JScrollPane scroller = new JScrollPane();
            centerPanel = new JPanel(new GridLayout(0, 1, 2, 2));
            for (int i = 0; i < colourPanel.length; i++)
            {
                colourPanel[i] = new CustomPanel(new Color(
                        random.nextInt(255), random.nextInt(255)
                        , random.nextInt(255)));
                centerPanel.add(colourPanel[i]);
            }
            scroller.setViewportView(centerPanel);
    
            contentPane.add(scroller, BorderLayout.CENTER);
    
            progressPanel = new JPanel(new BorderLayout(5, 5));
            progressBar = new JProgressBar(SwingConstants.HORIZONTAL);
            progressPanel.add(progressBar);
    
            contentPane.add(progressPanel, BorderLayout.PAGE_END);
    
            playerWindow.setContentPane(contentPane);
            playerWindow.pack();
            //playerWindow.setSize(750, 750);
            playerWindow.setLocationByPlatform(true);
            playerWindow.setVisible(true);
        }
    
        public static void main(String[] args)
        {
            Runnable runnable = new Runnable()
            {
                @Override
                public void run()
                {
                    new PlayerBase().displayGUI();
                }
            };
            EventQueue.invokeLater(runnable);
        }
    }
    
    class CustomPanel extends JPanel
    {
        public CustomPanel(Color backGroundColour)
        {
            setOpaque(true);
            setBackground(backGroundColour);
        }
    
        @Override
        public Dimension getPreferredSize()
        {
            return (new Dimension(750, 100));
        }
    }
    

    输出:

    【讨论】:

    • 我不能使用pack(),因为我需要窗口精确到 750x750
    • @LittleChild :你可能是对的,但同时也可能是错的。考虑这种情况,在这种情况下,您真的不知道您的应用程序的用户可能在什么分辨率上工作。所以在这种情况下,pack() 会派上用场:-)
    • 是的。我刚刚看到你上面关于gridweightxgridweighty的答案,可能会解决我的问题
    • gridweightxgridweighty 并不是为了招待这样的事情。它们旨在代表容器内的可用空间,用于相应的组件。而Container(JPanel) 的大小,在这种情况下将取决于它所拥有的组件,以及它们在容器(Preferred Size) 内占据的大小。例如,如果您的窗口是100X100,并且您在其中放置了两个组件。一个是weightx = 0.3/weighty = 1.0/gridx = 0/gridy = 0,一个是weighty = 0.7/weighty = 1.0/gridx = 1/gridy = 0,也就是说前者会占据30%
    • continued... : 容器,它所在的容器,后一个将占用70 % (from left to right orientation)
    猜你喜欢
    • 2020-07-08
    • 1970-01-01
    • 2016-12-03
    • 2020-02-28
    • 1970-01-01
    • 2021-06-08
    • 2020-07-11
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多