Blinking in JFrame Java

前端 未结 3 784
南笙
南笙 2020-12-06 23:54

Hello guys I am doing a thread to update a ball over JFrame so I repaint the screen... and then paint the ball update its position .. and then draw the screen again ... draw

3条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-07 00:33

    Some General Rules

    • Swing is not thread safe, you should only ever update UI components from within the context of the Event Dispatching Thread.
    • You do not control the paint process, the repaint manager does. You can request updates to occur by calling repaint, but you should never call update and paint directly when trying to update the display.
    • The Graphics context used by the paint sub system is a shared resource and is not guaranteed to be the same between paint cycles, you should never maintain a reference to it. You should also not rely on the results from JComponent#getGraphics this method is capable of returning null.

    An Example Solution

    You have a number of options, depending on what you want to ultimately achieve.

    You could use a SwingWorker, but given the fact that all your going to is enter an infinite loop and it would easier to use SwingUtilities#invokeLater then actually use the publish method, this approach would actually be more work.

    You could also use a Thread, but you'd end up with the same problems as using a SwingWorker

    The simpliset solution, for what you're presented, is actually a javax.swing.Timer

    public class Blinky {
    
        public static void main(String[] args) {
            new Blinky();
        }
    
        public Blinky() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new BlinkyPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
    
            });
        }
    
        protected class BlinkyPane extends JPanel {
    
            private JLabel blinkyLabel;
            private boolean blink = false;
    
            public BlinkyPane() {
                setLayout(new GridBagLayout());
                blinkyLabel = new JLabel("I'm blinking here");
                blinkyLabel.setBackground(Color.RED);
                add(blinkyLabel);
    
                Timer timer = new Timer(250, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        blink = !blink;
                        if (blink) {
                            blinkyLabel.setForeground(Color.YELLOW);
                        } else {
                            blinkyLabel.setForeground(Color.BLACK);
                        }
                        blinkyLabel.setOpaque(blink);
                        repaint();
                    }
                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.start();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 100);
            }
    
        }
    
    }
    

    You can take a look at Swing Timer and Concurrency in Swing for more info

提交回复
热议问题