2013-08-31 4 views
0

Я пытаюсь вызвать метод repaint из run() в коде. Если я перерисовываю() из MouseDragged или MouseMoved, он отлично работает. Но мне нужно сделать это из run(). Следующий код не вызывает вызов метода repaint из run().Попытка перекрасить Gui из run

Я новичок в JAVA. может ли кто-нибудь исправить код и вставить код? пожалуйста, извините любые глупые ошибки. :). Кстати, я видел, что SwingUtilities.invokelater может это исправить. но я не знаю, как это сделать. пожалуйста, исправьте код.

Заранее спасибо.

import java.awt.Graphics; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionListener; 
import javax.swing.JFrame; 

public class Tester { 

public static int x,y; 
public static void main(String[] args) { 
    x = 10; y= 10; 
    Draw d = new Draw(); 
    new Thread(d).start(); 
} 


public static class Draw extends JFrame implements Runnable,MouseMotionListener 
{ 

    public Draw() 
    { 
     super("Title"); 
     setSize(500,500); 
     addMouseMotionListener(this); 
     setVisible(true); 
    } 


    @Override 
    public void run() { 
     for(int i = 0 ; i < 10 ; i++) 
     { 
      System.out.println("Multithreaded"); 
      repaint(); 
     } 

    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 

    } 

    @Override 
    public void mouseMoved(MouseEvent e) { 


    } 

    public void paint(Graphics g) 
    { 
     System.out.println("repaint called"); 
    } 

} 


} 
+3

Что именно вы пытаетесь достичь? Какой смысл перерисовывать JFrame 10 раз в цикле? –

+1

'repaint()' запросы объединяются вместе, если незавершенный запрос уже присутствует в 'Event Dispatcher Thread'. Кроме того, попробуйте сделать внутри 'paintComponent (...)' метод 'JPanel' вместо прямого рисования на контейнере верхнего уровня. –

+0

@JBNizet Я ничего не пытался добиться. Я пытался проверить, вызван ли метод repaint() запуском. и сколько раз его вызывали. –

ответ

2

Свинг-персонал - пассивный двигатель перекраски. То есть, он будет обновляться только тогда, когда это требуется. RepaintManager также оптимизирован для объединения нескольких репрессий до нескольких событий перерисовки, которые, по его мнению, требуются.

Это значит, что вы можете сделать заявку на номер repaint, но нет гарантии, когда и когда произойдет перекраска.

Это делается главным образом для оптимизации производительности.

Отъезд Painting in AWT and Swing для получения более подробной информации.

Из-за своей природы repaint является потокобезопасным. repaint запрашивает RepaintManager, чтобы отправить событие рисования в очередь событий. Эта очередь обрабатывается Диспетчерством событий, то есть вам не нужно синхронизировать repaint с EDT самостоятельно.

Следующий пример демонстрирует эту идею. Он обеспечивает простой слайдер, который сбрасывает счетчики краски и устанавливает задержку между запросами repaint.

задержка Нить 0 миллисекунд ...

enter image description here

задержка Нить 2 секунды

enter image description here

Как вы можете видеть. При 0 миллисекундах (что фактически вы делаете в цикле) количество фактических красок не соответствует числу запросов на перерисовку, но при задержке в 2 секунды фактические краски и запросы краски почти равны (я думаю, что добавляется один из перерисовки, сделанных слайдером).

Фактически, в моем тестировании, около 100 миллисекунд, я смог получить его примерно равным. Я даже попробовал 5 миллисекунд и получил баланс.

Что фактическая краска делает и нагрузка на EDT будет также влиять на эти результаты ...

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class RepaintTest { 

    public static void main(String[] args) { 
     new RepaintTest(); 
    } 

    public RepaintTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private int paintRequests; 
     private int paints; 
     private int delay = 0; 

     public TestPane() { 
      Thread t = new Thread(new Runnable() { 
       @Override 
       public void run() { 
        while (true) { 
         paintRequests++; 
         try { 
          Thread.sleep(delay); 
         } catch (InterruptedException exp) { 
         } 
         System.out.println("tick"); 
         repaint(); 
        } 
       } 
      }); 
      t.setDaemon(true); 
      setLayout(new BorderLayout()); 
      final JSlider slider = new JSlider(); 
      slider.setMinimum(0); 
      slider.setMaximum(2000); 
      slider.setPaintTicks(true); 
      slider.setMajorTickSpacing(100); 
      slider.addChangeListener(new ChangeListener() { 
       @Override 
       public void stateChanged(ChangeEvent e) { 
        delay = slider.getValue(); 
        paintRequests = 0; 
        paints = 0; 
       } 
      }); 
      slider.setValue(0); 
      add(slider, BorderLayout.SOUTH); 
      t.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      paints++; 
      String text = "Paints = " + paints + "; Paint Requests = " + paintRequests; 
      Graphics2D g2d = (Graphics2D) g.create(); 
      FontMetrics fm = g2d.getFontMetrics(); 
      int x = (getWidth() - fm.stringWidth(text))/2; 
      int y = ((getHeight() - fm.getHeight())/2) + fm.getAscent(); 
      g2d.drawString(text, x, y); 
      g2d.dispose(); 
     } 

    } 
} 
+0

Я понял, спасибо: D. –

0

Попробуйте реализации ActionListener, а затем добавить этот бит кода:

import javax.swing.Timer; 
private final int DELAY = 60; 
private Timer t; 
public Draw() { 
    //your code 
    t = new Timer(DELAY, this); 
    t.start(); 
} 
//implemented method 
@Override 
public void actionPerformed(ActionEvent e) { 
    repaint(); 
} 

Довольно сам объяснительный, что находится в методе actionPerformed вызывается каждые DELAY миллисекунд.

+0

Это не требуется, перекрасить по своей природе поточно-безопасный. Он отправит события в очередь событий, которая обрабатывается самим событием Диспетчерский поток – MadProgrammer

+0

@MadProgrammer. Я читаю, что перерисовка безопасна, если repaint является потокобезопасной, тогда, если я обновляю GUI из другого потока, то почему repaint не вызывается ? его следует называть 10 раз, но вместо этого иногда его вызывают один раз, иногда его вызывают дважды. Я не понимаю причину. не могли бы вы объяснить? –

+0

@ShubhashisKarmakar Нет, не следует. Как я уже говорил в предыдущем ответе, «RepaintManager» будет консолидировать повторные вызовы как можно меньшее количество событий перерисовки. Это делается для переоценки и является частью алгоритма пассивной рендеринга, используемого Swing. – MadProgrammer