2012-06-15 16 views
3

我有一个JPanel填充了几个不透明的自定义组件。现在我想通过重写paintComponent()方法在这些组件上绘制一些东西。我的问题是,涂漆的东西放在嵌入式组件后面,因为它们是不透明的,所以被它们覆盖。在JPanel中的不透明组件上绘制自定义内容

有什么办法让绘画出现在组件的顶部?

这里是什么,我试图做一个简单的例子:

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); 
    } 
} 

回答

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.
+0

感谢,这正是我一直在寻找。我已经在几个地方看过,定制绘画应该总是**在paintComponent()中发生。还非常感谢您使用玻璃窗格的建议。我会看看这是否有必要。 – Moritz

+1

@Moritz是的我知道你指的是什么。我同意'paintComponent()'应该用于与其内容没有任何关系的自定义绘画。我们的情况并非如此。在我们的情况下,面板包含孩子,因为他们在父母完成后绘画,孩子总是会在其上面展示。出于这个简单的原因,为了绘制'over'子节点,我们必须在'paintChildren()'方法中调用它。 – Boro