2014-09-06 4 views
2

Все процессоры, обновляющие мой графический интерфейс swing из мест, отличных от пользовательских кликов, выполняются с использованием EventQueue.invokeLater (например, вывод, созданный в результате длинного ходового процесса, не связанного с EDT).Наилучшая практика для работы с длительным запуском процесса setText JEditorPane

В моем текущем сценарии у меня есть процесс чтения сокетов TCPIP, который возвращает данные, которые необходимо обновить объект JEditorPane. Я использую вызов setText JEditorPane. Проблема заключается в том, что размещение вызова setText в процедуре invokeLater замораживает GUI для больших файлов (пример case case 19,790 KB).

Моя попытка разрешить это - выполнить действие setText в фоновом потоке, отличном от EDT. Это, похоже, решает проблему, НО, меня беспокоят лучшие практики, потому что JEditorPane setText в java 7 (JDK, который я использую) НЕ является потокобезопасным.

HOWEVER, проходящий через код JDK, мне кажется, что длительный процесс, выполняемый здесь, находится в JDKs DefaultEditorKit.read, и внутри этого метода единственный код, который будет влиять на графический интерфейс, находится в вызовах doc.insertString (если только я ошибаюсь). Теперь, когда вы смотрите на метод InsertString JDKs PlainDocument.java, он документирует, что это потокобезопасно, поэтому можно подумать, что это решение является надежным.

ОДНАКО ...

нагрузочного тестирования моего приложения, я несколько случайных кликов вокруг GUI, и в настоящее время есть анимация работает дерево узлов, и при большой нагрузке ниже, он появляется, чтобы замедлить анимацию немного, поэтому я обеспокоен тем, что я не выполнил наилучшее разрешение (также очень обеспокоены будущими JRE, которые меня заворачивают и поэтому не полагаются на insertString, которые в настоящее время являются потокобезопасными).

Я исследовал и увидел, что этот вопрос «как обращаться с давно запущенным JEditorPane setText» был задан раньше, но без подходящих ответов.

ВОПРОС 1) У кого-нибудь есть мысли о моих текущих наблюдениях?

ВОПРОС 2) Есть ли у кого-нибудь идеи о том, как я мог бы достичь этого?

ПРИМЕЧАНИЕ JEditorPane - мой единственный выбор здесь, потому что я буду в конечном итоге поддерживать динамические шрифты в стиле IDE.

Обратите внимание, что вызов ниже вызывается в рамках процедуры EventQueue.invokeLater, поэтому начальная работа в редакторе находится в EDT.

public void updateBigDataEditorPane(final JEditorPane editorPane, final String inStr) { 
    // Update editor object and content. 
    editorPane.setContentType("text/plain"); 
    editorPane.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N 
    editorPane.setDocument(editorPane.getEditorKit().createDefaultDocument()); 
    // Content update. NOTE in non-EDT thread to stop GUI freeze with large content. 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      //// synchronized 
      synchronized(tabsLock) { 
       // Set content. 
       editorPane.setText(inStr); 
      } //// synchronized 
     } 
    }).start(); 
} 
+0

Используйте SwingWorker для загрузки текста и используйте его метод, чтобы применить его ... – MadProgrammer

+0

@MadProgrammer SwingWorker применяет тот же принцип, что и выше (и как только я установил правильность выше, я изменю его на используйте SwingWorker). То есть, setText выполняется в фоновом режиме, а не в EDT (по сути, что такое SwingWorker, правильно?), То любые действия, требуемые для EDT, выполняются в методе done. Я предполагаю, что это то, что вы имеете в виду, потому что в противном случае установка setText в методе SwingWorker будет иметь тот же эффект, что и мой исходный код проблемы - выполнение setText в EDT зависает от GUI. Мысли? –

+0

№ SwingWoker предоставляет вам методы публикации/процесса, которые позволяют синхронизировать обновления с EDT. Дело в том, что вы можете просто использовать метод done, который также вызывается в EDT для обновления пользовательского интерфейса. Помните, что Swing, как правило, не защищен потоком. – MadProgrammer

ответ

0

В то время как ответы, были полезны и будут использоваться для решения конкретных длительных требований EDT потоков, решение, которое я закончил с использованием следующим образом;

  1. Создать новый объект JEditorPane
  2. Выполните трудоёмкую SetText вызов
  3. По завершению замены в настоящее время активного объекта JEditorPane на GUI с этим вновь созданными один.

Использование SwingWorker для выполнения фона без EDT задачи (1 & 2), а затем выполнить шаг 3 на завершение в потоке EDT.

0

Вы можете использовать документ в EditorPane (через editorPane.getDocument()) и выполнить изменения в этот документ (с помощью insertString (...), вместо того, чтобы использовать SetText (...)) в другом потоке ,

Делая это, вы можете (вид) динамически (означает: при чтении) написать содержимое.

В примере (добавить текст из файла в Textpane, без замораживания пользовательского интерфейса):
(EDIT: этот новый код не испытания, но она должна лучше продемонстрировать мое предложение ...):

public void readFileAsync() 
{ 
    final String fileName = "/path/to/file.txt"; 
    final StyledDocument doc = yourTextPane.getStyledDocument(); 

    Runnable r = new Runnable() 
    { 
     public void run() 
     { 
      try 
      { 
       List<String> lines = Files.readAllLines(Paths.get(fileName), Charset.defaultCharset()); 
       for (String line : lines) 
       { 
        SwingUtilities.invokeLater(new Runnable() 
        { 
         public void run() 
         { 
          doc.insertString(doc.getLength(), line, null); 
         } 
        }); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t = new Thread(r); 
    t.start(); 
} 
+0

Состояние sycnhronisation потока недавно изменилось, и это может быть небезопасным потоком ... – MadProgrammer

+0

@Ben, выполняющий изменения в документе: если это сделано с помощью EDT, имеет ту же проблему с замораживанием GUI, что и изначально сообщалось. Если сделано из EDT, по существу, станет тем же самым решением, которое я изначально предложил, - единственное различие заключается в том, что мое предложенное решение выполняет действия вставки предварительного документа (код в setText и чтение, описанный выше) вне EDT. –

+0

@MadProgrammer В настоящее время в версии JDK 7, которую я использую, метод insertString document является потокобезопасным, если действительно решение выше звучит, мне нужно будет изучить последствия доставки моего JDK7-кода на более поздних JRE (I не задавайте этот вопрос здесь, опасаясь опускания, учитывая, что я еще не изучил это). –