已经构建了一个带有三个面板的小型测试 SWING 应用程序。一个主 JPanel,其中包含两个较小的 JPanel。一个在左边(板面板),另一个在右边(侧面板)。通过调用 min、preferred 和 max size 方法,将两个内部面板设置为请求的特定大小。右侧面板中的按钮将父 JFrame 设置为不可调整大小。在将父框架设置为不可调整大小之前,一切看起来都很棒,这会导致(?!)调整框架和主面板的大小,使其变大。
寻找调整大小的原因,以及可以做些什么来保持主面板和框架的大小以仅包含两个内部面板,一旦框架被冻结,就不再多了。
突出显示面板边框并添加绘画事件日志记录以调试尺寸问题。
感谢您的帮助和见解!
编辑: 这个问题出现在 JRE 8 中。在 JRE 9 中它消失了,但引入了缩放问题。整个应用程序在我的 4k 显示器上放大,运行 Windows 10。
package org.fubar;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PanelTest {
private static final String appTitle = "JPanel Test by Fubar.org(c)";
public static JFrame myFrame = null;
public static JPanel mainPanel = null;
public static JPanel boardPanel = null;
public static JPanel sidePanel = null;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
System.out.println("Create and show GUI");
JFrame myFrame = new JFrame(appTitle);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new MainPanel();
myFrame.add(mainPanel);
myFrame.pack();
centreWindow(myFrame);
myFrame.setVisible(true);
}
public static void centreWindow(Window frame) {
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
public static void barfSize(JPanel panel, String panelName) {
Dimension panelSize = panel.getSize();
System.out.println(String.format("%s size:(%d,%d);",panelName,panelSize.width,panelSize.height));
}
}
class MainPanel extends JPanel {
static final long serialVersionUID = 1;
public MainPanel() {
setBorder(BorderFactory.createLineBorder(Color.green));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
PanelTest.boardPanel = new BoardPanel();
PanelTest.boardPanel.setAlignmentY(TOP_ALIGNMENT);
add(PanelTest.boardPanel);
PanelTest.sidePanel = new SidePanel();
PanelTest.sidePanel.setAlignmentY(TOP_ALIGNMENT);
add(PanelTest.sidePanel);
}
public void paintComponent(Graphics gooey) {
super.paintComponent(gooey);
PanelTest.barfSize(this, "Main Panel");
}
}
class BoardPanel extends JPanel {
static final long serialVersionUID = 1;
public BoardPanel() {
setBorder(BorderFactory.createLineBorder(Color.red));
Dimension mySize = new Dimension(400,200);
setMinimumSize(mySize);
setPreferredSize(mySize);
setMaximumSize(mySize);
JLabel lblText = new JLabel("Board Panel");
add(lblText);
}
public void paintComponent(Graphics gooey) {
super.paintComponent(gooey);
PanelTest.barfSize(this, "Board Panel");
}
}
class SidePanel extends JPanel implements ActionListener {
static final long serialVersionUID = 1;
public SidePanel() {
setBorder(BorderFactory.createLineBorder(Color.blue));
Dimension mySize = new Dimension(200,200);
setMinimumSize(mySize);
setPreferredSize(mySize);
setMaximumSize(mySize);
JLabel lblText = new JLabel("Side Panel");
add(lblText);
JButton btnFreeze = new JButton("Freeze");
btnFreeze.setActionCommand("Freeze");
btnFreeze.setToolTipText("Click me to freeze frame");
btnFreeze.setBorderPainted(true);
btnFreeze.setEnabled(true);
btnFreeze.addActionListener(this);
add(btnFreeze);
}
public void actionPerformed(ActionEvent action) {
String command = action.getActionCommand();
if ( command == "Freeze") {
freezeFrame();
System.out.println("Froze frame.");
}
Dimension panelSize = getSize();
System.out.println(String.format("Side Panel size:(%d,%d);",panelSize.width,panelSize.height));
}
public void paintComponent(Graphics gooey) {
super.paintComponent(gooey);
PanelTest.barfSize(this, "Side Panel");
}
public void freezeFrame() {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
Dimension parentSize = this.getParent().getSize();
topFrame.setMaximumSize(parentSize);
topFrame.setResizable(false);
}
}
运行日志
Create and show GUI
Main Panel size:(602,202);
Side Panel size:(200,200);
Board Panel size:(400,200);
Main Panel size:(602,202);
Side Panel size:(200,200);
Board Panel size:(400,200);
Froze frame.
Side Panel size:(200,200);
Main Panel size:(618,218);
Side Panel size:(200,200);
Board Panel size:(400,200);
Main Panel size:(618,218);
Side Panel size:(200,200);
Board Panel size:(400,200);
如果您在第一次创建时将 JFrame 设置为 setResizable(false),则不会出现此问题。
JFrame myFrame = new JFrame(appTitle);
myFrame.setResizable(false);
我认为问题出在您放置
.pack()
的地方。此命令会自动将所有子组件设置为其首选大小。因此,您可以将 .setResizable(false)
放在 .pack()
命令之前,也可以将其删除。但请记住,删除它后,您必须使用 .setBounds
或 .setSize()
等替代方法手动调整所有子组件的大小