gpt4 book ai didi

java - Swing:正确的布局管理器与上层布局管理器的交互?

转载 作者:行者123 更新时间:2023-12-04 06:23:07 26 4
gpt4 key购买 nike

我正在尝试自定义 LayoutManager,但我不明白在本身具有上层布局管理器的组件中使用它的微妙之处。

enter image description here

下面是一个测试程序,它使用一对 JPanel 制作两个框架。两个 JPanel 中的每一个都有一个黑色的细边框,并使用我的 WeirdGridLayout 将其子组件强制为网格中的正方形,JPanel 高度是根据宽度计算的。两个 JPanel 都在另一个 JPanel 中,带有使用 BorderLayout 的细红色边框。

在一个框架中,带有 WeirdGridLayout 的 JPanel 被安排在 EAST 和 WEST,另一个
安排北和南。

问题是,在北/南的情况下,如果我改变框架的宽度/高度,
两个带有 WeirdGridLayout 的 JPanel 大小合适,但位置不合适(它们要么有间隙,要么垂直重叠)。

enter image description here

在东/西的情况下,它最终会出错。

enter image description here

我必须做些什么才能让我的布局管理器与外部布局管理器配合得很好?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.LayoutManager2;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
*/
public class WeirdGridLayout implements LayoutManager2
{


static final private int GRIDGAP = 10;
static final private int COMPONENT_SIZE = 30;
static final private int GRIDSPACING = COMPONENT_SIZE + GRIDGAP;

final private List<Component> components
= new ArrayList<Component>();

@Override public void addLayoutComponent(Component comp, Object constraints) {
this.components.add(comp);
}
@Override public void addLayoutComponent(String name, Component comp) {
this.components.add(comp);
}
@Override public void removeLayoutComponent(Component comp) {
this.components.remove(comp);
}

@Override public float getLayoutAlignmentX(Container target) {
return Component.LEFT_ALIGNMENT;
}
@Override public float getLayoutAlignmentY(Container target) {
return Component.TOP_ALIGNMENT;
}

@Override public void invalidateLayout(Container target) {}
@Override public Dimension maximumLayoutSize(Container target) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
@Override public Dimension minimumLayoutSize(Container parent) {
return new Dimension(0,0);
}

@Override public void layoutContainer(Container parent) {
int x = GRIDGAP;
int y = GRIDGAP;

Dimension d = preferredLayoutSize(parent);
parent.setSize(d);
for (Component component : this.components)
{
component.setBounds(x, y, COMPONENT_SIZE, COMPONENT_SIZE);

x += GRIDSPACING;
if (x >= d.getWidth())
{
x = GRIDGAP;
y += GRIDSPACING;
}
}
}

@Override public Dimension preferredLayoutSize(Container parent) {
// how many blocks wide can we fit?
int n = this.components.size();
int nblockwidth = (parent.getWidth() - GRIDGAP) / GRIDSPACING;
int nblockheight = (nblockwidth == 0) ? 0
: ((n-1)/nblockwidth) + 1;
return new Dimension(
nblockwidth*GRIDSPACING+GRIDGAP,
nblockheight*GRIDSPACING+GRIDGAP);
}

/* ---- test methods ---- */

static public class ColorPanel extends JPanel {
final private Color color;
final private String label;
public ColorPanel(String label, Color color) {
this.label = label;
this.color = color;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(this.color);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.WHITE);
FontMetrics fm = g.getFontMetrics();
int w = fm.stringWidth(this.label);
g.drawString(this.label, (getWidth()-w)/2,
(getHeight()+fm.getAscent())/2);
}
}

public static void main(String[] args) {
showFrame(true);
showFrame(false);
}
private static void showFrame(boolean eastWest) {
JFrame frame = new JFrame("WeirdGridLayout test: eastWest="+eastWest);
JPanel framePanel = new JPanel(new BorderLayout());
framePanel.setPreferredSize(new Dimension(400,200));

JPanel panel[] = new JPanel[2];
for (int i = 0; i < 2; ++i)
{
panel[i] = new JPanel(new WeirdGridLayout());
panel[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
final Random r = new Random();
for (int j = 0; j < 24; ++j)
{
Color c = new Color(
r.nextFloat(),
r.nextFloat(),
r.nextFloat());
JPanel subpanel = new ColorPanel(Integer.toString(j), c);
panel[i].add(subpanel);
}
}

framePanel.add(new JButton("test"), BorderLayout.NORTH);
JPanel bottomPanel = new JPanel(new BorderLayout());
framePanel.add(bottomPanel, BorderLayout.SOUTH);

if (eastWest)
{
bottomPanel.add(panel[0], BorderLayout.WEST);
bottomPanel.add(panel[1], BorderLayout.EAST);
}
else
{
bottomPanel.add(panel[0], BorderLayout.NORTH);
bottomPanel.add(panel[1], BorderLayout.SOUTH);
}
bottomPanel.setBorder(BorderFactory.createLineBorder(Color.RED));


frame.setContentPane(framePanel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

最佳答案

回答这个问题:无 :-) LayoutManager 不是为与其他 LayoutManager 交互而设计的,它们单独作用于它们负责的目标。

  • LayoutManager 负责容器的子项的大小和定位,而不是容器本身。因此, WeirdLayoutManager 在将父级的大小设置为其首选项时行为不当。
  • preferredLayoutSize 必须始终返回一些合理的值:将其视为一种分离的东西,例如“亲爱的容器,鉴于您拥有世界上所有的空间,您想要拥有多大的空间”或者相反:不要依赖关于父尺寸来回答这个问题。这就像一只狗试图咬自己的尾部。对于类似网格的结构,这可能需要某种 prefColumns/-Rows 属性
  • layoutContainer 必须在容器的当前边界内调整直接子项的大小和位置,不要接触容器本身。它可以以它喜欢的任何方式进行,根据需要在尽可能多的行/列
  • 关于java - Swing:正确的布局管理器与上层布局管理器的交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6334920/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com