将自定义 JButton 添加到 JFrame 会更改背景颜色
Adding custom JButton to JFrame changes background color
我创建了一个简单的 GUI,因为我想创建一个圆形的 JButton 而不是普通按钮。因此我创建了一个 class 来扩展 JButton 并覆盖一些方法来实现绘画。
但是,一旦我执行代码(使用 Java 13),就会创建带有难看的黄色的框架,之后包含按钮并且整个 JFrame 背景颜色发生变化。为什么会这样,我该如何预防?我只希望创建按钮,但不需要更改颜色或类似内容。
public class RoundedButton extends JButton {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setSize(800, 800);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setSize(new Dimension(200, 200));
JButton button = new RoundedButton("Text", 40, 2F, Color.BLACK);
button.setBackground(new Color(116, 10, 10));
button.setForeground(Color.WHITE);
button.setSize(new Dimension(200, 120));
button.setPreferredSize(new Dimension(200, 120));
button.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
button.setBackground(button.getBackground().brighter().brighter());
}
@Override
public void mouseExited(MouseEvent e) {
button.setBackground(button.getBackground().darker().darker());
}
});
panel.add(button, BorderLayout.CENTER);
frame.add(panel, BorderLayout.NORTH);
frame.setBackground(Color.YELLOW);
//frame.pack();
frame.setVisible(true);
}
private int arcRadius;
private float borderSize;
private Color borderColor;
public RoundedButton(String label, int arcRadius, float borderSize, Color borderColor) {
super(label);
this.setContentAreaFilled(false);
this.arcRadius = arcRadius;
this.borderSize = borderSize;
this.borderColor = borderColor;
}
@Override
public void paint(Graphics g) {
if(g instanceof Graphics2D) {
((Graphics2D) g).setStroke(new BasicStroke(borderSize));
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
//Draw background / fill button
g.setColor(this.getBackground());
g.fillRoundRect(getX(), getY(), this.getWidth(), (int)(this.getHeight()-borderSize), arcRadius, arcRadius);
//Draw border
g.setColor(borderColor);
g.drawRoundRect(getX(), getY(), this.getWidth(), (int)(this.getHeight()-borderSize), arcRadius, arcRadius);
//Draw font
if (this.getFont() != null && this.getText() != null) {
FontMetrics fm = getFontMetrics(getFont());
g.setColor(this.getForeground());
g.drawString(this.getText(), ((this.getWidth() / 2) - (fm.stringWidth(this.getText()) / 2)),
((this.getHeight() / 2) + fm.getMaxDescent()));
}
}
@Override
public boolean contains(int x, int y) {
return new RoundRectangle2D.Double(getX(), getY(), this.getWidth(), (int)(this.getHeight()-borderSize), arcRadius, arcRadius).contains(x, y);
}
@Override
public void updateUI() {
super.updateUI();
this.setContentAreaFilled(false);
this.setFocusPainted(false);
}
}
如果我将它添加到框架中,颜色的背景就会改变。这是为什么?
提供给组件 paint 方法的图形对象应该已经转换为组件的位置。所以你所有的绘画都应该在(0,0)和(宽度,高度)内完成。
我原以为剪辑也会设置到组件的边界,以防止您在组件之外进行绘画。但也许您的按钮覆盖了框架的很大一部分区域,或者由于某种原因剪辑为空。
具体来说:g.drawRoundRect(0, 0, ...
编辑回答问题编辑:当您只在 NORTH 添加一些东西,而 CENTER 没有任何内容时,BorderLayout 有点不确定。此外,面板和按钮的首选尺寸在放置在边框布局的中心时会被忽略。
我创建了一个简单的 GUI,因为我想创建一个圆形的 JButton 而不是普通按钮。因此我创建了一个 class 来扩展 JButton 并覆盖一些方法来实现绘画。
但是,一旦我执行代码(使用 Java 13),就会创建带有难看的黄色的框架,之后包含按钮并且整个 JFrame 背景颜色发生变化。为什么会这样,我该如何预防?我只希望创建按钮,但不需要更改颜色或类似内容。
public class RoundedButton extends JButton {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setSize(800, 800);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setSize(new Dimension(200, 200));
JButton button = new RoundedButton("Text", 40, 2F, Color.BLACK);
button.setBackground(new Color(116, 10, 10));
button.setForeground(Color.WHITE);
button.setSize(new Dimension(200, 120));
button.setPreferredSize(new Dimension(200, 120));
button.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
button.setBackground(button.getBackground().brighter().brighter());
}
@Override
public void mouseExited(MouseEvent e) {
button.setBackground(button.getBackground().darker().darker());
}
});
panel.add(button, BorderLayout.CENTER);
frame.add(panel, BorderLayout.NORTH);
frame.setBackground(Color.YELLOW);
//frame.pack();
frame.setVisible(true);
}
private int arcRadius;
private float borderSize;
private Color borderColor;
public RoundedButton(String label, int arcRadius, float borderSize, Color borderColor) {
super(label);
this.setContentAreaFilled(false);
this.arcRadius = arcRadius;
this.borderSize = borderSize;
this.borderColor = borderColor;
}
@Override
public void paint(Graphics g) {
if(g instanceof Graphics2D) {
((Graphics2D) g).setStroke(new BasicStroke(borderSize));
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
//Draw background / fill button
g.setColor(this.getBackground());
g.fillRoundRect(getX(), getY(), this.getWidth(), (int)(this.getHeight()-borderSize), arcRadius, arcRadius);
//Draw border
g.setColor(borderColor);
g.drawRoundRect(getX(), getY(), this.getWidth(), (int)(this.getHeight()-borderSize), arcRadius, arcRadius);
//Draw font
if (this.getFont() != null && this.getText() != null) {
FontMetrics fm = getFontMetrics(getFont());
g.setColor(this.getForeground());
g.drawString(this.getText(), ((this.getWidth() / 2) - (fm.stringWidth(this.getText()) / 2)),
((this.getHeight() / 2) + fm.getMaxDescent()));
}
}
@Override
public boolean contains(int x, int y) {
return new RoundRectangle2D.Double(getX(), getY(), this.getWidth(), (int)(this.getHeight()-borderSize), arcRadius, arcRadius).contains(x, y);
}
@Override
public void updateUI() {
super.updateUI();
this.setContentAreaFilled(false);
this.setFocusPainted(false);
}
}
如果我将它添加到框架中,颜色的背景就会改变。这是为什么?
提供给组件 paint 方法的图形对象应该已经转换为组件的位置。所以你所有的绘画都应该在(0,0)和(宽度,高度)内完成。
我原以为剪辑也会设置到组件的边界,以防止您在组件之外进行绘画。但也许您的按钮覆盖了框架的很大一部分区域,或者由于某种原因剪辑为空。
具体来说:g.drawRoundRect(0, 0, ...
编辑回答问题编辑:当您只在 NORTH 添加一些东西,而 CENTER 没有任何内容时,BorderLayout 有点不确定。此外,面板和按钮的首选尺寸在放置在边框布局的中心时会被忽略。