Мигание в JFrame Java

Привет, ребята, я делаю поток для обновления шара над JFrame, поэтому я перекрашиваю экран... а затем рисую шар, обновляю его положение... а затем снова рисую экран... рисую шар и тот же цикл... вот код

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
   Thread t = new Thread()
   {
     public void run()
     {
         while(true)
         {
             repaint();
             b2.update(ob,2);
             b2.paint(ob.getGraphics());

             b2.setT(b2.getT() + 1);
             try {
                 Thread.sleep(50);
             } catch (InterruptedException ex) {
                 System.out.println("Error in Sleeping");
             }

         }
     }
   };

   t.start();
}

но проблема в том что я не вижу шарика... краска экрана всегда перекрывает шарик и шарик как бы внизу под Jframe..


person I.el-sayed    schedule 08.12.2012    source источник
comment
Каков тип ваших переменных b2 и ob? Я думаю, что проблема может заключаться в том, что вы вызываете код SWING вне EDT (поток отправки событий). Можно вызывать перерисовку вне EDT (repaint — одно из немногих исключений), но если b2 — компонент свинга (или awt), вызывать его методы вне EDT нельзя.   -  person Bjarke    schedule 08.12.2012
comment
переменная b2 является экземпляром общедоступного класса Ball extends JApplet, который является самим мячом. переменная ob является ссылкой на объект jframe. Я отправляю его в мяч, чтобы определить высоту и ширину кадра, чтобы избежать за гранью .. Знаешь что... когда я комментирую эту строку repaint(); мяч появляется, но поверх jframe, а jframe не обновляется, что ожидается ... но как только я добавляю его ... мяч исчезает ... !!   -  person I.el-sayed    schedule 08.12.2012
comment
Вы не должны обрабатывать задачи обновления графического интерфейса вне EDT.   -  person Extreme Coders    schedule 08.12.2012
comment
Чтобы быстрее получить помощь, опубликуйте SSCCE.   -  person Andrew Thompson    schedule 09.12.2012


Ответы (3)


Если вы хотите иметь анимацию в Swing, рекомендуется использовать класс javax.swing.Timer . Этот класс позволяет выполнять операции над потоком отправки событий через равные промежутки времени.

person Robin    schedule 08.12.2012
comment
Вы также можете использовать SwingWorker. - person Extreme Coders; 08.12.2012
comment
@ 2012-EndoftheWorld SwingWorker исчерпан для этой проблемы - person MadProgrammer; 09.12.2012
comment
+1 за javax.swing.Timer, который удобно инкапсулирует сон. - person trashgod; 09.12.2012

Некоторые общие правила

  • Swing не является потокобезопасным, вам следует обновлять компоненты пользовательского интерфейса только из контекста потока диспетчеризации событий.
  • Вы не контролируете процесс покраски, это делает менеджер по перерисовке. Вы можете запросить обновление, вызвав repaint, но вы никогда не должны вызывать update и paint напрямую при попытке обновить дисплей.
  • Контекст Graphics, используемый подсистемой рисования, является общим ресурсом и не гарантируется, что он будет одинаковым между циклами рисования, вы никогда не должны поддерживать ссылку на него. Вы также не должны полагаться на результаты JComponent#getGraphics, этот метод может возвращать значение null.

Пример решения

У вас есть несколько вариантов, в зависимости от того, чего вы хотите в конечном итоге достичь.

Вы могли бы использовать SwingWorker, но, учитывая тот факт, что все, что вам нужно, это войти в бесконечный цикл, и было бы проще использовать SwingUtilities#invokeLater, чем фактически использовать метод publish, этот подход на самом деле потребует больше работы.

Вы также можете использовать Thread, но вы столкнетесь с теми же проблемами, что и при использовании SwingWorker.

Упрощенное решение для того, что вам представлено, на самом деле является 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);
        }

    }

}

Вы можете ознакомиться с таймером Swing и Параллелизм в Swing для получения дополнительной информации.

person MadProgrammer    schedule 08.12.2012

Если вы получаете доступ к компонентам графического интерфейса вне EDT (поток отправки событий), вы можете столкнуться со странными проблемами. Напротив, если вы выполняете длительные задачи в EDT, у вас также возникнут проблемы.

Проверьте этот пост для получения дополнительной информации о GUI Threading in Java

person Extreme Coders    schedule 08.12.2012
comment
неа не работает.. как будто я рисую шарик но нет перерисовки на экран.... так что я все равно вижу след от шарика на экране.... вроде вижу места мяч там где был...и не удаляются...что не то что я хочу.. - person I.el-sayed; 08.12.2012
comment
вызов Thread.sleep в EDT не выполняется, поскольку он заблокирует весь пользовательский интерфейс. Используйте класс javax.swing.Timer, если вам нужна анимация в Swing. - person Robin; 08.12.2012