Материал: Портянкин И. Swing

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Диапазоны значений

355

дом setStringPainted(true), и задаем нестандартный текст с помощью метода setString(). Текст, несмотря даже на то, что индикатор является вертикальным, может быть порядочного размера: текст прорисовывается так же, как и сам индикатор, то есть вертикально. Впрочем, стоит заметить, что читать в таком положении длинный текст не слишком удобно (может заболеть шея). Длинный текст лучше оставить для горизонтальных индикаторов, а в вертикальных ограничиться чем-то лаконичным, вроде символа процентов.

После настройки модели и индикаторов нужно добавить последние в панель содержимого нашего окна и вывести окно на экран. Так мы и делаем. Если больше ничего не предпринимать, индикаторы процесса застынут на отметке в пять процентов (помните, текущее значение модели изначально у нас равно пяти, а максимальное — ста, так что все справедливо) и будут малоинтересны. Действительно, в любом приложении, использующем индикаторы, должен быть некоторый процесс, по мере выполнения которого текущее значение индикатора непрерывно обновляется. Роль такого процесса в нашем примере сыграет внутренний класс LongProcess, созданный на основе инструмента SwingWorker и, следовательно, представляющий собой отдельный поток выполнения с возможностью вызова промежуточных действий в графическом потоке рассылке событий. В реальных приложениях процессом может быть загрузка данных из сети или файла с диска, установка компонентов или сетевых соединений, и еще много самых разных действий. Мы сразу же запускаем нашу задачу (вызывая метод execute()), и параллельно с потоком рассылки событий начинает выполняться ее метод doInBackground(). Работа задачи проста: пока текущее значение модели не превышает максимального (то есть пока наш воображаемый процесс не закончен), в цикле while текущее значение увеличивается на единицу, после чего процесс «засыпает» на случайный промежуток времени, а затем все повторяется. Случайный промежуток простоя процесса внесет в пример свою изюминку: вы увидите, как индикатор то бежит быстрее, то замедляется. Обратите внимание, что нам не приходится заботиться о синхронизации: мы применяем метод publish() для вызова кода из потока рассылки событий, передавая туда текущее значение для модели, и работаем с моделью, а не с компонентом, так что модель сама оповестит все присоединенные к ней виды о том, что пора обновить изображение. Просто и эффектно. Не забывайте, что работа с моделью, несмотря на то, что вы не работаете с графическими компонентами напрямую, подразумевает отсылку событий этим компонентам, и, соответственно, их обновление. Так что с моделями работать необходимо только из потока рассылки событий.

Напоследок выпишем все самые полезные свойства индикаторов JProgressBar, использованные нами в примере, чтобы они всегда были «под рукой» и могли послужить простым справочником (табл. 12.2).

356

ГЛАВА 12

Таблица 12.2. Основные свойства индикаторов JProgressBar

 

 

Свойства

Описание

orientation

Управляеториентациейиндикатора. Ориентацияможетбытьвертикальнойили

 

горизонтальной. Чаще всего это свойство задается при создании индикатора

 

инеменяетсявпоследствии. Еслижевыменяетеориентациюдлякомпонента,

 

которыйуженаходитсянаэкране, незабудьтепровестипроверкукорректности

 

контейнера: смена ориентации повлияет на расположение компонентов

stringPainted

Позволяет включить или выключить прорисовку текста на индикаторе про-

 

цесса. По умолчанию прорисовка текста выключена. Если вы ее включаете,

 

то стандартно будет прорисовываться значение в процентах, показываю-

 

щее, какая часть процесса закончена (значения берутся из модели). Сме-

 

нить текст позволяет следующее свойство

string

Задаеттекст, которыйбудетпрорисовыватьсянаиндикаторепроцесса. Неза-

 

бывайте только включать прорисовку текста: по умолчанию она отключена

value, maximum,

Эти свойства позволяют манипулировать данными модели Bounded-

minimum

RangeModel напрямуюспомощьюсамогоиндикатора(модельвлюбомслучае

 

есть, данные свойства просто делегируют ей свою работу). Управляют соот-

ветственно текущим, максимальным и минимальным значениями. Благодаря

им (а также благодаря конструкторам JProgressBar, которые сразу позволяют

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

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

Когда ничего не ясно

Бывают (и, надо сказать, довольно часто) ситуации, когда сказать точно, сколько осталось до завершения процесса и на каком этапе он в данный момент находится, вы не в состоянии. В таких случаях не слишком удобно использовать индикатор: непонятно, каковы же значения модели и как их обновлять. С другой стороны, лишать пользователя хоть какого-то намека на то, что процесс идет, тоже не следует. В расчете на такие ситуации индикаторы процесса JProgressBar поддерживают состояние «неопределенности»: периодическое движение на полосе есть, но, сколько осталось до конца, не ясно. В том случае, если процесс переходит в более «определенное» состояние, и вы, наконец, сможете выяснить, на каком этапе он находится и с какой скоростью продвигается, индикатор можно перевести в обычное состояние, которое нам уже знакомо. Давайте рассмотрим «неопределенный» пример:

//IndeterminateProgressBars.java

//Индикаторы в состоянии "неопределенности" import javax.swing.*;

import java.awt.*;

public class IndeterminateProgressBars extends JFrame { public IndeterminateProgressBars() {

Диапазоны значений

357

super("IndeterminateProgressBars"); setDefaultCloseOperation(EXIT_ON_CLOSE); // неопределенный индикатор

JProgressBar progress = new JProgressBar(0, 100); progress.setIndeterminate(true); progress.setStringPainted(true);

// добавляем его в окно и выводим на экран setLayout(new FlowLayout());

add(new JLabel("Соединение:")); add(progress);

setSize(300, 200); setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() { public void run() {

new IndeterminateProgressBars(); } });

}

}

