如何让 JComponents 在缩小后始终居中?
How to keep JComponents always centered even after being shrunk?
Objective
我正在制作一个带有三个 JComponent 的 JPanel:一个广泛的自定义 JComponent 和两个自定义的 AbstractButtons,后者又从 JComponent 扩展而来。
我想用 2 行和 2 列来组织我的 JPanel,宽 JComponent 跨越两列。 AbstractButtons 周围有很多 space。这是我绘制的我想要实现的图表:
问题
基本上,当用户单击其中一个 AbstractButton 时,它会缩小。我希望它们即使在被点击时也始终完美地居中于它们的单元格中。但是,当我使用 GridBagLayout 时,我的代码并非如此;按钮变得偏离中心,并且它们的左上角保持在原来的位置。
代码
这就是下面的代码将显示的内容(红色按钮现在会在按下后缩小):
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(); }
}
也许您可以尝试更改按钮的边界,具体取决于它是缩小尺寸还是完整尺寸?仅当您的主 window 不可调整大小时才如此。
Component.setBounds(int x, int y, int width, int height)
您的示例代码与您绘制的图片不匹配,并且没有使用 GridBagLayout。 SSCCE
应该用您测试的代码复制问题。
问题出在自定义对象的实现上。您真正需要的是 class 中的自定义 属性,它反映了组件的当前状态。类似于:
public void setLargeSize(Boolean largeSize)
{
this.largeSize = largeSize;
revalidate();
repaint();
}
然后需要根据这个变量修改getPreferredSize()方法return组件的大小:
@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。
Objective
我正在制作一个带有三个 JComponent 的 JPanel:一个广泛的自定义 JComponent 和两个自定义的 AbstractButtons,后者又从 JComponent 扩展而来。
我想用 2 行和 2 列来组织我的 JPanel,宽 JComponent 跨越两列。 AbstractButtons 周围有很多 space。这是我绘制的我想要实现的图表:
问题
基本上,当用户单击其中一个 AbstractButton 时,它会缩小。我希望它们即使在被点击时也始终完美地居中于它们的单元格中。但是,当我使用 GridBagLayout 时,我的代码并非如此;按钮变得偏离中心,并且它们的左上角保持在原来的位置。
代码
这就是下面的代码将显示的内容(红色按钮现在会在按下后缩小):
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(); }
}
也许您可以尝试更改按钮的边界,具体取决于它是缩小尺寸还是完整尺寸?仅当您的主 window 不可调整大小时才如此。
Component.setBounds(int x, int y, int width, int height)
您的示例代码与您绘制的图片不匹配,并且没有使用 GridBagLayout。 SSCCE
应该用您测试的代码复制问题。
问题出在自定义对象的实现上。您真正需要的是 class 中的自定义 属性,它反映了组件的当前状态。类似于:
public void setLargeSize(Boolean largeSize)
{
this.largeSize = largeSize;
revalidate();
repaint();
}
然后需要根据这个变量修改getPreferredSize()方法return组件的大小:
@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。