410013796724260
• Webmoney
R335386147728
Z369087728698
JTabbedPane, JSplitPane, JViewPortПанель с вкладками JTabbedPane позволяет в компактном виде размещать визуальные компоненты в интерфейсе приложения. При этом пользователь может работать только с одной группой компонентов на одной из вкладок, в то время, как остальные компоненты на других вкладках будут скрыты. Таким образом можно рационально использовать пространство формы и, при этом, представлять логически связанные группы компонентов. Разделяемая панель JSplitPane используется для гибкого распределения пространства между двумя компонентами. Она позволяет произвольным образом изменить соотношение размеров связанных компонентов. Панель прокрутки JScrollPane предназначена для размещения компонентов, размер которых может превышать доступный для них размер интерфейса (формы). В этом случае часть информации может быть скрыта. JScrollPane позволяет прокручивать содержимое визуального компонента и легко перемещаться к любой другой его части. В статье приводится пример использования компонента JViewPort, который является основой панели прокрутки, и который можно использовать в приложениях как «видоискатель». Панель с вкладками JTabbedPaneJTabbedPane позволяет размещать компоненты на так называемых вкладках tabs. Вкладки могут включать надписи, иконки, всплывающие подсказки и располагаться сверху, снизу, слева и справа. Для добавления вкладки в панель JTabbedPane можно использовать методы add() или addTab(). Второй метод лучше соответствует производимому действию и параметры этого метода удобнее настраивать. Методы addTab панели JTabbedPanepublic void addTab(String title, Component component) public void addTab(String title, Icon icon, Component component, String tip) JTabbedPane включает два перегруженных метода addTab. В качестве параметров второму методу addTab необходимо передать надпись, соответствующую вкладке, иконку, если она используется, компонент и всплывающую подсказку. Пример использования панели JTabbedPane// Swing пример использования панели с вкладками JTabbedPane import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.GridLayout; import java.awt.event.MouseEvent; import java.awt.event.MouseAdapter; public class TabbedPaneTest extends JFrame { private final Color[] colors = {Color.cyan, Color.orange, Color.magenta, Color.blue, Color.red , Color.green , Color.yellow , Color.pink }; private final String TEMPL_label = "Метка %d"; private final String TEMPL_dynamic = "Динамическая метка %d"; private final String TEMPL_button = "Кнопка %d"; private final String TEMPL_tab = "Вкладка %d"; public TabbedPaneTest() { super("Пример панели с вкладками JTabbedPane"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Левая панель с вкладками JTabbedPane tabsLeft = new JTabbedPane(JTabbedPane.BOTTOM, JTabbedPane.SCROLL_TAB_LAYOUT); // Создание вкладок for (int i = 1; i < colors.length; i++) { JPanel panel = new JPanel(); // Подкрашиваем панель panel.setBackground(colors[i - 1]); // Размещение метки во вкладке panel.add(new JLabel(String.format(TEMPL_label, i))); // Добавление вкладки tabsLeft.addTab(String.format(TEMPL_tab, i), panel); // Подключение мнемоники tabsLeft.setMnemonicAt(i-1, String.valueOf(i).charAt(0)); } // Подключение слушателя событий tabsLeft.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { // Получение выделенной вкладки JPanel panel = (JPanel)((JTabbedPane)e.getSource()).getSelectedComponent(); // Количество компонентов в панели int count = panel.getComponentCount(); // Добавление на вкладку новой метки panel.add(new JLabel(String.format(TEMPL_dynamic, count))); } }); // Подключение слушателя мыши tabsLeft.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { // Определяем индекс выделенной мышкой вкладки int idx = ((JTabbedPane)e.getSource()).indexAtLocation(e.getX(), e.getY()); System.out.println("Выбрана вкладка " + idx); } }); // Правая панель с вкладками JTabbedPane tabsRight = new JTabbedPane(JTabbedPane.TOP); // Создание вкладок for (int i = 1; i < colors.length; i++) { // Создание и подкрашивание панели JPanel panel = new JPanel(); panel.setBackground(colors[colors.length - i]); // Создание кнопки в панели panel.add(new JButton(String.format(TEMPL_button, i))); // Добавление панели во вкладку tabsRight.addTab("<html><i>Вкладка №" + i, new ImageIcon("images/copy.png"), panel, "Нажмите " + i); } // Определение табличного расположения компонентов getContentPane().setLayout(new GridLayout()); // Добавление вкладок в панель содержимого getContentPane().add(tabsLeft); getContentPane().add(tabsRight); // Вывод окна на экран setSize(600, 250); setVisible(true); } public static void main(String[] args) { new TabbedPaneTest(); } } В примере создается окно, в котором размещается две панели с вкладками JTabbedPane. Левая панель создается с помощью конструктора, принимающего два параметра: первый параметр определяет расположение вкладок, а второй указывает, как вкладки будут располагаться на экране в том случае, если их не удастся разместить в один ряд. Вкладки по умолчанию располагаются в несколько рядов. Такому поведению соответствует константа WRAP_TAB_LAYOUT. В примере для панели выбрана константа SCROLL_TAB_LAYOUT, добавляющая в панель небольшие кнопки прокрутки. Вкладки в панель добавляются в цикле методом addTab(); в качестве содержимого каждой вкладки используется подкрашенная панель JPanel с меткой JLabel. Для каждой вкладки методом setMnemonicAt определяется мнемоника, позволяющая выполнять переход по нажатию на клавиши ALT-N, где N - номер вкладки. Интерфейс окна представлен на следующем скриншоте. Правая панель JTabbedPane создается с помощью более простого конструктора, в котором указывается лишь верхнее расположение вкладок JTabbedPane.TOP. Способ размещения вкладок на экране остается заданным по умолчанию. Вкладки также добавляются в цикле, как и в первом случае, но используется более функциональная перегруженная версия метода addTab(). Она принимает сразу четыре параметра: надпись для вкладки, иконка, компонент, который будет отображаться во вкладке, и текст всплывающей подсказки. Заголовок вкладки определен в формате HTML. В классе JTabbedPane все свойства доступны с использованием методов get/set. Поэтому параметры панели с вкладками нетрудно изменить в любой момент, вызвав соответствующие методы, представленные в следующей таблице.
Единственное событие, поддерживаемое панелью с вкладками JTabbedPane, за исключением низкоуровневых событий (общих для всех графических компонентов), относится именно к модели ее активизации. Добавив к панели JTabbedPane слушателя ChangeListener, можно перехватывать событие смены вкладки. В примере в обработчике данного события в панель активной вкладки добавляется текстовая метка. Разделяемая панель JSplitPaneРазделяемая панель JSplitPane используется для гибкого распределения пространства между двумя компонентами и представляет тонкую полосу. Перетаскиванием мышью этой полосы можно изменить соотношение занимаемого общего пространства двумя компонентами. Пример разделяемой панели JSplitPaneimport java.awt.Color; // Swing пример использование разделяемой панели JSplitPane import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.*; public class SplitPaneTest extends JFrame { private JLabel lblMain; private int dividerMain = 200; private final String TEMPL_lbl = "dividerLocation = %d"; public SplitPaneTest() { super("Пример разделяемой панели JSplitPane"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Главная разделяемая панель final JSplitPane splitHorizontal = new JSplitPane(); splitHorizontal.setOneTouchExpandable(true); // Размер разделяемой панели splitHorizontal.setDividerSize(8); // Положение разделяемой панели splitHorizontal.setDividerLocation(dividerMain); // Вертикальная разделяемая панель JSplitPane splitVertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true); // Создание панелей splitVertical.setTopComponent (new JScrollPane()); splitVertical.setBottomComponent(new JScrollPane()); // Положение разделяемой панели splitVertical.setDividerLocation(100); // Текстовая метка для главной панели lblMain = new JLabel(String.format(TEMPL_lbl, dividerMain)); // Главная панель JPanel pnlMain = new JPanel(); pnlMain.add(lblMain); pnlMain.setBackground(Color.cyan); // Настройка главной панели splitHorizontal.setLeftComponent(new JScrollPane(pnlMain)); splitHorizontal.setRightComponent(splitVertical); // Слушатель изменения свойств разделяемой панели splitHorizontal.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent arg0) { dividerMain = splitHorizontal.getDividerLocation(); lblMain.setText(String.format(TEMPL_lbl, dividerMain)); } }); // Размещение панели в интерфейсе и вывод окна на экран getContentPane().add(splitHorizontal); setSize(600, 400); setVisible(true); } public static void main(String[] args) { new SplitPaneTest(); } } В примере создается небольшое окно, в панели содержимого которого размещаются две разделяемые панели JSplitPane : горизонтальная и вертикальная. В горизонтальных панелях компоненты располагаются в ряд, в вертикальных панелях - друг над другом. Горизонтальная разделяемая панель создается по умолчанию. Для главной разделяемой панели splitHorizontal был использован конструктор без параметров. После создания компонента splitHorizontal были установлены свойства разделяемой панели. Свойство oneTouchExpandable=true позволяет добавить к разделителю компонентов две маленькие кнопки со стрелками, щелкая на которых можно мгновенно переместить панель в крайнее положение, полностью предоставив все пространство разделяемой панели одному из компонентов. Свойство dividerSize управляет размером разделительной полосы в пикселах. Метод setDividerLocation позволяет определить положение панели в интерфейсе. В качестве левого компонента главной разделяемой панели устанавливается (метод setLeftComponent) панель с текстовой меткой, в которой отображается положение splitHorizontal. Слушатель PropertyChangeListener, подключенный к разделяемой панели, позволяет отслеживать изменение позиции splitHorizontal, значение которой отображается в текстовой метке lblMain. Вторая вертикальная разделяемая панель создается конструктором, который принимает два параметра: первый задает тип панели (вертикальная или горизонтальная), а второй позволяет сразу же определить, будут ли компоненты при перемещении разделительной полосы непрерывно обновляться (перерисовываться и, если это сложный компонент, проводить проверку корректности). По умолчанию непрерывное обновление отключено. Непрерывное обновление можно включить (или выключить) и после создания разделяемой панели, меняя значение свойства continuousLayout. Разделяемые панели используют методы setTopComponent() и setBottomComponent(), позволяющие определить верхний и нижний компоненты соответственно. Для горизонтального разделения используются методы setLeftComponent() и setRightComponent. Следует обратить внимание, что при размещении компонентов в разделительные полосы используются полосы прокрутки JScrollPane. Использовать панели прокрутки для компонентов, содержащихся в разделяемой панели, приходится почти всегда, поскольку разделяемая панель учитывает минимальный размер компонента и не позволяет делать его размер меньше. Если минимальный размер компонента значим (к примеру, минимальный размер надписи со значком равен размеру значка), толку от разделяемой панели будет мало — она просто не позволит изменять размеры компонентов и гибко распределять пространство контейнера. Принимая это во внимание, необходимо включать компоненты в панели прокрутки. Интерфейс примера с разделяемой панелью JSplitPane представлен на следующем скриншоте. Дополнительные свойства разделяемой панели JSplitPane
Панель прокрутки JScrollPaneПанель прокрутки JScrollPane дает возможность наделить компонент большого размера возможностью прокрутки на экране. JScrollPane добавляет в интерфейс, две полосы прокрутки, используя которые можно переходить к той или иной части компонента и отображать их на экране. Как правило, для добавления панели прокрутки к компоненту достаточно использовать следующий код : add(new JScrollPane(<компонент>); Передав компонент в простейший конструктор класса JScrollPane, разработчик может ограничить размеры компонента, не беспокоясь о том, что пользователь не сможет получить доступ к какой-либо его части. Рассмотрим небольшой пример, в котором настроим простые свойства панели прокрутки JScrollPane. // Использование панелей прокрутки JScrollPane import javax.swing.*; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Rectangle; public class ScrollPaneTest extends JFrame { private JLabelGrid label; public ScrollPaneTest() { super("Пример использования JScrollPane"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Создание панели прокрутки label = new JLabelGrid(); JScrollPane scrollPane = new JScrollPane(label, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); // Устанавливаем заголовки scrollPane.setColumnHeaderView(new XHeader()); scrollPane.setRowHeaderView (new YHeader()); // Определение свойств панели прокрутки scrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.yellow)); scrollPane.setWheelScrollingEnabled(true); // Размещение кнопки печати в левом верхнем углу scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, new JButton(new ImageIcon("images/print.gif"))); // Вывод окна на экран getContentPane().add(scrollPane); setSize(450, 300); setVisible(true); } // Внутренний класс class JLabelGrid extends JLabel implements Scrollable { private static final long serialVersionUID = 1L; private int CELL_SIZE = 10; // размер ячейки сетки private int CELL_COUNT = 50; // количество ячеек сетки public JLabelGrid() { // Изображение волков setIcon(new ImageIcon("images/wolf.jpg")); } // Предпочтительный размер компонента @Override public Dimension getPreferredSize() { return new Dimension(CELL_SIZE*CELL_COUNT, CELL_SIZE*CELL_COUNT); } // Прорисовка компонента @Override 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); } } } // Предпочтительный размер области прокрутки @Override public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } // Приращение при прокрутке на один элемент @Override public int getScrollableUnitIncrement(Rectangle visible, int or, int dir) { return CELL_SIZE; } // Приращение при прокрутке "блоком" @Override public int getScrollableBlockIncrement(Rectangle visible, int or, int dir) { return CELL_SIZE*10; } // Контроль размера области прокрутки @Override public boolean getScrollableTracksViewportWidth() { return false; } @Override public boolean getScrollableTracksViewportHeight() { return false; } } // Заголовок по оси X class XHeader extends JPanel { // Размер заголовка @Override public Dimension getPreferredSize() { return new Dimension(label.getPreferredSize().width, 20); } // Прорисовываем линейку @Override public void paintComponent(Graphics g) { int width = getWidth(); for (int i = 0; i < width; i += 50) { g.drawString("" + i, i, 15); } } } // Заголовок по оси Y class YHeader extends JPanel { // Размер заголовка @Override public Dimension getPreferredSize() { return new Dimension(20, label.getPreferredSize().height); } // Прорисовываем линейку @Override public void paintComponent(Graphics g) { int height = getHeight(); for (int i = 0; i < height; i += 50) { g.drawString("" + i, 0, i); } } } public static void main(String[] args) { new ScrollPaneTest(); } } В примере для создания панели прокрутки используется конструктор JScrollPane с тремя параметрами, в котором первым размещается компонент JLabelGrid, нуждающийся в прокрутке. Второй и третий параметры управляют полосами прокрутки. Второй параметр определяет поведение вертикальной полосы прокрутки, третий — горизонтальной. По умолчанию используются описанные в классе JScrollPane в качестве констант значения XXX_SCROLLBAR_AS_NEEDED (где XXX может принимать значение VERTICAL или HORIZONTAL). Они указывают, что полосы прокрутки должны появляться на экране только в том случае, если компонент в панели прокрутки действительно велик и ему требуется прокрутка. В примере использовали значение SCROLLBAR_ALWAYS, которое означает, что полосы прокрутки будут находиться на экране в любом случае, даже если прокрутка не требуется. Есть и еще один режим вывода полос прокрутки — XXX_SCROLLBAR_NEVER. При выборе этого значения появление полос прокрутки на экране блокируется, даже если в этом возникает необходимость. Панель прокрутки всегда добавляет особую рамку к видимой части компонента. Видимая часть компонента выводится на экран окном просмотра JViewport. Рамку панели прокрутки можно сменить с помощью свойства viewportBorder. В примере она меняется рамкой LineBorder желтого цвета. Наконец, свойство wheelScrollingEnabled определяет, будет ли поддерживаться прокрутка колесиком мыши. Интерфейс примера с использованием JScrollPane представлен на следующем скриншоте. Особый интерес представляет компонент JLabelGrid, реализующий свой режим прокрутки с помощью интерфейса Scrollable. Было отмечено, что если панель прокрутки JScrollPane обнаруживает, что размещенный в ней компонент реализует данный интерфейс, она настраивает процесс прокрутки согласно информации, возвращаемой описанными в нем методами. Методы интерфейса Scrollable представлены в следующей таблице.
Полоса прокрутки JScrollPane не что иное, как удобный «фасад» для системы, занимающейся прокруткой компонента. Эта система состоит из специальным образом расположенных вспомогательных компонентов для прокрутки : вертикальных и горизонтальных полос прокрутки, заголовков и «уголков» панели. Отображение лишь части от целого компонента и переход к другим его частям лежит на плечах компонента JViewport, основной рабочей «лошадки» системы прокрутки. Заголовки панели прокрутки дополняют прокручиваемый компонент сверху и слева, позволяя размещать в них вспомогательную информацию. Как правило, заголовки используются в качестве навигационных или информационных дополнений: линеек или координатных осей, которые помогают быстро определить размеры прокручиваемой области, текущую позицию или получить иную вспомогательную информацию. В примере к панели прокрутки добавлены заголовки и размещена кнопка печати в левом верхнем уголке. Определить заголовки позволяют свойства columnHeaderView и rowHeaderView (верхний и левый заголовки соответственно). В качестве заголовков были использованы специальные компоненты, представленные в виде внутренних классов XHeader и YHeader. Они унаследованы от панелей JPanel и прорисовывают координатную сетку по оси X и Y с шагом в 50 пикселов. Обратите внимание на то, какой размер возвращается методами getPreferredSize() : по одной из осей он постоянен, а по второй зависит от компонента, находящегося в панели прокрутки. При создании заголовков чаще всего приходится поступать именно так : размеры заголовков должны совпадать с размерами области прокрутки, иначе они будут не в состоянии сообщить информацию обо всей прокручиваемой области. «Видоискатель» JViewportКомпонент JViewport удобно представлять себе в виде своеобразного «видоискателя», работающего примерно так же, как в фотоаппарате : есть общая картина, которую хотелось бы запечатлеть, но доступного пространства меньше. JViewport позволяет показывать часть компонента и при необходимости перемещаться к любой другой его части. К основным возможностям класса JViewport относится определение компонента для отображения, называемого видом, определение размера области для отображения, называемой видимым диапазоном (extent) и определение точки левого верхнего угла в области координат вида, с которой и отсчитывается видимая область. Управляя точкой левого верхнего угла можно отображать различные части компонента. «Видоискатель» JViewport редко применяется изолированно. Но если потребуется реализовать нестандартный способ прокрутки, то компонент JViewport может быть полезен и сам по себе. В следующем примере метка JLabel с изображением волков, размещается не в полосе прокрутки JscrollPane, а в JViewport. // Пример работы с компонентом JViewport import javax.swing.*; import java.awt.*; public class ViewportTest extends JFrame { public ViewportTest() { super("Пример JViewport"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Метка с изибражением JLabel label = new JLabel(new ImageIcon("images/wolf.jpg")); // "Видоискатель" JViewport viewport = new JViewport(); // Настройка "видоискателя" - размещение метки viewport.setView(label); // Определение видимого диапазона viewport.setExtentSize(new Dimension(200, 200)); // Точка начала видимой области viewport.setViewPosition(new Point(150, 150)); // Ограничение размера "видоискателя" viewport.setPreferredSize(new Dimension(200, 200)); // Определение менеджера расположения getContentPane().setLayout(new FlowLayout()); // Вывод окна на экран getContentPane().add(viewport); setSize(400, 300); setVisible(true); } public static void main(String[] args) { new ViewportTest(); } } С помощью «видоискателя» JViewport в интерфейсе отображается только часть большого изображения. На следующем скриншоте представлен интерфейс примера использования JViewport. Следует обратить внимание на следующие нюансы примера. В качестве менеджера расположения панели содержимого был использован менеджер FlowLayout и определен предпочтительный размер компонента JViewport, который совпадает с размером видимой области. Эти два условия обеспечивают размещения компонента JViewport в пределах установленных размеров. В противном случае он может занять всю доступную область интерфейса приложения вне зависимости от настройки. Скачать примерыИсходные коды примеров, рассмотренных на странице, можно скачать здесь (133 Кб). |