2013-09-09 3 views
0

Хорошо так, у меня есть алгоритм работает, как указано ниже, и я хотел бы знать, как я мог перекрашивать в отдельном потоке вместо Event диспетчерской Темы:Как перерисовать() мой JPanel параллельно с вычислениями/в другом потоке?

Input an ArrayList of 2 Dimensional Point objects. 
while(each point object has not been a starting point) 
LOOP 

    Arbitrarily choose a starting point 
    Find the shortest path through all nodes 
    Call repaint() on the JPanel that displays this path. 

END LOOP 

Моего вопрос, как я могу настроить другой Thread, так что каждый раз, когда вычисляется кратчайший путь, он отправляет путь к потоку, который перерисовывает JPanel? Я хочу сделать это, потому что я чувствую, что теряю время перерисовки(), и это может сделать метод намного быстрее.

Я предполагаю, что я не могу просто сказать:

new Thread() { 
    void run() { 
     myJPane.repaint(); 
    } 
}.start() 

... так что бы создать новый поток каждый раз. Как я логически это делаю?

+0

пожалуйста, почему причина используя 'новый поток() {' 'и не свинг Timer', есть Somthing вроде как' OpenGL' – mKorbel

+0

к сожалению, я не понимаю, как я мог бы использовать Swing-таймер здесь ... – ujvl

ответ

4

Простой, используйте SwingWorker. A SwingWorker имеет методы публикации результатов длительных операций и обработки этих результатов на EDT.

Поэтому в основном ...

public class PathFinderWorker extends SwingWorker<Void, Path> { 
    protected Void doInBackground() throws Exception { 
     Input an ArrayList of 2 Dimensional Point objects. 
     while(each point object has not been a starting point) 
     LOOP 
      Arbitrarily choose a starting point 
      Find the shortest path through all nodes 
      publish(path); 

     END LOOP 
    } 

    protected void process(List<Path> paths) { 
     // Process the results as required... 
    } 
} 

Самое забавное repaint это, по его дизайн, это один из немногих способов, которые на самом деле Потокобезопасная.

То есть, repaint просит RepaintManager перекрасить область подачи. RepaintManager будет, в какой-то момент в ближайшем будущем, планировать paint событие в очередь событий, будет затем обрабатывается событие Диспетчерская Thread ... безопасно ...

Для получения более подробной информации, посмотрите на Concurrency in Swing

0

Покрасьте в EDT, сделайте свою работу в другой теме. EDT - это тот, который предназначен для работы с графическим интерфейсом - попытка привлечь еще один поток, который гарантированно будет испорчен.

Итак, реальный вопрос заключается в том, как передать значение или структуру данных из «рабочего» потока обратно в пользовательский интерфейс для рисования?

Вероятно, самая простая структура данных, которую я недавно видел для этого, была цепочка узлов, каждая с обратным указателем на предыдущий узел. Поскольку они неизменяемы, это можно безопасно передавать между потоками для отображения.

+0

Хорошо, поэтому в классе, который выполняет всю работу, которую я теперь понимаю, должен быть в отдельном потоке - как мне обратиться к вызову repaint(), чтобы он перерисовывался в EDT, а не в отдельном потоке? Я не уверен, что я понял ваш последний абзац (я действительно новичок в параллелизме и потоках, извините) Не могли бы вы добавить ссылку, объясняющую? – ujvl

+0

@Trust По своей природе «repaint» всегда планирует перекрасить обратно на EDT. 'repaint' simple просит« RepaintManager »рисовать область. Затем «RepaintManager» планирует событие рисования в очередь событий, которая обрабатывается EDT ... – MadProgrammer

+0

Так что было бы просто просто переписать repaint() на панели из потока, отличного от EDT, без каких-либо действий? Это так просто? – ujvl