java - GridBagLayout - 一行的高度导致下一行的宽度发生变化

标签 java swing awt layout-manager gridbaglayout

我正在开发的 UI 显示一个面板,让用户选择电影并播放。有播放、暂停等控件。

布局似乎是我想要的。该面板使用 GridBagLayout。第 2 行显示状态消息的文本区域,第 3 行显示带有按钮和进度栏的面板。

我遇到的问题是,当文本区域中有太多文本行时,第 3 行中的按钮会环绕。这与外框的高度无关。

第 2 行的高度影响第 3 行的宽度。我不明白这种行为。我想知道是否有人可以告诉我我做错了什么以及如何解决它?我已附上代码。

在一个稍微不同的主题上,如果您正在查看代码,您是否还可以建议一种在最底部组件和最外层面板之间留出边距的方法?

预先感谢您的帮助。

问候,
彼得



    private static JButton CreateImageButton(String fileName) {
        JButton retVal = new JButton("xxx");
        return retVal;
    }

    public MoviePanel() {
        this.setLayout(new GridBagLayout());
        this.setBackground(Color.WHITE);

        JButton btnRefresh = CreateImageButton("refresh.png");
        GridBagConstraints c = new GridBagConstraints(); 
        c.gridx=0;
        c.gridy=0;
        c.fill = GridBagConstraints.NORTH;
        c.insets.left = 10; c.insets.right = 10; c.insets.top = 10;
        this.add(btnRefresh, c);

        JComboBox cbMovieList = new JComboBox();
        c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets.right = 10; c.insets.top = 10;
        c.weightx = 1.0;
        this.add(cbMovieList, c);

        JButton btnAuthorize = new JButton("Get Info");
        c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 1;
        c.anchor = GridBagConstraints.WEST;
        c.insets.top = 10;
        this.add(btnAuthorize, c);

        JTextArea txtInfo = new JTextArea();
        txtInfo.setFont( new Font("SansSerif", Font.BOLD, 12));
        txtInfo.setBackground(Color.cyan);
        // txtInfo.setText("abc\ndef");
        txtInfo.setText("abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyz");
        c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 2;
        c.anchor = GridBagConstraints.NORTHWEST;
        c.weighty = 1.0;
        c.insets.top = 10;

        this.add(txtInfo, c);

        JPanel controllerOuter = new JPanel();
        controllerOuter.setLayout(new BoxLayout(controllerOuter, BoxLayout.Y_AXIS));
        controllerOuter.setBorder(BorderFactory.createRaisedBevelBorder());

        FlowLayout controllerLayout = new FlowLayout(FlowLayout.CENTER);
        controllerLayout.setHgap(0);
        JPanel controller = new JPanel(controllerLayout);

        controller.setBorder(new EmptyBorder(10, 10, 10, 10));

        Dimension dim = new Dimension(60, 40);
        JButton btnPlay = CreateImageButton("play.png");
        btnPlay.setPreferredSize(dim);

        controller.add(btnPlay);
        JButton btnPause = CreateImageButton("pause.png");
        btnPause.setPreferredSize(dim);
        controller.add(btnPause);
        JButton btnStop = CreateImageButton("stop.png");
        btnStop.setPreferredSize(dim);
        controller.add(btnStop);
        JButton btnForward = CreateImageButton("forward.png");
        btnForward.setPreferredSize(dim);
        controller.add(btnForward);
        JComboBox cbAspectRatio = new JComboBox();
        cbAspectRatio.setPreferredSize(new Dimension(100, 40));
        cbAspectRatio.setBorder(new EmptyBorder(0, 10, 0, 0));
        controller.add(cbAspectRatio);

        controllerOuter.add(controller);

        JProgressBar pbProgress = new JProgressBar(0, 100);
        pbProgress.setPreferredSize(new Dimension(350, 40));
        pbProgress.setBorder(new EmptyBorder(0, 10, 10, 10));
        pbProgress.setValue(50);
        pbProgress.setString("50/100");
        pbProgress.setStringPainted(true);
        pbProgress.setForeground(Color.BLUE);
        pbProgress.setBorderPainted(true);
        controllerOuter.add(pbProgress);


        c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 2;
        c.weightx = 1.0;
        this.add(controllerOuter, c);
    }

Here is the image

最佳答案

我在您的代码中看到了一些内容:

  1. 您强制使用 JButton 的首选大小。如果可能的话,我会删除它,因为这通常会给你带来更多的问题而不是解决方案。如果你想强制使用preferredSize,你还应该注意设置最小和最大尺寸,否则你会得到像你所观察到的奇怪的行为
  2. 您使用 BoxLayout 来显示控件。虽然这是完全可以接受的,但 BoxLayout 还依赖于最小/最大尺寸来执行布局,而这是您没有设置的。
  3. 您使用叠瓦式布局。这也很好,但为什么不只使用 MoviePanel 的 GridBagLayout 呢?
  4. 通常 TextArea 会包裹在 JScrollPane 中,以防文本太大。您还可以在 TextArea 上设置LineWrap(true),这样它就不会在右侧走得太远。通过在 TextArea 上设置行/列,您将定义其首选大小(以防止它依赖于其包含的文本)。
  5. GridBagConstraints 上,填充属性只能是:NONEVERTICALHORIZONTALBOTH(您对其中之一使用了 VERTICAL)。另外,不需要重新创建新实例,您可以一遍又一遍地重复使用相同的 GridBagConstraint,当您为组件设置约束时,LayoutManager 会自动克隆它。

现在对于解决方案,我找到了几个:

  1. 添加 contollerOuter 时,还要指定 c.fill = GridBagConstraints.HORIZONTAL;(这是解决问题的最简单方法)
  2. 当您设置 JButton 的preferredSize 时,还要强制它们的minimumSize 为相同的值。
  3. 仅使用 GridBagLayout 来布局所有组件。 (这是我最喜欢的)
  4. 将 FlowLayout 替换为带有 X_AXIS 的 BoxLayout。

记住 GridBagConstraints 属性:

  • gridx、gridy:指定位置
  • gridwidth、gridheight:指定列跨度/行跨度
  • weightx、weighty:指定谁获得额外的水平/垂直空间以及比例
  • anchor :如果“单元格”大于组件,则指定组件与其“单元格”的对齐方式
  • fill:指定组件是否应拉伸(stretch)至单元格宽度/高度

关于java - GridBagLayout - 一行的高度导致下一行的宽度发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10507257/

相关文章:

java - “必须使用 Types 类型的封闭实例来限定分配”

java - Collections.sort 中的 Comparator<> 面临问题

Java KeyListener 断断续续

java - 程序运行时JButton中的图标不显示,可能是什么原因?

java - 从一个类获取文本字段信息并将其显示在另一类的 JTextArea 上

java - 导入 javax.annotation.PostConstruct 无法解析

java - 从 EDT 调用 invokeAndWait

java - 显示图像,Java

java - 使用双缓冲有点毁了我的小程序。并且它有 java 使用或覆盖已弃用的 API

java Graphics2D - 生成动态图像