В панель содержимого окна мы добавляем индикатор JProgressBar, у которого нет даже самой простой отдельной модели: нам помогает конструктор, позволяющий задать минимальное и максимальное значения, а стандартная модель будет создана автоматически, за кулисами. Большего нам не понадобится: индикатор в состоянии неопределенности не использует никаких данных модели. Как видно из примера, состояние «неопределенности» включается свойством indeterminate. Никаких действий предпринимать больше не требуется: индикатор сам позаботится о том, чтобы вид полосы периодически менялся, изображая продолжающуюся деятельность процесса и подбадривая этим пользователя. Дополнительно мы включили прорисовку текста свойством stringPainted, он появится даже в «неопределенном состоянии» (по умолчанию будет изображаться выполненная в процентах часть процесса — в зависимости от значения, установленного в модели). Однако чаще всего «неопределенное» состояние не использует стандартное отображение в процентах, как дополнительное подтверждение того, что на данный момент информация о выполнении процесса отсутствует. Лучше заменить строку на свою собственную, которая подчеркнет что процесс занимает неопределенное время. Запустив программу с примером, вы сможете оценить, как смотрится «неопределенная» ситуация в исполнении индикатора JProgressBar.

Пример довольно реален: сетевые соединения зачастую не позволяют сказать определенно, что именно произошло и когда возобновится прием информации.

358

ГЛАВА 12

Небольшие хитрости

Индикаторы процесса на самом деле очень просты, и работа с ними сводится в основном к обновлению текущего значения модели. Даже их внешний вид толком не настраивается (изменить можно лишь отображаемую индикатором строку). Впрочем, с помощью некоторых незамысловатых свойств UI-представителя индикаторов JProgressBar, не попавших в класс самого компонента, вы сможете добиться более изысканных визуальных эффектов, в некоторых случаях больше отвечающих стилю вашего приложения. Свойства эти отвечают за вид полосы индикатора. Рассмотрим небольшой пример, в котором эти свойства будут использоваться для достижения нового внешнего вида:

//ProgressBarTricks.java

//Небольшие хитрости индикаторов процесса import javax.swing.*;

import java.awt.*;

public class ProgressBarTricks extends JFrame { // максимальное значение индикатора

private final int MAX = 100; public ProgressBarTricks() { super("ProgressBarTricks");

setDefaultCloseOperation(EXIT_ON_CLOSE);

//настроим параметры для UI-представителей

UIManager.put("ProgressBar.cellSpacing", 2); UIManager.put("ProgressBar.cellLength", 6);

//стандартная модель

final DefaultBoundedRangeModel model =

new DefaultBoundedRangeModel(0, 0, 0, MAX);

//создадим простой индикатор процесса

//на основе полученной модели

JProgressBar progress = new JProgressBar(model);

//добавим его в окно setLayout(new FlowLayout()); add(progress);

//выводим окно на экран setSize(300, 200); setVisible(true);

//создадим "процесс"

Thread process = new Thread(new Runnable() { public void run() {

//увеличиваем текущее значение модели до

//достижения максимального значения

int value = 0;

while ( ++value <= MAX ) {

Диапазоны значений

359

final int passValue = value; SwingUtilities.invokeLater(

new Runnable() { public void run() {

model.setValue(passValue); }});

try { Thread.sleep(200);

} catch (Exception ex) { }

}

}

}); // запустим поток

process.start();

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new ProgressBarTricks(); } });

}

}

Здесь мы создаем небольшое окно, в котором разместится незатейливый индикатор процесса. Данные этому индикатору будет поставлять стандартная модель, начальное значение ее равно нулю, минимальное также равно нулю, а максимальное значение равно ста (вы можете видеть, как мы задаем значения в конструкторе модели). Самое интересное происходит в паре строк, которые настраивают внутренние свойства UIпредставителей индикаторов процесса (а мы знаем, что именно эти представители и выполняют фактическую прорисовку компонента на экране). Свойства UI-представителей всех компонентов Swing для любого внешнего вида хранятся в специальной таблице класса UIManager, и мы можем менять их, используя методы put(). Оказывается, что с помощью данных свойств можно тонко настроить внешний вид индикаторов процесса (точнее, перемещающейся в них полосы). Свойство с названием cellLength управляет тем, какой длины будут ячейки полосы индикатора (полоса индикатора не обязательно прорисовывается сплошной, она может состоять из набора ячеек одинакового размера), а свойство cellSpacing задает расстояние между ячейками (если это расстояние приравнять нулю, то полоса будет сплошной). Запустив программу с примером, вы увидите, как описанные два свойства влияют на внешний вид индикатора процесса (в современных пользовательских интерфейсах более популярны именно такие, ячеистые, индикаторы). Правда, стоит иметь в виду, что данные свойства действуют, только если в индикаторе процесса не прорисовывается информационная строка. Если строка есть, то полоса индикатора будет сплошной в любом случае.

Источник: https://studfile.net/preview/15935977/