Java 嵌套的 JPanel 未保持指定的大小
Java nested JPanel is not maintaining the specified size
我有一个 JFrame
,其中包含 2 个 JPanels
,其中一个是 JFrame
的 70%,另一个是剩余的 30%。 JPanel
是宽度的 30%,其中有一个嵌套的 JPanel。然而,这个嵌套的 JPanel
应该是其父级 JPanel 宽度的 50%,但是当它显示时,它占据了父级 JPanel
.
的整个宽度
父级 JPanel
属于 width 358
和 height 772
,嵌套的 JPanel
具有以下值:width 179
和 height 772
我已将这些组件的颜色设置为绿色和灰色,因此我可以轻松查看它们是否正确呈现。当我 运行 我的应用程序时,嵌套的 JPanel
实际上被呈现为好像它是 parent
的整个宽度(整个区域呈现绿色)。
这是当前的代码。
public class DisplayFrame extends JFrame{
private final static int WIDTH = 1200;
private final static int HEIGHT = 800;
private DisplayCanvas canvas;
private ControlContainer controlContainer;
public DisplayFrame() {
//simple inheritance.
super(title);
setSize(new Dimension(WIDTH, HEIGHT));
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
addComponents(this.getContentPane());
}
public void addComponents(Container container){
canvas = DisplayCanvas.getInstance(container);
canvas.setAlignmentX(Component.LEFT_ALIGNMENT);
container.add(canvas);
controlContainer = ControlContainer.getInstance(container);
controlContainer.setAlignmentX(Component.RIGHT_ALIGNMENT);
container.add(controlContainer);
}
}
70%宽度的面板
public class DisplayCanvas extends JPanel{
private final double WIDTH_PERCENT = 70;
private static DisplayCanvas instance;
private DisplayCanvas(Container parent) {
this.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT,
parent.getWidth()), parent.getHeight()));
this.setBackground(Color.WHITE);
this.setVisible(true);
}
//implement the singleton
public static DisplayCanvas getInstance(Container parent) {
if(instance != null){
return instance;
}
instance = new DisplayCanvas(parent);
return instance;
}
}
面板宽度为 30%:
public class ControlContainer extends JPanel{
private final double WIDTH_PERCENT = 30;
private static ControlContainer instance;
private ControlPanel controlPanel;
private ControlContainer(Container parent) {
this.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT,
parent.getWidth()), parent.getHeight()));
this.setBackground(Color.GRAY);
this.setLayout(new BorderLayout(0,0));
this.setVisible(true);
addControlElements(this);
}
//implement Singelton
public static ControlContainer getInstance(Container parent){
if(instance != null){
return instance;
}
instance = new ControlContainer(parent);
return instance;
}
public void addControlElements(Container parent){
controlPanel = ControlPanel.getInstance(parent);
controlPanel.setAlignmentX(LEFT_ALIGNMENT);
System.out.println("ControlContainer: " + parent.getWidth()
+ " " + parent.getHeight()+ " vis: " + parent.isVisible());
System.out.println("ControlPanel: " + controlPanel.getWidth()
+ " " + controlPanel.getHeight() + " vis: " + controlPanel.isVisible());
parent.add(controlPanel, BorderLayout.CENTER);
}
}
现在,此面板应嵌套在 ControlContainer
内,占其宽度的 50%。
public class ControlPanel extends JPanel{
private final double WIDTH_PERCENT = 50;
private static ControlPanel instance;
private ControlPanel(Container parent) {
super.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT,
parent.getWidth()), parent.getHeight()));
super.setBackground(Color.GREEN);
super.setVisible(true);
}
//implement singelton measures
public static ControlPanel getInstance(Container parent){
if(instance != null){
return instance;
}
instance = new ControlPanel(parent);
return instance;
}
}
这是 addControlElements
方法的输出:
ControlContainer: 358 772 vis: true
ControlPanel: 179 772 vis: true
这只是用来测试值是否按预期设置,如您所见 ControlPanel
width is 179
然而,这是预期的,当呈现时它会填充整个 ControlContainer
.
希望你明白我的意思,这不是最容易解释的。
首先查看 Laying Out Components Within a Container to understand how components are laied out in Swing. Take a look at How to Use GridBagLayout 以了解如何实现您正在寻找的结果
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
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.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BasePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BasePane extends JPanel {
public BasePane() {
TestPane top = new TestPane();
TestPane bottom = new TestPane();
// top.setBorder(new LineBorder(Color.RED));
// bottom.setBorder(new LineBorder(Color.BLUE));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 0.3;
add(top, gbc);
gbc.gridy++;
gbc.weighty = 0.7;
add(bottom, gbc);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class TestPane extends JPanel {
public TestPane() {
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Dimension mySize = getSize();
Dimension parentSize = getParent().getSize();
String widthPer = NumberFormat.getPercentInstance().format((float) mySize.width / (float) parentSize.width);
String heightPer = NumberFormat.getPercentInstance().format((float) mySize.height / (float) parentSize.height);
String[] text = new String[]{
"Me = " + mySize.width + "x" + mySize.height,
"Parent = " + parentSize.height + "x" + parentSize.height,
"Perctange = " + widthPer + "x" + heightPer
};
FontMetrics fm = g2d.getFontMetrics();
int y = (getHeight() - (fm.getHeight() * text.length)) / 2;
for (String value : text) {
int x = (getWidth() - fm.stringWidth(value)) / 2;
g2d.drawString(value, x, y + fm.getAscent());
y += fm.getHeight();
}
g2d.dispose();
}
}
}
我有一个 JFrame
,其中包含 2 个 JPanels
,其中一个是 JFrame
的 70%,另一个是剩余的 30%。 JPanel
是宽度的 30%,其中有一个嵌套的 JPanel。然而,这个嵌套的 JPanel
应该是其父级 JPanel 宽度的 50%,但是当它显示时,它占据了父级 JPanel
.
父级 JPanel
属于 width 358
和 height 772
,嵌套的 JPanel
具有以下值:width 179
和 height 772
我已将这些组件的颜色设置为绿色和灰色,因此我可以轻松查看它们是否正确呈现。当我 运行 我的应用程序时,嵌套的 JPanel
实际上被呈现为好像它是 parent
的整个宽度(整个区域呈现绿色)。
这是当前的代码。
public class DisplayFrame extends JFrame{
private final static int WIDTH = 1200;
private final static int HEIGHT = 800;
private DisplayCanvas canvas;
private ControlContainer controlContainer;
public DisplayFrame() {
//simple inheritance.
super(title);
setSize(new Dimension(WIDTH, HEIGHT));
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
addComponents(this.getContentPane());
}
public void addComponents(Container container){
canvas = DisplayCanvas.getInstance(container);
canvas.setAlignmentX(Component.LEFT_ALIGNMENT);
container.add(canvas);
controlContainer = ControlContainer.getInstance(container);
controlContainer.setAlignmentX(Component.RIGHT_ALIGNMENT);
container.add(controlContainer);
}
}
70%宽度的面板
public class DisplayCanvas extends JPanel{
private final double WIDTH_PERCENT = 70;
private static DisplayCanvas instance;
private DisplayCanvas(Container parent) {
this.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT,
parent.getWidth()), parent.getHeight()));
this.setBackground(Color.WHITE);
this.setVisible(true);
}
//implement the singleton
public static DisplayCanvas getInstance(Container parent) {
if(instance != null){
return instance;
}
instance = new DisplayCanvas(parent);
return instance;
}
}
面板宽度为 30%:
public class ControlContainer extends JPanel{
private final double WIDTH_PERCENT = 30;
private static ControlContainer instance;
private ControlPanel controlPanel;
private ControlContainer(Container parent) {
this.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT,
parent.getWidth()), parent.getHeight()));
this.setBackground(Color.GRAY);
this.setLayout(new BorderLayout(0,0));
this.setVisible(true);
addControlElements(this);
}
//implement Singelton
public static ControlContainer getInstance(Container parent){
if(instance != null){
return instance;
}
instance = new ControlContainer(parent);
return instance;
}
public void addControlElements(Container parent){
controlPanel = ControlPanel.getInstance(parent);
controlPanel.setAlignmentX(LEFT_ALIGNMENT);
System.out.println("ControlContainer: " + parent.getWidth()
+ " " + parent.getHeight()+ " vis: " + parent.isVisible());
System.out.println("ControlPanel: " + controlPanel.getWidth()
+ " " + controlPanel.getHeight() + " vis: " + controlPanel.isVisible());
parent.add(controlPanel, BorderLayout.CENTER);
}
}
现在,此面板应嵌套在 ControlContainer
内,占其宽度的 50%。
public class ControlPanel extends JPanel{
private final double WIDTH_PERCENT = 50;
private static ControlPanel instance;
private ControlPanel(Container parent) {
super.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT,
parent.getWidth()), parent.getHeight()));
super.setBackground(Color.GREEN);
super.setVisible(true);
}
//implement singelton measures
public static ControlPanel getInstance(Container parent){
if(instance != null){
return instance;
}
instance = new ControlPanel(parent);
return instance;
}
}
这是 addControlElements
方法的输出:
ControlContainer: 358 772 vis: true
ControlPanel: 179 772 vis: true
这只是用来测试值是否按预期设置,如您所见 ControlPanel
width is 179
然而,这是预期的,当呈现时它会填充整个 ControlContainer
.
希望你明白我的意思,这不是最容易解释的。
首先查看 Laying Out Components Within a Container to understand how components are laied out in Swing. Take a look at How to Use GridBagLayout 以了解如何实现您正在寻找的结果
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
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.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BasePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BasePane extends JPanel {
public BasePane() {
TestPane top = new TestPane();
TestPane bottom = new TestPane();
// top.setBorder(new LineBorder(Color.RED));
// bottom.setBorder(new LineBorder(Color.BLUE));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 0.3;
add(top, gbc);
gbc.gridy++;
gbc.weighty = 0.7;
add(bottom, gbc);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class TestPane extends JPanel {
public TestPane() {
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Dimension mySize = getSize();
Dimension parentSize = getParent().getSize();
String widthPer = NumberFormat.getPercentInstance().format((float) mySize.width / (float) parentSize.width);
String heightPer = NumberFormat.getPercentInstance().format((float) mySize.height / (float) parentSize.height);
String[] text = new String[]{
"Me = " + mySize.width + "x" + mySize.height,
"Parent = " + parentSize.height + "x" + parentSize.height,
"Perctange = " + widthPer + "x" + heightPer
};
FontMetrics fm = g2d.getFontMetrics();
int y = (getHeight() - (fm.getHeight() * text.length)) / 2;
for (String value : text) {
int x = (getWidth() - fm.stringWidth(value)) / 2;
g2d.drawString(value, x, y + fm.getAscent());
y += fm.getHeight();
}
g2d.dispose();
}
}
}