2012-06-15 19 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