2012-06-02 5 views
1

Я работаю над параллельным холстом, написанным на Java, который заставит пользователей думать, что они рисуют на холсте параллельно.SwingUtilities.invokeLater не работает как ожидалось

Для того, чтобы достигнуть воспринимаемого пользователем параллелизма, я получаю их для создания этих объектов Runnable, которые я продвигаю и добавляю EventQueue с помощью SwingUtilities.invokeLater().

Чтобы проверить это, я смоделировал пользователей, используя пару потоков, и добавил немного задержки (около 50 мс) между каждым вызовом invokeLater(), чтобы увидеть, действительно ли это выглядит так, как это происходит. в параллели.

Проблема заключается в том, что, хотя она отлично работала с этой добавленной задержкой между вызовами invokeLater(), извлечение этой задержки приводит к тому, что рисунки рисуются должным образом, частично отрисовываются и иногда исчезают и просто не рисуются в другое время ,

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

Ниже приводится код с задержкой закомментированного:

public void run(){ 
    //add tasks on to the event queue of the EDT 
    for(int i = 0; i<numLines; i++){ 
     DrawLineTask task = new DrawLineTask(g, x1, y1+i, x2, y2+i, lineColor); 
     SwingUtilities.invokeLater(task); 
//   try { 
// Thread.sleep(new Double(Math.random()*50).longValue());//random sleeping times to    make it appear more realistic 
//   } catch (InterruptedException e) { 
//    e.printStackTrace(); 
//   } 
    } 

Приветствия

EDIT: Вот код для DrawLineTask по запросу. Его довольно просто, как просто расширение класса Runnable, которое рисует линию, используя стандартную функцию Java по заданным параметрам.

public class DrawLineTask implements Runnable { 
Graphics g; 
int x1 = 0; 
int y1 = 0; 
int x2 = 0; 
int y2 = 0; 
Color color = Color.BLACK; 

public DrawLineTask(Graphics g, int x1, int y1, int x2, int y2){ 
    this.g = g; 
    this.x1 = x1; 
    this.y1 = y1; 
    this.x2 = x2; 
    this.y2 = y2; 
} 

public DrawLineTask(Graphics g, int x1, int y1, int x2, int y2, Color color){ 
    this.g = g; 
    this.x1 = x1; 
    this.y1 = y1; 
    this.x2 = x2; 
    this.y2 = y2; 
    this.color = color; 
} 

@Override 
public void run() { 
    g.setColor(color); 
    g.drawLine(x1, y1, x2, y2); 
} 

} 
+0

Просто догадайтесь, но я предполагаю, что «Thread.sleep» упростил время выполнения, чтобы переключиться на EDT, чтобы сделать рисунок, а это значит, что это произойдет почти сразу. – cHao

+1

Согласитесь с первым комментарием, но я подозреваю, что есть еще одна проблема. Можете ли вы опубликовать код DrawLineTask. –

+0

Спасибо за ваши ответы. Как вы можете видеть выше, код чертежа очень прост, и даже если он был каким-то образом вычислительным, EDT может немного замедлить, но он все равно будет рисовать линии. – freakii

ответ

4

AFAIK, вы не должны сохранить ссылку на объект Graphics и рисовать на ней, когда вы хотите. Вместо этого вы должны дождаться, когда метод paintComponent() будет вызван Swing, и сделайте свои рисунки в этом методе.

Итак, ваша задача должна просто изменить состояние вашего компонента и запросить асинхронную или синхронную перерисовку (используя repaint() или paintImmediately()). Затем Swing вызывает метод paintComponent() с объектом Graphics, который вы можете использовать для рисования соответствующих строк на основе состояния вашего компонента.

Для получения более подробной информации и разъяснений см. http://java.sun.com/products/jfc/tsc/articles/painting/.

+0

Я понимаю это. Тем не менее, я пытаюсь отделить задачу (команду) рисования от компонента, который должен быть нарисован, чтобы кто-либо извне мог создать задачу рисования и нарисовать ее на компоненте. Сказав это, хотя, поскольку объект, создающий задачи, будет иметь ссылку на компонент, на который они должны быть нарисованы, я продолжу и попробую ваше предложение и вернусь к вам. Благодаря! – freakii

+0

Итак, я сделал еще несколько тестов, и выясняется, что иногда появляются чертежи, а в других случаях их нет, потому что иногда вызов repaint() выполняется после рисования задач рисования, что приводит к очистке компонента. Я понимаю, что один из способов гарантировать, что предыдущие рисунки не теряются, - это поместить мой код рисования в paintComponent(), но я ожидаю, что пользователи будут продолжать рисовать, поэтому в конечном итоге не будут перерисовывать чертежи снова и снова битное налогообложение для системы? – freakii

+0

Также как я могу гарантировать, что предыдущие рисунки сохраняются в paintComponent(), поскольку все они завернуты в задачи? Должен ли я поддерживать какой-то список в методе paintComponent()? – freakii

Смежные вопросы