2012-02-16 99 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