【问题标题】:Java paintComponent override differences between versions 5 and 6Java paintComponent 覆盖版本 5 和 6 之间的差异
【发布时间】:2012-02-17 03:02:03
【问题描述】:

我已经针对 Java 5 开发了我的应用程序,我最近在 6 中进行了测试,发现我有一个paintComponent 问题。

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

【问题讨论】:

    标签: java swing


    【解决方案1】:

    你必须尝试这些代码,然后放在一起

    【讨论】:

      【解决方案2】:

      在paintComponent 函数中创建图形上下文的副本。这将解决问题。

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

      【讨论】:

      • 我以前在我制作的任何自定义组件中都没有看到过这种情况,但由于某种原因,处理 Graphics2D 会导致问题。删除那行代码使它变得更好,但并没有完全修复它。创建Graphics 的副本并使用该副本似乎可以解决问题。
      【解决方案3】:

      paintComponent 中的第一条语句应该是

         super.paintComponent(g);
      

      为了清除离屏位图。否则,您可能会得到意想不到的结果。

      【讨论】:

      • 嗯,是的,也不是。是的,我可能应该调用它,但它实际上并不能解决问题。
      • 你可能有不止一个错误 - 我指出一个会导致结果不一致的错误。
      猜你喜欢
      • 2012-01-03
      • 1970-01-01
      • 2015-12-13
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 2011-06-24
      • 1970-01-01
      • 2012-10-29
      相关资源
      最近更新 更多