2012-02-16 127 views
3

在開發我的應用程序對Java 5之後,我最近在6中進行了測試,發現我有一個paintComponent問題。Java paintComponent覆蓋版本5和版本6之間的區別

在jre5中發生了什麼是屏幕開始變暗,按鈕「前景」出現在調光面板的頂部(如預期的那樣)。在jre6中,按鈕完全不會出現,但您確實會得到調光。您可以通過將鼠標移動到其位置來強制該按鈕(強制翻轉以重新繪製它)。我可以稍微重新排列代碼以使按鈕出現在jre6中,但變暗的面板總是塗在按鈕的頂部。

我假設它運氣好於判斷它在jre5中可以工作但在網上找不到多少幫助。任何可以幫助你解決這個問題的方法都是非常值得讚賞的。

我產生了下面的代碼,以顯示該問題:

import java.awt.AlphaComposite; 
    import java.awt.BorderLayout; 
    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.Graphics; 
    import java.awt.Graphics2D; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import java.awt.event.MouseAdapter; 
    import java.awt.event.MouseEvent; 
    import java.awt.event.WindowAdapter; 
    import java.awt.event.WindowEvent; 

    import javax.swing.BorderFactory; 
    import javax.swing.JButton; 
    import javax.swing.JFrame; 
    import javax.swing.JLabel; 
    import javax.swing.JPanel; 
    import javax.swing.Timer; 

    @SuppressWarnings("serial") 
    public class TranslucentGlass extends JPanel 
    { 
     public static void main(String[] args) 
     { 
      // Create a frame 
      JFrame f = new JFrame(); 
      JPanel mainPanel = new JPanel(new BorderLayout()); 

      JLabel bgLabel = new JLabel(System.getProperty("java.version")); 
      mainPanel.add(bgLabel, BorderLayout.SOUTH); 

      // create a panel for the glasspane 
      final JPanel glassPane = new JPanel(); 
      glassPane.setLayout(new BorderLayout()); 
      glassPane.setVisible(false); 
      glassPane.setOpaque(false); 

      // create the containing panel for the 'foreground' button 
      final JPanel largePanel = new JPanel(new BorderLayout()); 
      largePanel.setOpaque(false); 
      largePanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 50, 20)); 
      largePanel.add(new JButton("Foreground"), BorderLayout.SOUTH); 

      // set the glass pane and mainpanel 
      f.add(mainPanel); 
      f.setGlassPane(glassPane); 
      f.setPreferredSize(new Dimension(250, 250)); 

      f.addWindowListener(new WindowAdapter() 
      { 
       @Override 
       public void windowClosing(WindowEvent e) 
       { 
        System.exit(0); 
       } 
      }); 

      // an action to show or hide the panel on mouse clicked 
      f.addMouseListener(new MouseAdapter() 
      { 
       boolean panelVisible = false; 

       @Override 
       public void mouseClicked(MouseEvent e) 
       { 
        if(!panelVisible) 
        { 
         glassPane.removeAll(); 

         TranslucentGlass dimmingPanel = new TranslucentGlass(false); 
         dimmingPanel.add(largePanel); 

         glassPane.add(dimmingPanel); 

         dimmingPanel.startTimer(); 
         glassPane.setVisible(true); 

         panelVisible = true; 
        } 
        else 
        { 
         glassPane.setVisible(false); 
         panelVisible = false; 
        } 
       } 
      }); 

      f.pack(); 
      f.setVisible(true); 
     } 

     private Timer timer; 
     private float opacity = 0; 
     private long sysTime = System.currentTimeMillis(); 

     private static final int TIMER_INTERVAL = 50; // measured in milliseconds 
     private static final int TIMER_TOTAL = 750; // measured in milliseconds 

     private static final Color FADE_COLOUR = Color.RED; 
     private static final float FINAL_OPACITY = 0.3f; 

     public TranslucentGlass() 
     { 
      this(true); 
     } 

     public TranslucentGlass(boolean startTimer) 
     { 
      super(); 
      setOpaque(false); 
      setLayout(new BorderLayout()); 

      // Create a new timer to change the opacity over time and repaint the panel 
      timer = new Timer(TIMER_INTERVAL, new ActionListener() 
      { 
       public void actionPerformed(ActionEvent e) 
       { 
        long newSysTime = System.currentTimeMillis(); 
        opacity += FINAL_OPACITY * (newSysTime - sysTime)/TIMER_TOTAL; 
        sysTime = newSysTime; 
        validate(); 
        repaint(); 

        if(opacity >= FINAL_OPACITY) 
        { 
         timer.stop(); 
        } 
       } 
      }); 

      if(startTimer) 
      { 
       timer.start(); 
      } 
     } 

     public void startTimer() 
     { 
      timer.start(); 
     } 

     // Override the paintComponent calling paintComponent*s* to ensure the panels contents are painted 
     @Override 
     protected void paintComponent(Graphics g) 
     { 
      final Graphics2D g2 = (Graphics2D) g; 

      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity)); 
      g2.setColor(FADE_COLOUR); 
      g2.fillRect(0, 0, getWidth(), getHeight()); 
      g2.dispose(); 

      super.paintComponents(g); 
     } 
    } 

回答

1

在paintComponent函數中創建Graphics上下文的副本。這將解決問題。

public void paintComponent(Graphics g) 
{  
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g.create(); 
    ... 
} 
+0

我以前在任何自定義組件中都沒有看到過這個,但出於某種原因處置'Graphics2D'導致了問題。刪除該代碼行使它更好,但沒有完全解決它。創建'Graphics'的副本並使用該副本似乎可以做到。 – Tony 2012-02-16 18:46:14

+0

感謝您的支持。 – Remlap21 2012-02-17 11:41:34

0

中的paintComponent第一條語句應該是

super.paintComponent(g); 

序清離屏位圖。否則,你可能會得到意想不到的結果

+0

好,yes和no。是的,我可能應該打電話給它,但實際上並沒有幫助解決問題。 – Remlap21 2012-02-16 18:30:55

+0

你可能在這裏有多個錯誤 - 我指出一個會導致不一致結果的錯誤。 – 2012-02-16 18:33:27