Java Swing 中的不对称布局
Asymmetrical Layout in Java Swing
是否可以在 Java Swing 中创建不对称布局(相对于方形布局)?我在想这样的事情:
这是否可以通过任何布局管理器实现?如果没有,我也很想知道解释。
简短的回答是,是的,长的回答有些复杂。
首先,我将使用 GridBagLayout
作为布局管理器的主要选择,但我可能会考虑将 GridLayout
和 BorderLayout
作为附加选项。关键是,您想将布局分解为可管理的功能块,并找出解决其特定问题的最佳解决方案。然后,您想要将这些单独的元素拼凑成一张大图,使用最合适的布局管理器来解决每个元素呈现的问题。
我只想说你的基本布局让我尖叫 JTable
。
但是,如果您对非矩形 window 感兴趣,那么它会变得有些困难,主要是因为 Java 不支持装饰透明 windows(即,windows 使用原生帧)
If not, I'd be interested in an explanation, too
好吧,这有点复杂,但是,它基本上归结为屏幕上绘制的所有内容都包含在一个矩形边界框中。这个盒子填充了背景颜色,内容被绘制在上面。
这样做是为了提高效率,因为不需要绘制此边界框后面的所有内容。
随着硬件变得更快并且渲染管线更多地利用更高端的库,如 DirectX 和 OpenGL,开始处理更广泛的系统范围内的不透明度成为可能,例如个人 windows。
因此,即使您看到非常酷、弯曲、时髦的外观 UI,它也包含在透明的矩形边界框内 :/
这是非常基本的图形概念。请记住,计算矩形边界框 (intersections/hit detection/etc) 比计算非矩形边界框
更容易和更快
每像素 alpha 实际上执行起来相当密集,这是它最初未在 OS/every 天级别使用的另一个原因,系统资源可以更好地用于其他事情
可运行示例
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;
}
}
}
是否可以在 Java Swing 中创建不对称布局(相对于方形布局)?我在想这样的事情:
这是否可以通过任何布局管理器实现?如果没有,我也很想知道解释。
简短的回答是,是的,长的回答有些复杂。
首先,我将使用 GridBagLayout
作为布局管理器的主要选择,但我可能会考虑将 GridLayout
和 BorderLayout
作为附加选项。关键是,您想将布局分解为可管理的功能块,并找出解决其特定问题的最佳解决方案。然后,您想要将这些单独的元素拼凑成一张大图,使用最合适的布局管理器来解决每个元素呈现的问题。
我只想说你的基本布局让我尖叫 JTable
。
但是,如果您对非矩形 window 感兴趣,那么它会变得有些困难,主要是因为 Java 不支持装饰透明 windows(即,windows 使用原生帧)
If not, I'd be interested in an explanation, too
好吧,这有点复杂,但是,它基本上归结为屏幕上绘制的所有内容都包含在一个矩形边界框中。这个盒子填充了背景颜色,内容被绘制在上面。
这样做是为了提高效率,因为不需要绘制此边界框后面的所有内容。
随着硬件变得更快并且渲染管线更多地利用更高端的库,如 DirectX 和 OpenGL,开始处理更广泛的系统范围内的不透明度成为可能,例如个人 windows。
因此,即使您看到非常酷、弯曲、时髦的外观 UI,它也包含在透明的矩形边界框内 :/
这是非常基本的图形概念。请记住,计算矩形边界框 (intersections/hit detection/etc) 比计算非矩形边界框
更容易和更快每像素 alpha 实际上执行起来相当密集,这是它最初未在 OS/every 天级别使用的另一个原因,系统资源可以更好地用于其他事情
可运行示例
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;
}
}
}