I want a rectangular GUI with 4 quadrants. The ratio of the height to the width of the JFrame (not including the minimize/maximize/close buttons) should be 1 to phi, where phi equals the golden ratio (roughly 1.62).
我想要一个带有4个象限的矩形GUI。 JFrame的高度与宽度的比率(不包括最小化/最大化/关闭按钮)应为1到phi,其中phi等于黄金比率(大约1.62)。
Now, for the four quadrants inside the JFrame. The JFrame has a horizontal dividing line that splits the height into two parts, an upper and a lower. The ratio between the height of the upper and the height of the lower should also be phi to one. Finally, the JFrame has a vertical dividing line that splits the width into two parts, a left and a right. The ratio between the left side and the right side should also be one to phi. See image above.
现在,对于JFrame内的四个象限。 JFrame具有水平分界线,将高度分成两部分,上部和下部。鞋面的高度与下部的高度之间的比率也应该是phi到1。最后,JFrame有一条垂直分界线,将宽度分成两部分,左边和右边。左侧和右侧之间的比率也应该是1。见上图。
Now, here's the tough part. I want these four components to always obey the ratios no matter what Swing component (JScrollPane, JList, JTextArea, JPanel, JTree, or JButton) gets put into the corresponding grid location. For example, I want to be able to start with four JButtons in the four grid locations, and then swap one of the JPanels with a JScrollPane that has a JList in it without the inner component changing the relative ratios of the outer components, even if the inner component has some text or data or something in it. See image below.
现在,这是艰难的部分。我希望这四个组件始终遵循比率,无论Swing组件(JScrollPane,JList,JTextArea,JPanel,JTree或JButton)放入相应的网格位置。例如,我希望能够从四个网格位置中的四个JButton开始,然后将其中一个JPanel与一个具有JList的JScrollPane交换,而内部组件不会改变外部组件的相对比例,即使内部组件中包含一些文本或数据。见下图。
No matter how hard I try to implement it (using GridBadLayout and a set of constrains), I can't get the gridlines to stay put. How do I make the gridlines stay in place?
无论我多么努力地实现它(使用GridBadLayout和一组约束),我都无法让网格线保持不变。如何使网格线保持原位?
So far I have source code that looks like this:
到目前为止,我有源代码,如下所示:
public static final double GOLDEN_RATIO = 1.6180339887498948482;
public static final double RELATIVE_LENGTH_OF_LONGER_SIDE = 1 / GOLDEN_RATIO;
public static final double RELATIVE_LENGTH_OF_SHORTER_SIDE = 1 - (1/GOLDEN_RATIO);
// ...
// make GridBagLayout
pane.setLayout(new GridBagLayout());
final GridBagConstraints c = new GridBagConstraints();
// Make 4 components to put in the four grid spaces.
JButton filler1 = new JButton();
c.fill = GridBagConstraints.BOTH;
c.weightx = RELATIVE_LENGTH_OF_SHORTER_SIDE;
c.weighty = RELATIVE_LENGTH_OF_LONGER_SIDE;
c.gridx = 0;
c.gridy = 0;
filler1.setMinimumSize(new Dimension(0,0));
filler1.setPreferredSize(new Dimension(0,0));
pane.add(filler1, c);
JButton filler2 = new JButton();
c.fill = GridBagConstraints.BOTH;
c.weightx = RELATIVE_LENGTH_OF_LONGER_SIDE;
c.weighty = RELATIVE_LENGTH_OF_LONGER_SIDE;
c.gridx = 1;
c.gridy = 0;
filler2.setMinimumSize(new Dimension(0,0));
filler2.setPreferredSize(new Dimension(0,0));
pane.add(filler2, c);
JButton filler3 = new JButton();
c.fill = GridBagConstraints.BOTH;
c.weightx = RELATIVE_LENGTH_OF_SHORTER_SIDE;
c.weighty = RELATIVE_LENGTH_OF_SHORTER_SIDE;
c.gridx = 0;
c.gridy = 1;
filler3.setMinimumSize(new Dimension(0,0));
filler3.setPreferredSize(new Dimension(0,0));
pane.add(filler3, c);
JButton filler4 = new JButton();
c.fill = GridBagConstraints.BOTH;
c.weightx = RELATIVE_LENGTH_OF_LONGER_SIDE;
c.weighty = RELATIVE_LENGTH_OF_SHORTER_SIDE;
c.gridx = 1;
c.gridy = 1;
filler4.setMinimumSize(new Dimension(0,0));
filler4.setPreferredSize(new Dimension(0,0));
pane.add(filler4, c);
// Set the size of the enclosing panel.
this.setPreferredSize(new Dimension(
(int)(screen_height_*RELATIVE_LENGTH_OF_LONGER_SIDE),
(int)(screen_height_*RELATIVE_LENGTH_OF_SHORTER_SIDE))
);
Also, no matter how small I make the size, it should never look like this:
此外,无论我的尺寸有多小,它都不应该像这样:
2 个解决方案
#1
You can use GroupLayout
to do the work for you.
您可以使用GroupLayout为您完成工作。
Edit: Added the swap button
编辑:添加了交换按钮
Example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.WindowConstants;
public class Test extends JFrame {
public static final double GOLDEN_RATIO = 1.6180339887498948482;
public static final double RELATIVE_LENGTH_OF_LONGER_SIDE = 1 / GOLDEN_RATIO;
public static final double RELATIVE_LENGTH_OF_SHORTER_SIDE = 1 - (1 / GOLDEN_RATIO);
private static final int screenHeight = 500;
private static final int LENGTH_OF_LONGER_SIDE_FOR_RATIO = (int) (screenHeight * RELATIVE_LENGTH_OF_LONGER_SIDE);
private static final int LENGTH_OF_SHORTER_SIDE_FOR_RATIO = (int) (screenHeight * RELATIVE_LENGTH_OF_SHORTER_SIDE);
private static final int MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO = (int) (50 * RELATIVE_LENGTH_OF_LONGER_SIDE);
private static final int MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO = (int) (50 * RELATIVE_LENGTH_OF_SHORTER_SIDE);
public Test() {
buildGUI();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void buildGUI() {
JPanel pane = new JPanel();
// make GridBagLayout
GroupLayout layout = new GroupLayout(pane);
pane.setLayout(layout);
// Make 4 components to put in the four grid spaces.
JButton filler1 = new JButton("Press here to swap");
JButton filler2 = new JButton("Press here to swap");
JButton filler3 = new JButton("Press here to swap");
Object[] objects = new Object[50];
for (int i = 0; i < 50; i++) {
objects[i] = "Test" + i;
}
JTree jTree = new JTree(objects);
JScrollPane scrollPane = new JScrollPane(jTree);
JButton button = new JButton("Press here to swap");
JPanel filler4 = new JPanel(new BorderLayout());
filler4.add(button);
ActionListener l = (e) -> {
if (filler4.getComponents()[0] instanceof JButton) {
filler4.remove(button);
filler4.add(scrollPane, BorderLayout.CENTER);
} else {
filler4.remove(scrollPane);
filler4.add(button, BorderLayout.CENTER);
}
filler4.repaint();
filler4.revalidate();
};
filler1.addActionListener(l);
filler2.addActionListener(l);
filler3.addActionListener(l);
button.addActionListener(l);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler1, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler2, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler3, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler4, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
));
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler1, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler3, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler2, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler4, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
));
add(pane);
setSize(new Dimension(200, 200));
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new Test().setVisible(true);
});
}
}
#2
You should create your own LayoutManager. The only method I think you'd really need to implement is layoutContainer. In this method, you can setup the subcomponents (should be 4) using the ratios you've specified
您应该创建自己的LayoutManager。我认为你真正需要实现的唯一方法是layoutContainer。在此方法中,您可以使用指定的比率设置子组件(应为4)
#1
You can use GroupLayout
to do the work for you.
您可以使用GroupLayout为您完成工作。
Edit: Added the swap button
编辑:添加了交换按钮
Example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.WindowConstants;
public class Test extends JFrame {
public static final double GOLDEN_RATIO = 1.6180339887498948482;
public static final double RELATIVE_LENGTH_OF_LONGER_SIDE = 1 / GOLDEN_RATIO;
public static final double RELATIVE_LENGTH_OF_SHORTER_SIDE = 1 - (1 / GOLDEN_RATIO);
private static final int screenHeight = 500;
private static final int LENGTH_OF_LONGER_SIDE_FOR_RATIO = (int) (screenHeight * RELATIVE_LENGTH_OF_LONGER_SIDE);
private static final int LENGTH_OF_SHORTER_SIDE_FOR_RATIO = (int) (screenHeight * RELATIVE_LENGTH_OF_SHORTER_SIDE);
private static final int MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO = (int) (50 * RELATIVE_LENGTH_OF_LONGER_SIDE);
private static final int MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO = (int) (50 * RELATIVE_LENGTH_OF_SHORTER_SIDE);
public Test() {
buildGUI();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void buildGUI() {
JPanel pane = new JPanel();
// make GridBagLayout
GroupLayout layout = new GroupLayout(pane);
pane.setLayout(layout);
// Make 4 components to put in the four grid spaces.
JButton filler1 = new JButton("Press here to swap");
JButton filler2 = new JButton("Press here to swap");
JButton filler3 = new JButton("Press here to swap");
Object[] objects = new Object[50];
for (int i = 0; i < 50; i++) {
objects[i] = "Test" + i;
}
JTree jTree = new JTree(objects);
JScrollPane scrollPane = new JScrollPane(jTree);
JButton button = new JButton("Press here to swap");
JPanel filler4 = new JPanel(new BorderLayout());
filler4.add(button);
ActionListener l = (e) -> {
if (filler4.getComponents()[0] instanceof JButton) {
filler4.remove(button);
filler4.add(scrollPane, BorderLayout.CENTER);
} else {
filler4.remove(scrollPane);
filler4.add(button, BorderLayout.CENTER);
}
filler4.repaint();
filler4.revalidate();
};
filler1.addActionListener(l);
filler2.addActionListener(l);
filler3.addActionListener(l);
button.addActionListener(l);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler1, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler2, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler3, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler4, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
));
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler1, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler3, MIN_LENGTH_OF_SHORTER_SIDE_FOR_RATIO, LENGTH_OF_SHORTER_SIDE_FOR_RATIO, Short.MAX_VALUE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(filler2, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
.addComponent(filler4, MIN_LENGTH_OF_LONGER_SIDE_FOR_RATIO, LENGTH_OF_LONGER_SIDE_FOR_RATIO, Short.MAX_VALUE)
));
add(pane);
setSize(new Dimension(200, 200));
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new Test().setVisible(true);
});
}
}
#2
You should create your own LayoutManager. The only method I think you'd really need to implement is layoutContainer. In this method, you can setup the subcomponents (should be 4) using the ratios you've specified
您应该创建自己的LayoutManager。我认为你真正需要实现的唯一方法是layoutContainer。在此方法中,您可以使用指定的比率设置子组件(应为4)