【问题标题】:Java FlowLayout inside FlowLayoutFlowLayout 内的 Java FlowLayout
【发布时间】:2019-02-13 11:46:24
【问题描述】:

我正在尝试设计类似于浏览器标题栏(浏览器顶部)。左侧有选项卡,右侧有最小化、调整大小(最小化/最大化)、退出按钮。

为此,我尝试过。

JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
JPanel tabpanel= new JPanel();
tabpanel.setLayout(new  FlowLayout(FlowLayout.LEFT));
tabpanel.add(new JButton("Tab 1"));
tabpanel.add(new JButton("Tab 2"));
panel.add(tabpanel); 
panel.add(new JButton("Minimize")); 
panel.add(new JButton("Resize")); 
panel.add(new JButton("Quit")); 

根据我的需要在右侧创建了退出、调整大小、最小化按钮,但在最小化按钮附近创建的选项卡而不是框架的左侧。我认为应该有方法或任何东西来填充剩余的内容,还是应该使用其他布局?任何帮助表示赞赏

【问题讨论】:

  • 我只是想说-GridBagLayout
  • @MadProgrammer 异端!!!! ;-)(说真的,GridBagLayoutsomewhat awkward to use 闻名)。根据描述,听起来可以通过将BorderLayout 放入标题栏中并将两个带有按钮的面板放入EASTWEST 来解决。 @Tekin 如果您认为这可以解决问题,我会写这个作为答案,包括minimal reproducible example)
  • 在发布@Marco13 建议的 MCVE 时:提供 ASCII 艺术或 GUI 的 预期 布局的简单绘图,最小尺寸,如果可调整大小,则具有更大的宽度和高度 - 显示应该如何使用额外的空间。
  • @Marco13 GridBagLayout 是可用的最灵活的布局管理器,但也带来了复杂性。它将解决 OP 在单个容器中非常简单地描述的问题
  • @Marco13 好了,用 9 行代码解决了????????

标签: java swing user-interface layout-manager


【解决方案1】:

我强烈推荐GridBagLayout,它是可用的最灵活和可配置的布局管理器之一,但它确实带来了复杂性

public class HeaderPane extends JPanel {

    public HeaderPane() {
        setLayout(new GridBagLayout());

        add(new JButton("Tab 1"));
        add(new JButton("Tab 2"));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 1;
        gbc.anchor = GridBagConstraints.BASELINE_TRAILING;

        add(new JButton("Minimize"), gbc);
        add(new JButton("Maximise"));
        add(new JButton("Close"));          
    }

}

Arrgggh,复杂性燃烧,它燃烧? 讽刺

所以,这个解决方案是一个容器,带有一个布局管理器。我并不是说更复杂的需求可能会受益于复合解决方案(我很想将最小/最大/关闭和选项卡按钮放在自己的容器中),但作为起点,它相对简单。

可运行示例

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new HeaderPane(), BorderLayout.NORTH);
                frame.add(new JPanel() { 
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(600, 200);
                    }                   
                });
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class HeaderPane extends JPanel {

        public HeaderPane() {
            setLayout(new GridBagLayout());

            add(new JButton("Tab 1"));
            add(new JButton("Tab 2"));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.BASELINE_TRAILING;

            add(new JButton("Minimize"), gbc);
            add(new JButton("Maximise"));
            add(new JButton("Close"));          
        }

    }

}

【讨论】:

  • (1+) 通过这个例子学到了一些东西:1)如果你不指定约束,你会得到一个“流布局” 2)我不知道布局管理器在 Mac 中的工作方式不同与 Windows。在这个示例和 Hao 在 Windows 上的 BoxLayout 示例中,组件之间没有间距。我认为控制间距是布局管理器的工作。 Mac 是否会以某种方式覆盖它以确保组件之间存在间隙?我原以为您需要使用“插入”约束来获得组件之间的间隙。
  • @camickr 我认为这取决于按钮的工作方式 - mac 按钮有额外的焦点边框插入
  • @MadProgrammer 实际上所有的方法都解决了我的问题,但我决定使用 Gridbaglayout,但我不明白 Gridbaglayout 是如何做到的。 GridBagConstraints.BASELINE_TRAILING 是关键,但我无法得到它。有没有很好的解释可以理解?
  • @TekinGüllü How to use GridBagLayout 将是一个很好的起点。 anchor 属性只是告诉布局在单元格中要放置组件的位置,BASELINE_TRAILING 表示组件应沿后缘水平放置。 “后沿”对于从左到右和从右到左的语言有不同的含义
【解决方案2】:

我建议使用BoxLayout作为panel的布局管理器来组织左右部分。

完整的演示代码如下:

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

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()->{
            JFrame frame = new JFrame("Solution");
            JPanel container = new JPanel();
            container.setLayout(new BorderLayout());

            JPanel panel = new JPanel();
            panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
            JPanel tabpanel= new JPanel();
            tabpanel.setLayout(new  FlowLayout(FlowLayout.LEFT));
            tabpanel.add(new JButton("Tab 1"));
            tabpanel.add(new JButton("Tab 2"));
            panel.add(tabpanel);
            panel.add(new JButton("Minimize"));
            panel.add(new JButton("Resize"));
            panel.add(new JButton("Quit"));

            container.add(panel, BorderLayout.PAGE_START);
            frame.add(container);
            frame.pack();
            frame.setSize(new Dimension(500,500));
            frame.setVisible(true);
        });
    }
}

它的样子:

【讨论】:

  • (1+) 但是,据我所知 BoxLayout 不会自动在组件之间添加间距。当我在 Windows 上运行您的代码时,Minimize/Resize/Quit 按钮没有间距,您需要在组件之间添加 Box.createHorizo​​ntalStrut(5) 以获得与 FlowLayout 默认情况下相同的 5 像素间距。使用 BoxLayout 您也不需要 tabPanel。您只需添加按钮,然后在第二个选项卡按钮之后使用 Box.addHorizo​​ntalGlue() 。请参阅Using Invisible Components as Filler 上的 Swing 教程。
【解决方案3】:

正如 cmets 中所建议的:一种解决方案是将“选项卡”和“按钮”放入单独的面板中,并将它们添加到标题面板的 WESTEAST 中,其中有一个 BorderLayout

这是 MCVE:

import java.awt.BorderLayout;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TitleBarLayout
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        JPanel mainPanel = new JPanel(new BorderLayout());

        JPanel titleBar = new JPanel(new BorderLayout());

        JPanel tabPanel = new JPanel();
        tabPanel.setLayout(new FlowLayout());
        tabPanel.add(new JButton("Tab 1"));
        tabPanel.add(new JButton("Tab 2"));
        titleBar.add(tabPanel, BorderLayout.WEST);

        JPanel buttonsPanel = new JPanel();
        buttonsPanel.add(new JButton("Minimize"));
        buttonsPanel.add(new JButton("Resize"));
        buttonsPanel.add(new JButton("Quit"));
        titleBar.add(buttonsPanel, BorderLayout.EAST);

        mainPanel.add(titleBar, BorderLayout.NORTH);

        f.getContentPane().add(mainPanel);
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 2013-08-22
    • 2013-06-02
    相关资源
    最近更新 更多