[英]How to dynamically control auto-resize components in Java Swing
Creating a new GUI in Java (1.8) Swing, I am searching for a way to override resize behavior of all my components. 我正在Java(1.8)Swing中创建新的GUI,我正在寻找一种方法来覆盖我所有组件的调整大小行为。
Let me explain to you with some edited photos: 让我向您解释一些编辑后的照片:
This is my full screen GUI, with 3 panels and a JToolBar
. 这是我的全屏GUI,带有3个面板和一个
JToolBar
。 The green one needs to have a fixed size , the others would be resizable . 绿色的需要固定大小 ,其他的则需要调整大小 。
Currently, I only have 2 small GridLayout
to organize them (one vertical, and one horizontal for green and cyan panels). 目前,我只有2个小的
GridLayout
来组织它们(一个垂直,绿色和青色面板一个水平)。
If I, for example, reduce the frame size from the right side, I want my blue and cyan panel to be resized according to the new frame size. 例如,如果我从右侧减小框架尺寸,我希望根据新的框架尺寸调整我的蓝色和青色面板的尺寸。 But the green panel must be fixed .
但是绿色面板必须固定 。 (Not the most difficult part I think.)
(这不是我认为最困难的部分。)
This is the most difficult part for me. 这对我来说是最困难的部分。 As soon as the cyan (or blue) panel reach is minimum size, I want him to " push " the green panel to the left, even if it disappears off the frame.
一旦青色(或蓝色)面板达到最小尺寸,我希望他将绿色面板“ 推 ”到左侧,即使它从框架中消失了。
Of course, pulling the frame to the right will make the green panel appear again. 当然,将框架向右拉将使绿色面板再次出现。
How could I do it? 我该怎么办?
I thought of using JSplitPane
or a specific listener to manually decide the resize behavior but I need some advice. 我考虑过使用
JSplitPane
或特定的侦听器来手动确定调整大小的行为,但我需要一些建议。
Sorry if an existing post can answer this, I didn't find any answer explaining the issue for me. 抱歉,如果现有帖子可以回答这个问题,我没有找到任何答案为我解释问题。
Thanks in advance! 提前致谢!
If you want more examples, look at the "Evernote" software which acts the same way 如果您需要更多示例,请查看功能相同的“ Evernote”软件
Setting the max/min/preferred size of the Green
panel can keep that panel the same size under the first condition. 设置
Green
面板的最大/最小/首选尺寸可以使面板在第一种情况下保持相同的尺寸。 To check for resizes, you can use a ComponentListener
on one of the other JPanel
's - if the size gets below a particular width then change the max/min/preferred size of the Green
panel. 要检查大小,可以在其他
JPanel
之一上使用ComponentListener
如果大小小于特定宽度,则更改“ Green
面板的最大/最小/首选大小。
Below is a hacked together example of doing this - it resizes the Green
panel when the Blue
is < 600, and the resize is a weighted resize (30% of total width). 以下是一起执行此操作的示例-当
Blue
<600时,它将调整Green
面板的大小,并且调整大小是加权调整大小(占总宽度的30%)。 To get the true L&F and that you desire you may have to play with the layout/sizes. 要获得真正的L&F,您可能需要尝试布局/尺寸。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
public class GridTest extends JPanel{
private boolean changeAllowed = false;
//keep reference to cyan for the height dimension
final JPanel cyan = new JPanel();
public GridTest(){
cyan.setPreferredSize(new Dimension(600, 300));//provide sizing hint
}
private Dimension getCustomDimensions(){
if ( changeAllowed ){
return new Dimension((int)(super.getParent().getBounds().width * 0.3), cyan.getBounds().height);
}else{
return new Dimension(200, cyan.getBounds().height);
}
}
@Override
public Dimension getMaximumSize(){
return getCustomDimensions();
}
@Override
public Dimension getMinimumSize(){
return getCustomDimensions();
}
@Override
public Dimension getPreferredSize(){
return getCustomDimensions();
}
public static void main(String[] args) throws Exception{
SwingUtilities.invokeAndWait(new Runnable(){
@Override
public void run() {
final int MINIMUM = 600;
JFrame frame = new JFrame();
frame.add(new JToolBar(), BorderLayout.NORTH);
final JPanel blue = new JPanel();
final GridTest green = new GridTest();
green.setBackground(Color.green);
green.setOpaque(true);
green.cyan.setBackground(Color.cyan);
green.cyan.setOpaque(true);
blue.setOpaque(true);
blue.setBackground(Color.blue);
blue.setPreferredSize(new Dimension(900, 300));//hint at size
blue.setMinimumSize(new Dimension(100, 200));//hint at size
//Nest Box Layouts
Box top = Box.createHorizontalBox();
top.add(blue);
Box bottom = Box.createHorizontalBox();
bottom.add(green);
bottom.add(green.cyan);
Box vert = Box.createVerticalBox();
vert.add(top);
vert.add(bottom);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(vert);
//listen for resizes
blue.addComponentListener(new ComponentAdapter(){
@Override
public void componentResized(ComponentEvent e) {
if ( blue.getBounds().width < MINIMUM ){//set flag
green.changeAllowed = true;
}else{
green.changeAllowed = false;
}
}
});
frame.pack();
frame.setSize(800, 600);
frame.setVisible(true);
}
});
}
}
This is how I do it and I am not sure this is the proper way: 这是我的操作方式,我不确定这是否正确:
First set the layout to null. 首先将布局设置为null。
Next create a component resized event for your frame: 接下来,为框架创建组件调整大小事件:
addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e){
}
});
Inside here you can manually make changes to the components as it is resized. 在这里,您可以在调整大小后手动更改组件。 I have done this for a few of my programs to keep a scroll pane on the left and right of the frame always the same width and have everything else size up and down as resized.
我为一些程序执行了此操作,以使框架左右两侧的滚动窗格始终保持相同的宽度,并使其他所有内容的大小都随着调整大小而变大。
This should be easy with a GridBagLayout, provided you set appropiate minimum sizes for the green and cyan components: 如果您为绿色和青色组件设置了适当的最小尺寸,那么使用GridBagLayout应当很容易:
setLayout(new GridBagLayout());
green.setMnimumSize(new Dimension(0, 0));
cyan.setMinimumSize(new Dimension(100, 100)); // whatever fits
add(blue, new GridBagConstraints(0, 0, 2, 1,
1.0, 0.0,
GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0);
add(green, new GridBagConstraints(0, 1, 1, 1,
0.0, 0.0,
GridBagConstraints.WEST, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0);
add(cyan, new GridBagConstraints(1, 1, 1, 1,
1.0, 0.0,
GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0);
By specifying a weight x for cyan and blue component as well as setting resize = HORIZONTAL they resize with the container. 通过为青色和蓝色分量指定权重x并设置resize = HORIZONTAL,它们将随容器调整大小。
You can use a BoxLayout
to contain the green and cyan panel. 您可以使用
BoxLayout
包含绿色和青色面板。 A BoxLayout
respects the minimum and maximum sizes of a component. BoxLayout
遵循组件的最小和最大大小。 So for the green panel you set then maximum size equal to the preferred size and for the cyan panel you set the minimum size equal to the preferred size: 因此,对于绿色面板,将最大大小设置为等于首选大小,对于青色面板,将最小大小设置为等于首选大小:
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
JPanel blue = new JPanel();
blue.setBackground( Color.BLUE );
blue.setPreferredSize( new Dimension(500, 100) );
Box box = Box.createHorizontalBox();
JPanel green = new JPanel();
green.setBackground( Color.GREEN );
green.setPreferredSize( new Dimension(200, 100) );
green.setMaximumSize( green.getPreferredSize() );
box.add( green );
JPanel cyan = new JPanel();
cyan.setBackground( Color.CYAN );
cyan.setPreferredSize( new Dimension(300, 100) );
cyan.setMinimumSize( cyan.getPreferredSize() );
box.add( cyan );
setLayout( new BorderLayout() );
add(blue, BorderLayout.NORTH);
add(box, BorderLayout.CENTER);
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Of course the proper solution is to override the getMaximumSize()
and getMinimumSize()
methods respectively of each panel to just return the preferred size of the panel. 当然,正确的解决方案是分别重写每个面板的
getMaximumSize()
和getMinimumSize()
方法,以仅返回面板的首选大小。
The important sequence is this: 重要的顺序是这样的:
frame.revalidate();
frame.pack();
frame.repaint();
Use this sequence after each series of changes, you have done in your code and want to see the results appearing on screen. 在完成每一系列更改之后,请使用此顺序,您已经在代码中完成了操作,并希望看到显示在屏幕上的结果。
I like the java.awt.GridBagLayout in combination with the java.awt.GridBagConstraints and I use this layout on all containers starting up from the content pane. 我喜欢java.awt.GridBagLayout中与java.awt.GridBagConstraints中的结合,我用从内容窗格中启动所有的容器此布局。
If you add a container into an other container use a layout on each of them, otherwise the calculation fails because of a missing layout in the hierarchy. 如果将一个容器添加到另一个容器中,请在每个容器上使用一个布局,否则由于层次结构中缺少布局,计算将失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.