Использование режима резьбы SwingWorker
Для разработчиков свинг -разработчиков очень важно тщательно использовать параллелизм. Программа Good Swing использует механизмы параллелизма для создания пользовательских интерфейсов, которые не теряют ответа - независимо от того, какое взаимодействие с пользователем программа всегда может ответить на нее. Чтобы создать адаптивную программу, разработчики должны узнать, как использовать многопоточное чтение в рамках Swing.
Разработчик свинг будет иметь дело со следующими типами потоков:
(1) Начальные потоки, такие потоки выполнят код приложения инициализации.
(2) Поток отправки событий, все коды обработки событий выполняются здесь. Большая часть кода, который взаимодействует с структурой свинг, также должен выполнять этот поток.
(3) Рабочие потоки, также известные как фоновые потоки, будут выполнять все трудоемкие задачи.
Разработчикам не нужно явно создавать эти потоки в своем коде: они предоставляются во время выполнения или структуры свинга. Работа разработчиков состоит в том, чтобы использовать эти темы для создания отзывчивых, постоянных программ свинга.
Как и все другие программы, работающие на Java -платформах, программа Swing может создавать дополнительные потоки и пулы потоков, что требует использования подхода, который будет представлен в этой статье. В этой статье будут представлены три вышеуказанные темы. Обсуждение работников будет включать в себя использование класса javax.swing.swingworker. Этот класс имеет много полезных функций, включая связь и сотрудничество между задачами рабочих потоков и другими задачами потока.
1. Начальный поток
Каждая программа генерирует серию потоков в начале логики приложения. В стандартной программе есть только один такой поток: этот поток будет вызывать основной метод в основном классе программы. В апплете начальный поток является конструктором объекта апплета, который будет вызывать метод инициирования; Эти действия могут быть выполнены в одном потоке или в двух или трех разных потоках, все в зависимости от конкретной реализации платформы Java. В этой статье мы называем этот тип последних потоков потока.
В программе свинга в начальной теме не так много дел. Их основная задача - создать выполняемый объект, который инициализирует графический интерфейс и организует объекты, используемые для выполнения событий в потоке диспетчерии событий. Как только графический интерфейс будет создан, программа будет двигаться в основном событиями графического интерфейса, каждая из которых вызовет выполнение события в потоке диспетчеры. Код программы может организовать дополнительные задачи в потоки, управляемые событиями (при условии, что они выполняются быстро, чтобы они не мешали обработке событий) и не создают потоки работников (используемые для выполнения много времени задачи).
Первоначальная задача по созданию графического интерфейса в отношении поток - позвонить в javax.swing.swingutilities.invokelater или javax.swing.swingutilities.invokeandwait. Оба метода принимают уникальный параметр: Runnable используется для определения новых задач. Единственная разница между ними: invokerlater только организует задачу и возвращает; INVOKEANDWAIT будет ждать выполнения задачи перед возвращением.
См. Следующий пример:
SwingUtilities.invokelater (new Runnable ()) {public void run () {createAndshowgui (); }} В апплете задача создания графического интерфейса должна быть помещена в метод init и использовать InvokeandWait; В противном случае начальный процесс будет возможен до создания графического интерфейса, что может вызвать проблемы. В других случаях задачи создания графического интерфейса обычно являются последними в начальном потоке, который должен быть выполнен, поэтому оба используют Invokelater или InvokeandWait.
Почему начальный поток не создает графического интерфейса напрямую? Потому что почти весь код, используемый для создания и взаимодействия с компонентами свинг, должен быть выполнен в потоке диспетчерской события. Это ограничение будет обсуждаться ниже.
2. Поток распределения событий
Код обработки события Swing выполняется в специальном потоке, который называется потоком диспетчерской события. Большая часть кода, который вызывает метод Swing, выполняется в этом потоке. Это необходимо, потому что большинство качающихся объектов «не в безопасности».
Вы можете думать о выполнении кода как о выполнении серии коротких задач в потоке отправки событий. Большинство задач вызываются методами обработки событий, такими как ActionListener.ActionPerformed. Остальные задачи будут организованы кодом программы с использованием Invokelater или InvokeandWait. Задачи в потоке отправки событий должны быть в состоянии выполнять быстро. В противном случае необработанные события будут заброшены, а пользовательский интерфейс станет «отзывчивым».
Если вам нужно определить, выполняется ли ваш код в потоке отправки событий, вызовите javax.swing.swingutilities.iseventdispatchthread.
3. Рабочие нити и свинг -производители
Когда программа свинга должна выполнить длинную задачу, она обычно выполняется с помощью рабочей потока. Каждое задание выполняется в рабочем потоке, который является экземпляром класса Javax.swing.swingworker. Класс Swingworker - это абстрактный класс; Вы должны определить его подкласс, чтобы создать объект Swingworker; Обычно используйте анонимные внутренние классы для этого.
Swingworker предоставляет некоторые функции связи и управления:
(1) Подкласс свинг -работы может определить метод, выполненный. Когда фоновая задача будет выполнена, она будет автоматически вызвана потоком диспетчерской события.
(2) Класс Swingworker реализует java.util.concurrent.future. Этот интерфейс позволяет фоновым задачам предоставлять возвратное значение для других потоков. Методы в этом интерфейсе также предоставляют функции, которые позволяют отменить фоновые задачи и определять, были ли фоновые задачи выполнены или отозваны.
(3) Фоновые задачи могут дать промежуточные результаты, вызывая SwingWorker.publish, и поток для отправки событий будет называть этот метод.
(4) Фоновые задачи могут определять свойства связывания. Изменения в атрибуте привязки будут запускать события, а поток диспетчерской события позвонит обработчику события для обработки этих запускаемых событий.
4. Простые бэкэнд задачи
Вот пример, эта задача очень проста, но это потенциально трудоемкая задача. TumbleTem апплет импортирует серию файлов изображений. Если эти файлы изображений импортируются через начальный поток, будет задержка до появления графического интерфейса. Если эти файлы изображений импортируются в потоке отправки событий, графический интерфейс может временно не ответить.
Чтобы решить эти проблемы, класс TumbleM создает и выполняет экземпляр класса StringWorker, когда он инициализируется. Метод Doinbackground этого объекта выполняется в рабочем потоке, импортирует изображение в массив Imageicon и возвращает ссылку на него. Затем метод выполненного выполняется в потоке диспетчерского потока событий, получите возвращенную ссылку и поместите его в переменную члена IMG класса апплета. Это позволяет классу Tumbletem немедленно создать графический интерфейс без необходимости ждать завершения импорта изображения.
Следующий пример кода определяет и реализует объект Swingworker.
SwingWorker Worker = новый SwingWorker <ImageICon [], void> () {@Override public ImageICon [] doInbackground () {final Imageicon [] innerimgs = new Imageicon [nimgs]; for (int i = 0; i <nimgs; i ++) {innerimgs [i] = LoadMage (i+1); } вернуть Innerimgs; } @Override public void ed () {// Удалить метку «Загрузка изображений». animator.removeall (); Loopslot = -1; try {imgs = get (); } catch (прерывание, игнорировать) {} catch (java.util.concurrent.executionexception e) {string Почему = null; Бросая причина = e.getCause (); if (причина! = null) {почему = cane.getMessage (); } else {почему = e.getMessage (); } System.err.println ("ошибка получения файла:" + почему); }}}}; Все подклассы, унаследованные от Swingworker, должны реализовать Doinbackground; Реализация метода выполненного является необязательной.
Обратите внимание, что Swingworker - это класс парадигмы с двумя параметрами. Первый параметр типа указывает тип возврата Doinbackground. Это также тип метода получения, который можно вызвать другими потоками, чтобы получить возвратное значение от Doinbackground. Второй параметр типа указывает тип промежуточного результата. Этот пример не возвращает промежуточный результат, поэтому он установлен на недействительную.
Используя метод GET, вы можете использовать ссылку на объект IMGS (созданный в потоке работников) в потоке диспетчерского потока событий. Это позволяет обменять объекты между потоками.
На самом деле есть два способа вернуть объект классом Doinbackground.
(1) Нет параметров для вызова SwingWorker.get. Если фоновая задача не выполнена, метод GET будет блокироваться до тех пор, пока она не завершится.
(2) Вызовы SwingWorker.get с параметрами для указания тайм -аута. Если фоновая задача не выполнена, блокируйте, пока она не завершится - если не истекает тайм -аут, и в этом случае Get выбросит java.util.concurrent.timeoutexception.
5. Задачи с промежуточными результатами
Полезно иметь рабочую боковую задачу предоставить промежуточные результаты. Бэкэнд задач может вызвать Swingworker.publish Method для этого. Этот метод принимает много параметров. Каждый параметр должен быть указан вторым параметром типа свинг -работника.
SwingWorker.Process можно переопределить, чтобы сохранить результаты, предоставленные методом публикации. Этот метод вызывается потоком отправки событий. Набор результатов из метода публикации обычно собирается методом процесса.
Давайте посмотрим на примеры, предоставленные Filpper.java. Эта программа генерирует серию случайных логических тестов java.util.random через фоновую задачу. Это как эксперимент по броску монеты. Чтобы сообщить о своих результатах, фоновая задача использует объект Flippar.
Частный статический класс Flippair {Private Final Long Heads, Total; Flippair (длинные головы, длинный общий) {this.heads = головы; this.total = total; }} Головы представляют результат истины; Общее количество представляет общее количество бросков.
Фоновая программа является экземпляром Filptask:
Private Class Fliptsk расширяет SwingWorker <void, Flippair> {
Поскольку задача не возвращает конечный результат, нет необходимости указывать, что такое параметр первого типа, используйте void. После каждого «броска» задача вызывает публикацию:
@OverrideProtected void doInbackground () {long Heads = 0; длинный общий = 0; Случайный случайный = new Random (); while (! iscancelled ()) {total ++; if (random.nextboolean ()) {Heads ++; } Publish (New Flippair (Heads, Total)); } return null;} Поскольку публикация часто называется, многие значения Flippair будут собираться до того, как метод процесса будет вызван потоком диспетчерской события; Процесс фокусируется только на последнем наборе значений, возвращаемых каждый раз, и использует его для обновления графического интерфейса:
Protected void процесс (списки пары) {flippair pare = pairs.get (pairs.size () - 1); headstext.settext (string.format ("%d", pair.heads)); totaltext.settext (string.format ("%d", pair.total)); devtext.settext (string.format ("%. 10g", ((double) pair.heads)/((double) pair.total) - 0,5));} 6. Отмените фоновую задачу
Вызовите SwingWorker.cancel, чтобы отменить выполняющую фоновую задачу. Задача должна соответствовать своему собственному механизму. Есть два способа сделать это:
(1) Когда будет получено прерывание, оно будет прекращено.
(2) Звоните SwingWorker.iscancell. Если Swingworker вызывает отмену, метод вернет True.
7. Привязки атрибутов и методов состояния
Swingworker поддерживает связанные свойства, что очень полезно при общении с другими потоками. Обеспечивает два обязательных свойства: прогресс и состояние. Прогресс и состояние могут использоваться для запуска задач обработки событий в потоках диспетчеры.
Внедряя слушателя изменения имущества, программа может поймать изменения в прогрессе, состояния или других связующих свойств.
7.1 Переменная связанная с прогрессом
Переменная привязки прогресса представляет собой целочисленную переменную с диапазоном от 0 до 100. Она предопределила методы сеттера (защищенный свинг -chounder.setprogress) и Getter (Public Swingworker.getProgress).
7.2 Переменная связанная с государством переменная
Изменения в переменных связывания состояния отражают процесс изменения объекта SwingWorker в течение его жизненного цикла. Эта переменная содержит тип перечисления типа SwingWorker.stateValue. Возможные значения:
(1) В ожидании
Это состояние длится некоторое время, чтобы узнать по созданию объекта, который называется метод Doinbackground.
(2) началось
Это состояние длится на мгновение до того, как метод Doinbackground будет вызван до тех пор, пока не будет вызван метод выполнения.
(3) сделано
Оставшееся время, которое существует объект, останется в этом состоянии.
Если вам нужно вернуть значение текущего состояния, вы можете позвонить в SwingWorker.getState.
7.3 Статус методы
Два метода, предоставленные будущим интерфейсом, также могут сообщить о состоянии фоновых задач. Если задача отменяется, Iscancelled возвращает True. Кроме того, если задача выполнена, то есть она либо завершена нормально, либо отменена, Isdone возвращает True.
Использование контейнера на верхнем уровне
Swing предоставляет 3 класса контейнеров на верхнем уровне: JFrame, JDialog, Japplet. При использовании этих трех классов вы должны обратить внимание на следующие моменты:
(1). Чтобы отображаться на экране, каждый компонент графического интерфейса должен быть частью содержащей иерархии. Иерархия включения представляет собой древовидную структуру компонента, а контейнер верхнего уровня-его корень.
(2). Каждый компонент графического интерфейса может быть включен только один раз. Если компонент уже находится в контейнере, а затем пытается добавить его в новый контейнер, компонент будет удален из первого контейнера и добавлена во второй контейнер.
(3). Каждый контейнер на верхнем уровне имеет панель содержимого. Как правило, эта панель содержимого будет содержать (прямо или косвенно) все визуальные компоненты контейнера верхнего уровня.
(4). Вы можете добавить строку меню в верхний контейнер. Обычно эта панель меню помещается в верхний контейнер, но за пределами панели контента.
1. Контейнеры на верхнем уровне и иерархии включения
Каждая программа, которая использует компонент свинга, имеет по крайней мере один контейнер верхнего уровня. Этот контейнер верхнего уровня является корневым узлом, содержащим иерархию-эта иерархия будет содержать все компоненты качания, которые появятся в этом контейнере верхнего уровня.
Как правило, отдельное приложение на основе качания имеет по крайней мере одну иерархию включения, а его корневой узел-Jframe. Например, если приложение имеет одно окно и два диалоговых окна, приложение будет иметь три уровня включения, то есть будет три контейнера верхнего уровня. Иерархия сдерживания принимает jframe в качестве корневого узла, а два других иерархии сдерживания имеют jdialog в качестве корневого узла.
Крапплет, основанный на компонентах свинг, содержит хотя бы одну иерархию включения, и можно определить, что один из них должен быть сделан с помощью Japplet в качестве корневого узла. Например, апплет с диалоговым окном, он будет иметь два уровня включения. Компонент в окне браузера будет помещен в иерархию сдерживания, а его корневой узел - это объект Japplet. Диалоговое окно будет иметь иерархию, а его корневой узел - это объект jdialog.
2. Добавить компоненты в панель содержимого
Следующая операция кода - получить панель содержимого кадра в приведенном выше примере и добавить желтую метку:
Frame.getContentPane (). Add (Yellowlabel, Borderlayout.center);
Как показано в коде, вы должны сначала найти панель содержимого контейнера верхнего уровня и реализовать ее с помощью метода GetContentPane. Панель содержимого по умолчанию представляет собой простой промежуточный контейнер, который наследует от JComponent, используя Borderlayout в качестве менеджера панели.
Настройка панели контента проста - настроить диспетчер панели или добавить границы. Здесь следует отметить, что метод GetContentPane вернет объект контейнера, а не объект JComponent. Это означает, что если вам нужно воспользоваться преимуществами некоторых функциональности JComponent, вы также должны ввести конвертирование возвращаемого значения или создать свой собственный компонент в качестве панели контента. Наш пример обычно использует второй метод. Потому что второй метод является более ясным и ясным. Другой способ, которым мы иногда используем,-просто добавить самоопределенный компонент в панель содержимого, чтобы полностью покрыть панель содержимого.
Если вы создаете свою собственную панель контента, будьте осторожны, чтобы убедиться, что она непрозрачна. Неопроверенный JPanel будет хорошим выбором. Обратите внимание, что по умолчанию макет JPanel управляется как FlowLayout, и вы можете заменить его другим менеджером макета.
Чтобы компонент был панелью контента, вам необходимо использовать метод SetContentPane контейнера верхнего уровня, например:
// Создать панель и добавить компоненты в это. pane./contentpane.setopaque(true); toplevelcontainer.setContentPane(contentPane);
Примечание. Не используйте прозрачные контейнеры в качестве панелей содержимого, таких как JScrollpane, Jsplitpane и jtabbedpane. Прозрачная панель содержимого приведет к тому, что компоненты будут запутаться. Хотя вы можете сделать любой прозрачный компонент качания непрозрачным с помощью метода SetoPaque (true), он не будет выглядеть правильно, когда некоторые компоненты будут установлены полностью непрозрачными. Например, панель метки.
3. Добавление бара меню
Теоретически, каждый контейнер на верхнем уровне может иметь планку меню. Но факты показывают, что строка меню появляется только в кадре или в апплете. Чтобы добавить строку меню в контейнер на верхнем уровне, вам нужно создать объект jmenubar, собрать несколько меню, а затем вызовать метод SetJmenubar. Экземпляр Topleveldemo добавляет строку меню в свой кадр через следующий код.
Frame.setjmenubar (cyanmenubar);
4. Корневой панель
Каждый контейнер верхнего уровня опирается на неявный промежуточный контейнер, называемый корневым контейнером. Этот корневой контейнер управляет панелью содержимого и панели меню вместе с двумя или более другими контейнерами (см. Слоистая панель и т. Д.). Обычно вам не нужно знать об использовании корневого контейнера качелей. Однако, если вы хотите перехватить щелчок мыши или нарисовать несколько компонентов, вам нужно знать корневой контейнер.
Приведенное выше было описано о панели контента и дополнительной панели меню, и здесь не будет повторен. Два других компонента, содержащихся в корневом контейнере, представляют собой панель макета и стеклянная панель. Панель макета напрямую содержит панель меню и панель содержимого и позволяет сортировать другие компоненты, добавленные по координатам Z. Стеклянные панели обычно используются для перехвата входных действий, которые происходят в верхнем слое, и могут также использоваться для рисования нескольких компонентов.