如何使JComponents在收缩后始终居中?

时间:2015-04-26 06:39:08

标签: java swing layout

目的

我正在创建一个包含三个JComponents的JPanel:一个宽的自定义JComponent,以及两个自定义的AbstractButtons,它们也从JComponent扩展。

我想组织我的JPanel有2行和2列,宽JComponent跨越两列。 AbstractButtons周围有足够的空间。这是我绘制的我想要实现的图表:

enter image description here

问题

基本上,当用户点击其中一个AbstractButtons时,它会缩小。即使点击它,我也希望它们能够完全集中在细胞中。但是当我使用GridBagLayout时,我的代码中的情况并非如此;按钮变得偏离中心,它们的左上角保持在以前的任何位置。

代码

以下代码会显示(红色按钮现在会在按下后缩小):

enter image description here

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.*;

public class Example
{
    public static void main(String[] args)
    {
        // Instantiate components needed.
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        frame.add(panel);
        Button b1 = new Button();
        Button b2 = new Button();
        WideComponent w = new WideComponent();

        // give margins to each component
        EmptyBorder padding = new EmptyBorder(20, 20, 20, 20);
        b1.setBorder(padding);
        b2.setBorder(padding);
        w.setBorder(padding);

        // Add stuff to panel
        panel.add(b1);
        panel.add(b2);
        panel.add(w);

        // Add panel to frame, show frame
        frame.add(panel);
        frame.setVisible(true);
        frame.pack();
    }
}

class Button extends AbstractButton implements MouseListener
{   
    final int WIDTH = 175;
    final int HEIGHT = 75; 
    boolean mousePressed;

    public Button() 
    {
        addMouseListener(this);
    }

    // draw method
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.RED);
        if (!mousePressed)
            g.fillRect(0, 0, WIDTH, HEIGHT);
        else
        {
            g.fillRect(0, 0, WIDTH - 30, HEIGHT - 30);
            g.setColor(Color.YELLOW);
        }
    }

    // MouseListener interface implementation
    public void mousePressed(MouseEvent me) { mousePressed = true; repaint(); }
    public void mouseReleased(MouseEvent me) { mousePressed = false; repaint(); }
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}

    // JComponent sizing methods
    public Dimension getPreferredSize()
    {
        return new Dimension(WIDTH, HEIGHT);
    }
    public Dimension getMaximumSize() { return getPreferredSize(); }
    public Dimension getMinimumSize() { return getPreferredSize(); }    



}

class WideComponent extends JComponent
{
    final int WIDTH = 500;
    final int HEIGHT = 150; 

    // drawing method
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, WIDTH, HEIGHT);
    }

    // JComponent sizing methods
    public Dimension getPreferredSize()
    {
        return new Dimension(WIDTH, HEIGHT);
    }
    public Dimension getMaximumSize() { return getPreferredSize(); }
    public Dimension getMinimumSize() { return getPreferredSize(); }    
}

2 个答案:

答案 0 :(得分:2)

您的示例代码与您绘制的图片不匹配,并且它不使用GridBagLayout。 SSCCE应该使用您测试的代码复制问题。

问题是您的自定义对象的实现。您真正需要的是类中的自定义属性,它反映了组件的当前状态。类似的东西:

public void setLargeSize(Boolean largeSize)
{
    this.largeSize = largeSize;
    revalidate();
    repaint();
}

然后你需要修改getPreferredSize()方法以根据这个变量返回组件的大小:

@Override
public Dimension getPreferredSize()
{
    if (largeSize)
        return new Dimension(WIDTH, HEIGHT);
    else
        return new Dimension(WIDTH - 30, HEIGHT - 30);
}

现在,布局管理器可以根据组件的当前状态完成其工作。

您还可以更改您的绘画代码。绘图代码不需要检查按下状态,因为布局管理器已经考虑了这一点。实际上,我不会'认为你甚至需要覆盖paintComponent()。只需设置按钮的一些属性:

setBorderPainted( false );
setContentAreaPainted( false );
setFocusPainted( false );

然后,您可以在setLargeSize(...)方法中设置背景颜色。

最后,MouseListener将使用适当的参数调用setLargeSize(...)方法。

所以现在您需要做的就是确保正确设置约束,以便组件在其单元格中居中。您可能需要设置组件的对齐x / y。

答案 1 :(得分:-2)

也许您可以尝试更改按钮的界限,具体取决于它是缩小的尺寸还是全尺寸?只有当您的主窗口不可调整大小时才会这样。

Component.setBounds(int x,int y,int width,int height)