3

我有一个 JPanel 填充了几个不透明的自定义组件。现在我想通过覆盖 paintComponent() 方法在这些组件之上绘制一些东西。我的问题是涂漆的东西被放置在嵌入式组件的后面,并且由于它们是不透明的,因此被它们覆盖。

有什么办法可以让绘画出现在组件之上?

这是我正在尝试做的一个简短示例:

public class DrawOnTop {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new JFrame("Draw on top");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new MyPanel());
                f.pack();
                f.setVisible(true);
            }
        });
    }
}

class MyPanel extends JPanel {

    public MyPanel() {
        setLayout(new BorderLayout(3, 3));
        add(new JButton("Button 1"), BorderLayout.NORTH);
        add(new JButton("Button 2"), BorderLayout.CENTER);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.red);
        g.drawLine(0, 0, getVisibleRect().width, getVisibleRect().height);
    }
}
4

1 回答 1

2

你的想法是正确的。唯一的问题是您应该paintChildren()像下面的代码一样覆盖该方法。这是因为该paintComponent()方法首先被调用,并且对组件本身(MyPanel)进行背景等绘制,然后被调用paintBorders(),最后paintChildren()调用它绘制调用它的组件内部的所有内容。

public class DrawOnTop {

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

            @Override
            public void run() {
                JFrame f = new JFrame("Draw on top");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new MyPanel());
                f.pack();
                f.setVisible(true);
            }
        });
    }
}

class MyPanel extends JPanel {

    public MyPanel() {
        setLayout(new BorderLayout(3, 3));
        JButton b1 = new JButton("Button 1");
        MouseListener ml = new MouseAdapter() {

            @Override
            public void mouseExited(MouseEvent e) {
                super.mouseExited(e);
                MyPanel.this.repaint();
            }
        };
        b1.addMouseListener(ml);
        JButton b2 = new JButton("Button 2");
        b2.addMouseListener(ml);
        add(b1, BorderLayout.NORTH);
        add(b2, BorderLayout.CENTER);
    }

    @Override
    protected void paintChildren(Graphics g) {
        super.paintChildren(g);
        g.setColor(Color.red);
        g.drawLine(0, 0, getVisibleRect().width, getVisibleRect().height);
    }
}

重要的是要注意,在代码示例中,我还添加了一个MouseListener以在鼠标退出按钮时重新绘制面板,否则一旦鼠标进入其中一个按钮,按钮将始终停留在该线上。

但是,如果您想拥有始终位于组件顶部的自定义绘画,那么我建议您使用玻璃窗格。此处提供了玻璃窗格使用的示例:

  1. 简单的一个。
  2. 一个更复杂的。
于 2012-06-15T11:20:50.643 回答