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

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

390

ГЛАВА 13

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

Чтобы избежать негативного эффекта, достаточно считать, что вешка разбивки разделяемой панели представляет собой и так достаточно сильную визуальную рамку, и ни в коем случае не применять внутри разделяемой панели других рамок и эффектов отделения содержимого. На крайний случай, если вам совершенно необходима рамка или что-то подобное в компоненте, который содержится в разделяемой панели, вы можете отделить его от вешки разбивки с помощью пустой рамки EmptyBorder определенного размера, соблюдая при этом рекомендации дизайнеров вашего внешнего вида. Ну а панель прокрутки можно избавить от рамки по умолчанию, заменив ее на все ту же пустую рамку нулевого размера, и вы будете избавлены от лишних линий и «шума».

Панель прокрутки JScrollPane

Панель прокрутки JScrollPane — настоящая «волшебная палочка» пользовательских интерфейсов Swing. Она уже не раз позволяла нам добиваться многого всего строчкой кода и, как мы сейчас увидим, способна на большее. Несложно догадаться по названию, что панель JScrollPane дает возможность наделить компонент (обычно большого размера) возможностью прокрутки (на экране появляется одна или две полосы прокрутки, используя которые, вы можете переходить к той или иной части компонента, выводя ее на экран). Как правило, для добавления панели прокрутки достаточно следующей записи:

add(new JScrollPane(ваш_компонент));

Этой строкой вы добавляете в контейнер некоторый компонент, размеры которого не позволяют ему разместиться на экране полностью2. Передав компонент в простейший конструктор класса JScrollPane, вы получаете прекрасную возможность ограничить размеры компонента (применив для этого подходящие менеджеры расположения или вспомогательные компоненты), не беспокоясь о том, что пользователь не сможет получить доступ к какой-либо его части.

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

//SimpleScrollPanes.java

//Настройка некоторых простых свойств панелей прокрутки import javax.swing.*;

import java.awt.*;

public class SimpleScrollPanes extends JFrame { public SimpleScrollPanes() {

super("SimpleScrollPanes");

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

Управление пространством

391

setDefaultCloseOperation(EXIT_ON_CLOSE); // надпись

JLabel label = new JLabel(new ImageIcon("image.jpg"));

//особый конструктор панели прокрутки

JScrollPane scrollPane = new JScrollPane(label, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

//некоторые свойства scrollPane.setViewportBorder(

BorderFactory.createLineBorder(Color.BLUE));

scrollPane.setWheelScrollingEnabled(false);

//выводим окно на экран

add(scrollPane); setSize(400, 300); setVisible(true);

}

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

new Runnable() {

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

}

}

Пример замечательно прост: мы создаем надпись JLabel со значком ImageIcon, который был получен из файла с изображением в формате JPEG. Предположительно надпись большого размера. Мы размещаем ее в панели прокрутки, используя довольно сложный конструктор с тремя параметрами. Первый параметр, как нетрудно видеть, — это сам компонент, нуждающийся в прокрутке, то есть наша надпись с изображением. Вторые два параметра, прежде не применяемые нами при создании панелей прокрутки, управляют полосами прокрутки (JScrollBar), которые собственно и позволяют пользователю выполнять прокрутку. Первый из этих двух параметров определяет поведение вертикальной полосы прокрутки, второй — горизонтальной. По умолчанию используются описанные в классе JScrollPane в качестве констант значения XXX_SCROLLBAR_AS_NEEDED (где XXX может принимать значение VERTICAL или HORIZONTAL). Они указывают, что полосы прокрутки должны появляться на экране только в том случае, если компонент в панели прокрутки действительно велик и ему требуется прокрутка. Мы использовали значение SCROLLBAR_ALWAYS, которое означает, что полосы прокрутки будут находиться на экране в любом случае, даже если прокрутка не требуется. Иногда это позволяет ясно показать пользователю, что в случае необходимости компонент поддерживает прокрутку (к примеру, такое поведение вполне подходит текстовым компонентам: текста в них может быть немного, но полосы прокрутки должны быть всегда, как показатель того, что объем текста ничем не ограничен). Есть и еще один режим вывода полос прокрутки — XXX_SCROLLBAR_NEVER. При выборе этого значения полосы прокрутки не появляются на экране вообще, даже если в этом возникает необходимость. Обычно такое поведение требуется там, где прокрутка реализована программно. Помимо задания режима появления полос прокрутки в конструкторе вы можете изменять его с помощью свойств verticalScrollBarPolicy и horizontalScrollBarPolicy.

392

ГЛАВА 13

