首页 > 解决方案 > Java通过调整元素大小来调整布局

问题描述

我有个问题。

我有 JFrame 元素。在这个框架元素内有一个paintingPanel(扩展swing JPanel 类),其布局设置为FlowLayout(FlowLayout.LEFT)固定宽度和高度。在 PaintingPanel 内部有 CanvasPanel 元素(也扩展了 JPanel 类)。CanvasPanel 的布局设置为 GroupLayout (2x2)。在左上角单元格中,我有画布元素。在其他 3 个单元格中,我有画布的大小调整器。Resizer 也扩展了 JPanel 类。

调整画布大小时,我想使用(画布)调整大小调整 CanvasPanel 的大小。我还希望调整大小适合画布尺寸:

  1. 对,水平调整大小应该有 10px 的宽度和画布的高度
  2. 底部,垂直调整大小应具有画布的宽度和 10 像素的高度
  3. 右下角,(水平和垂直)调整大小应为 10 像素 x 10 像素

我也不想调整 PaintingPanel 的大小。

我怎样才能达到预期的结果?

这是 CanvasPanel 中布局的代码:

private void setDefaultLayout()
{
    GroupLayout layout = new GroupLayout(this);
    setLayout(layout);
    layout.setAutoCreateGaps(true);
    layout.setAutoCreateContainerGaps(true);
    layout.setHorizontalGroup(
        layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                .addComponent(canvas)
                .addComponent(resizers.get("middle-right")))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
                .addComponent(resizers.get("bottom-middle"))
                .addComponent(resizers.get("bottom-right")))
    );
    layout.setVerticalGroup(
        layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(canvas)
                .addComponent(resizers.get("bottom-middle")))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(resizers.get("middle-right"))
                .addComponent(resizers.get("bottom-right")))
    );
}

这是调整 CanvasPanel 大小的当前方法

public void resizeCanvas(int width, int height)
{
    this.width = width + 40;
    this.height = height + 40;
    setSize(width, height);
    setPreferredSize(new Dimension(this.width, this.height));
    setMinimumSize(new Dimension(this.width, this.height));
    setMaximumSize(new Dimension(this.width, this.height));
    canvas.setSize(width, height);
}

有人可以帮忙吗?

标签: javaswinglayout-managergrouplayout

解决方案


我已经找到了解决方案,并将其发布在下面。我已经通过使用setLayout(null)andsetBounds()方法完成了它。代码尚未重构。

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;

public class Launcher
{
    private int offsetX = 10, offsetY = 10;
    private HashMap<String, Res> resizers = new HashMap<String, Res>();
    private JFrame frame;
    private JScrollPane pane;
    private Canvas canvas;

public static void main(String[] args)
{
    Launcher l = new Launcher();
    l.create();
}

public void create()
{
    initFrame();

    int canvasWidth = 200;
    int canvasHeight = 200;

    canvas = new Canvas();
    canvas.setSize(canvasWidth, canvasHeight);
    canvas.setPreferredSize(new Dimension(canvasWidth, canvasHeight));
    canvas.setMinimumSize(new Dimension(canvasWidth, canvasHeight));
    canvas.setMaximumSize(new Dimension(canvasWidth, canvasHeight));
    canvas.setBackground(Color.WHITE);
    canvas.setVisible(true);
    canvas.setBounds(offsetX, offsetY, canvasWidth, canvasHeight);
    canvas.repaint();

    resizers.put("horizontal", new Res(
            this,
            2*offsetX + canvasWidth,
            offsetY,
            Res.DEFAULT_WIDTH,
            canvasHeight
    ));
    resizers.put("vertical", new Res(
            this,
            offsetX,
            2*offsetY + canvasHeight,
            canvasWidth,
            Res.DEFAULT_WIDTH
    ));
    resizers.put("both", new Res(
            this,
            2*offsetX + canvasWidth,
            2*offsetY + canvasHeight,
            Res.DEFAULT_WIDTH,
            Res.DEFAULT_WIDTH
    ));

    pane = new JScrollPane();
    pane.setLayout(null);
    pane.setBackground(Color.LIGHT_GRAY);
    pane.add(canvas);
    pane.add(resizers.get("horizontal"));
    pane.add(resizers.get("vertical"));
    pane.add(resizers.get("both"));

    frame.add(pane, BorderLayout.CENTER);
    frame.pack();
}

public void resizeCanvasBy(int x, int y)
{
    int width = canvas.getWidth() + x;
    int height = canvas.getHeight() + y;
    canvas.setSize(width, height);
    canvas.setPreferredSize(new Dimension(width, height));
    canvas.setMinimumSize(new Dimension(width, height));
    canvas.setMaximumSize(new Dimension(width, height));

    resizers.get("horizontal").setBounds(
            2*offsetX + width, offsetY, Res.DEFAULT_WIDTH, height);
    resizers.get("vertical").setBounds(
            offsetX, 2*offsetY + height, width, Res.DEFAULT_WIDTH);
    resizers.get("both").setBounds(
            2*offsetX + width, 2*offsetY + height, Res.DEFAULT_WIDTH, Res.DEFAULT_WIDTH);
}

public void initFrame()
{
    frame = new JFrame();
    frame.setPreferredSize(new Dimension(400, 400));
    frame.setMinimumSize(new Dimension(400, 400));
    frame.setMaximumSize(new Dimension(400, 400));
    frame.setResizable(true);
    frame.setUndecorated(false);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public class Res extends JPanel implements MouseListener
{
    public static final int DEFAULT_WIDTH = 10;
    private Launcher launcher;
    private int pressedX, pressedY;

    public Res(Launcher launcher, int x, int y, int width, int height)
    {
        this.launcher = launcher;
        setPreferredSize(new Dimension(width, height));
        setMinimumSize(new Dimension(width, height));
        setMaximumSize(new Dimension(width, height));
        setVisible(true);
        addMouseListener(this);
        setBounds(x, y, width, height);
        repaint();
    }

    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e)
    {
        pressedX = e.getX();
        pressedY = e.getY();
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
        int deltaX = e.getX() - pressedX;
        int deltaY = e.getY() - pressedY;
        launcher.resizeCanvasBy(deltaX, deltaY);
    }

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}
}

}

推荐阅读