在JPanel中的不透明组件上绘制自定义内容

时间:2012-06-15 09:18:22

标签: swing jpanel paintcomponent

我有一个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);
    }
}

1 个答案:

答案 0 :(得分: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. Simple one.
  2. A more complex one.