Java Swing:如何在JPanel的组件下方绘制?

4
我有一个包含按钮的JPanel。按钮的位置不重要。以下是paint(Graphics g)代码:
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        /* 绘制代码 */
    }
如果我想用黑色矩形填充整个面板,同时在面板中有按钮,则填充的矩形会将所有内容覆盖。因此,整个面板都是黑色,而不是在按钮周围有黑色。 是否有任何方法可以修改面板或绘画过程,使组件在自定义绘画的上方绘制? 我已经试图在绘画的末尾放置super.paint(g),如下所示:
    @Override
    public void paint(Graphics g) {
        /* 绘制代码 */
        super.paint(g);
    }
我认为这会首先进行自定义绘画,然后简单地将组件放在其上。但是,如果这样做,自定义绘画就会完全消失,只有按钮显示出来。也就是说,只有按钮和白色(默认)背景,而不是黑色矩形。
有什么想法吗?
谢谢! 编辑: 我想澄清,黑色矩形只是一个例子。我知道我可以简单地设置背景颜色,但我最终希望能够进行任何自定义绘画。

那么,你想要实现什么?一个被黑色覆盖而看不见的按钮吗?如果是这样,目的是什么? - Hovercraft Full Of Eels
我正在尝试制作一个具有自定义绘画但也使用基本Swing组件的菜单。我意识到我可以使用setBackground(..),但它不允许我进行自定义绘画。而且,据我所知,如果菜单是纯色的且无法交互,那么它们并不是很有趣。 - Martin Tuskevicius
2个回答

9

我认为你想重写paintComponent()而不是paint()

paint()通常不会进行任何绘制,而是委托给paintComponent()paintBorder()paintChildren()

有关更多信息,请参见javax.swing.JComponent.paint()

示例:

  @Override
  public void paintComponent(Graphics g) {
    /* your draw code here */
  }

您可以调用 super.paintComponent(g) 以通常的方式绘制组件,但是可以省略。

1
+1 作为参考,"Swing 程序应该重写 paintComponent() 而不是重写 paint()。"——在 AWT 和 Swing 中绘图:绘图方法 - trashgod
是的!这正是我所需要的。非常感谢! - Martin Tuskevicius
1
你能发一个例子展示一下你是怎么做的吗?我也遇到了同样的问题,但是我无法让它正常工作。 - Erich

6
您可以将面板的背景设置为黑色并调整UI委托的颜色。您可以使用setBorderPainted(false),并根据需要突出显示按钮。这是一个SSCCE,可用于根据需要更新您的问题。这个AnimationTest展示了如何通过paintComponent()更新组件“后面”的面板。
补充说明:将super.paintComponent(g)放在第一位将确保组件似乎覆盖在(可能会改变的)背景之上。因为组件的背景颜色受其UI委托的控制,所以您可以执行以下任何操作:
- 使用UIManager更改相应的属性,如下所示。 - 使用自定义JButton覆盖paintComponent(),如此处所示。 - 使用自定义UI委托,如此处所示。
SSCCE:
import component.Laf;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

/** @see https://dev59.com/NWXWa4cB1Zd3GeqPJRWn#11075785 */
public class ButtonPanel extends JPanel {

    public ButtonPanel() {
        this.setBackground(Color.black);
        final JButton b = new JButton(new AbstractAction("Button"){

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Clicked");
            }
        });
        // b.setBorderPainted(false);
        this.add(b);
    }

    private void display() {
        UIManager.put("Button.foreground", Color.white);
        UIManager.put("Button.background", Color.black);
        JFrame f = new JFrame("ButtonPanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ButtonPanel().display();
            }
        });
    }
}

但是如果我想做更多的事情而不仅仅是设置背景颜色,该怎么办呢?我想要进行自定义绘画,黑色矩形只是一个例子。 - Martin Tuskevicius
我已经链接了一个更复杂的示例。 - trashgod
现在看它。感谢它。 - Martin Tuskevicius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接