Далее мы настраиваем еще несколько свойств панели прокрутки. Как известно, панель прокрутки всегда добавляет особую рамку к видимой части компонента (видимая часть компонента выводится на экран окном просмотра JViewport, незаменимым помощником класса JScrollPane — вскоре мы о нем узнаем), которая определяется UIпредставителем. Иногда именно эта рамка позволяет придать компоненту, добавленному в панель прокрутки, законченный вид (в главе 11 мы отмечали, что списки JList из-за отсутствия своей собственной рамки выглядят без панели прокрутки не слишком презентабельно, то же относится к большинству текстовых компонентов). Менять ее стоит лишь тогда, когда у вас и так хватает визуального подчеркивания компонента, как мы говорили в этой главе про разделяемые панели. Как правило, лишнюю рамку можно просто убрать методом setBorder(), передав в него экземпляр пустой рамки EmptyBorder нулевого размера.

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

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

Запустив программу с примером, вы сможете увидеть (вернее, «пощупать») те небольшие, но часто требующиеся изменения, которые мы произвели с панелью прокрутки JScrollPane. Обратите внимание, что когда компоненту в панели прокрутки хватает места, он все равно занимает все доступное место в панели (растягивается), и то, как он при этом будет выглядеть, зависит уже исключительно от него. Надпись JLabel, к примеру, при избытке пространства по умолчанию помещает значок по центру, а текст бы разместила слева. При разработке интерфейса следует учесть все подобные «краевые условия», и удостовериться в том, что он всегда ведет себе подобающе. Для этого панель прокрутки предоставляет специальные инструменты, о которых мы сейчас узнаем.

Управление пространством

393

Управление прокруткой

По умолчанию процесс прокрутки компонента, добавленного в панель прокрутки JScrollPane, проходит довольно очевидно: при нажатии на одну из кнопок полос прокрутки компонент сдвигается в ту или иную сторону на один пиксел. При щелчке на полосе прокрутки видимая часть изображения меняется «блоком», при этом прежняя видимая часть исчезает, а вместо нее появляется следующая или предыдущая (в зависимости от того, по какую сторону полосы прокрутки был сделан щелчок) часть такого же размера, если это возможно. С другой стороны, можно вспомнить разнообразные сложные компоненты Swing, такие как списки или таблицы — уж они-то точно прокручиваются не по одному пикселу, даже если пользователь щелкает на кнопке полосы прокрутки. Вместо этого содержимое этих компонентов перемещается на одну логическую единицу: на один элемент списка или столбец таблицы, и это именно то поведение, что ожидает от них пользователь. Как же реализовать особое поведение при прокрутке?

Оказывается, ничего сложного в этом нет. Все компоненты Swing, поддерживающие нестандартную прокрутку, просто пользуются предоставленным им панелью прокрутки JScrollPane механизмом управления. Это интерфейс Scrollable, который необходимо реализовать компоненту, требующему особый режим прокрутки. Когда такой компонент попадает в панель прокрутки JScrollPane, последняя видит это и получает (вызывая определенные в интерфейсе методы Scrollable) дополнительную информацию о компоненте, которая и позволяет ей проводить прокрутку компонента так, как тому необходимо. Интерфейс Scrollable несложен и назначение методов его очевидно. Рассмотрим пример, в котором реализуем особый режим прокрутки своего компонента:

//ControllingScrolling.java

//Управление процессом прокрутки с помощью

//интерфейса Scrollable

import javax.swing.*; import java.awt.*;

public class ControllingScrolling extends JFrame { public ControllingScrolling() {

super("ControllingScrolling"); setDefaultCloseOperation(EXIT_ON_CLOSE);

//добавим в центр панель прокрутки с

//нашим компонентом

add(new JScrollPane(new GridComponent())); // выводим окно на экран

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

}

// компонент-"сетка" с особым режимом прокрутки class GridComponent extends JPanel

implements Scrollable { // размер ячейки сетки private int CELL_SIZE = 45;

394

ГЛАВА 13

//количество ячеек сетки private int CELL_COUNT = 50;

//предпочтительный размер компонента public Dimension getPreferredSize() {

return new Dimension(CELL_SIZE*CELL_COUNT, CELL_SIZE*CELL_COUNT);

}

//прорисовка компонента

public void paintComponent(Graphics g) { // нужно вызвать метод базового класса super.paintComponent(g);

for (int x=0; x<CELL_COUNT; x++) { for (int y=0; y<CELL_COUNT; y++) {

//рисуем ячейку g.setColor(Color.BLACK); g.drawRect(x*CELL_SIZE, y*CELL_SIZE,

CELL_SIZE, CELL_SIZE);

//текст с координатами g.drawString(""+x+","+y,

x*CELL_SIZE + 5, y*CELL_SIZE + CELL_SIZE/2);

}

}

}

//предпочтительный размер области прокрутки public Dimension getPreferredScrollableViewportSize() {

return getPreferredSize();

}

//приращение при прокрутке на один элемент public int getScrollableUnitIncrement(

Rectangle visible, int or, int dir) { return CELL_SIZE;

}

//приращение при прокрутке "блоком"

public int getScrollableBlockIncrement( Rectangle visible, int or, int dir) {

return CELL_SIZE*10;

}

// нужно ли следить за размером области прокрутки public boolean getScrollableTracksViewportWidth() {

return false;

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