【问题标题】:Asymmetrical Layout in Java SwingJava Swing 中的非对称布局
【发布时间】:2019-02-24 13:53:44
【问题描述】:

是否可以在 Java Swing 中创建不对称布局(相对于方形布局)?我正在考虑这样的事情:

这可以通过任何布局管理器实现吗?如果没有,我也有兴趣解释一下。

【问题讨论】:

  • 是的,GridBagLayout 将是起点,但我也会考虑使用复合布局来实现更精细的控制
  • 如果您想到一个非矩形的窗户,那么您将进入一个充满乐趣的世界

标签: java swing layout layout-manager


【解决方案1】:

简短的回答是,是的,长的答案是更复杂一些。

首先,我会使用GridBagLayout 作为布局管理器的主要选择,但我可能会考虑将GridLayoutBorderLayout 作为附加选项。关键是,您希望将布局分解为可管理的功能块,并找出解决特定问题的最佳解决方案。然后,您希望将这些单独的元素拼凑成一张大图,使用最适合解决每个部分所呈现的问题的布局管理器。

我只想说你的基本布局让我尖叫JTable

但是,如果您对非矩形窗口感兴趣,那么它会变得有些困难,主要是因为 Java 不支持装饰透明窗口(即带有原生框架的窗口)

如果不是,我也有兴趣解释一下

好吧,这有点复杂,但是,它基本上归结为这样一个事实,即在屏幕上绘制的所有内容都包含在一个矩形边界框中。这个盒子填充了背景颜色,并在上面绘制了内容。

这样做是为了提高效率,因为不需要绘制此边界框后面的所有内容。

随着硬件变得更快,渲染管道更多地利用了更高端的库,如 DirectX 和 OpenGL,开始处理更广泛的系统范围内的不透明度成为可能,例如单个窗口。

因此,即使您看到非常酷、弯曲、时髦的 UI,它也包含在一个透明的矩形边界框内:/

这是非常基本的图形概念。请记住,计算矩形边界框(交叉点/命中检测等)要比计算非矩形边界框更容易、更快

每像素 alpha 实际上执行起来相当密集,这是它最初不是在操作系统/日常级别上使用的另一个原因,系统资源可以更好地用于其他事情

可运行示例

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

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.setUndecorated(true);
                frame.setBackground(new Color(0, 0, 0, 0));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {

        public MainPane() {
            setOpaque(false);
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 0.5;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.anchor = GridBagConstraints.NORTH;
            add(new FieldsPane(), gbc);

            gbc.gridx++;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;
            add(new JScrollPane(new JTextArea(20, 20)), gbc);
        }

    }

    public class FieldsPane extends JPanel {

        private JPanel fields;
        private JLabel filler;

        public FieldsPane() {
            setBorder(new LineBorder(Color.GRAY));
            fields = new JPanel(new GridBagLayout());
            filler = new JLabel();
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weighty = 1;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            fields.add(filler, gbc);

            addFields(new JLabel("Col1"), new JLabel("Col2"), new JLabel("Col3  "));
            addFields(new JTextField(10), new JTextField(10), new JTextField(10));

            setLayout(new GridBagLayout());
            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;
            add(fields, gbc);

            JPanel buttons = new JPanel(new GridBagLayout());
            JButton add = new JButton("Add");
            JButton remove = new JButton("Remove");
            buttons.add(add);
            buttons.add(remove);

            gbc.gridy++;
            gbc.weightx = 1;
            gbc.weighty = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(buttons, gbc);
        }

        protected void addFields(JComponent col1, JComponent col2, JComponent col3) {
            GridBagLayout layout = (GridBagLayout) fields.getLayout();
            GridBagConstraints gbc = layout.getConstraints(filler);
            fields.add(makeRow(col1, col2, col3), gbc);

            gbc.gridy++;
            layout.setConstraints(filler, gbc);
        }

        protected JPanel makeRow(JComponent col1, JComponent col2, JComponent col3) {
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridy = 0;
            gbc.weightx = 0.33;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            panel.add(col1, gbc);
            panel.add(col2, gbc);
            panel.add(col3, gbc);
            return panel;
        }

    }

}

【讨论】:

  • 很好的答案,谢谢!到目前为止,我还没有图形编程的经验,所以我不知道即使是那些“非常酷、弯曲、时髦的 UI”,正如你所说的那样,也是矩形框的一部分。但仔细想想,从数学的角度来看,这当然要容易得多。
  • 甚至可以追溯到基于 dos 和基于文本的解决方案,但请记住,当我在 Windows 3 中学习编码时,我读过一些东西,关于所有控件都是矩形的,无论它们绘制的形状如何
猜你喜欢
  • 2012-01-29
  • 2019-04-04
  • 2018-05-03
  • 2014-12-20
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
相关资源
最近更新 更多