Про swing - часть 6
Материал из DOM
[править] Элемент управления (контейнер) JscrollPane
Данные элементы представляют контейнеры для других элементов или контейнеров. Область прокрутки – не только набор полос и находящийся внутри элемент. Фактически область прокрутки состоит из 7 зон – одна из них центральная в которой находится сам элемент управления, две зоны образуют заголовок и левую границу и еще четыре – уголки прямоугольника, согласно приведенному рисунку.
Следующий пример был взят и творчески адаптирован на основании Dem-ки из учебника swing на сайте sun. Однако тот пример мне не понравился, т.к. при изменении размера области и скролинге возникали баги отрисовки - линейки не изменяли свой размер. Посмотрите примечания по этой теме внизу в примере использования Rule.
Сначала пример компонента играющего роль "линейки" расположенной слева и сверху основной области прокрутки. В качестве параметра конструктору класса Rule передается флаг ориентации линейки (горизонтальная или вертикальная), таке указываем единицы измерения (ну что с буржуев с их дюймами и ярдами возьмешь ...)
class Rule extends JComponent { public static final int INCH = Toolkit.getDefaultToolkit().getScreenResolution(); // получаем сведения о разрешении экрана - сколько точек на дюйм public static final int HORIZONTAL = 0;// константы указывающие на режим создаваемой области линейки public static final int VERTICAL = 1; public static final int SIZE = 35;// размер по умолчанию для линейки public int orientation; public boolean isMetric; private int increment; private int units; // при создании линейки прокрутки необходимо указать ее ориентацию и используемые единицы измерения // будут ли использованы дюймы или сантиметры public Rule(int o, boolean m) { orientation = o; // ориентация линейки - горизонтальная или вертикальная isMetric = m;// единицы измерения setIncrementAndUnits();// метод изменения размеров штриха, растояния между ними } // установить режим метрической системы public void setIsMetric(boolean isMetric) { this.isMetric = isMetric; setIncrementAndUnits(); repaint(); } // функция выполняющая расчет величины приращения линейки прокрутки на основе текущих единиц измерения private void setIncrementAndUnits() { if (isMetric) { // получаем сколько точек должно прийтись на один сантиметр units = (int) ((double) INCH / (double) 2.54); increment = units; } else { units = INCH; increment = units / 2; } } public boolean isMetric() { return this.isMetric; } public int getIncrement() { return increment; } // установка размеров линейки - линейка будет занимать размер // равный одному дюйму // все методы изменения размеров линейки сводятся к перевызову базового для всех компонентов метода setPreferedSize public void setPreferredHeight(int ph) { setPreferredSize(new Dimension(SIZE, ph)); } public void setPreferredWidth(int pw) { setPreferredSize(new Dimension(pw, SIZE)); } protected void paintComponent(Graphics g) { // Метод, который выполняет рисование линейки для области прокрутки. // Обратите внимание на то, что здесь перекрыт не вызов paint, а, именно, paintComponent. // Дело в том, что paint выполняет рисование в следующей последовательности: // фон, САМ элемент, все дочерние элементы. // А метод paintComponent выполняет рисование именно САМОГО компонента. Rectangle drawHere = g.getClipBounds(); g.setColor(new Color(230, 253, 4)); g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height); // первым шагом всю область линейки закрасили фоновым цветом g.setFont(new Font("SansSerif", Font.PLAIN, 10)); g.setColor(Color.black); int end = 0; int start = 0; int tickLength = 0; String text = null; if (orientation == HORIZONTAL) { start = (drawHere.x / increment) * increment; end = (((drawHere.x + drawHere.width) / increment) + 1) * increment; } else { start = (drawHere.y / increment) * increment; end = (((drawHere.y + drawHere.height) / increment) + 1) * increment; } if (start == 0) { text = Integer.toString(0) + (isMetric ? " cm" : " in"); tickLength = 10; if (orientation == HORIZONTAL) { g.drawLine(0, SIZE - 1, 0, SIZE - tickLength - 1); g.drawString(text, 2, 21); } else { g.drawLine(SIZE - 1, 0, SIZE - tickLength - 1, 0); g.drawString(text, 9, 10); } text = null; start = increment; } for (int i = start; i < end; i += increment) { if (i % units == 0) { tickLength = 10; text = Integer.toString(i / units); } else { tickLength = 7; text = null; } if (tickLength != 0) { if (orientation == HORIZONTAL) { g.drawLine(i, SIZE - 1, i, SIZE - tickLength - 1); if (text != null) g.drawString(text, i - 3, 21); } else { g.drawLine(SIZE - 1, i, SIZE - tickLength - 1, i); if (text != null) g.drawString(text, 9, i + 3); } } } } }
Теперь пример кода использующего созданный компонент Rule.
public class ScrollDemo { public static void main(String[] args) { JFrame jf = new JFrame("scroller pic"); JLabel lab_img = new JLabel(new ImageIcon("C:\\tmp\\2011.jpg")); final JScrollPane jscr = new JScrollPane(lab_img); final Rule viewCol = new Rule(Rule.HORIZONTAL, true); // Устанавливаем размер линейки по высоте – 32 пикселя viewCol.setPreferredHeight(32); // Устанавливаем линейку по горизонтали. Заготоловок для области прокрутки. jscr.setColumnHeaderView(viewCol); final Rule viewRow = new Rule(Rule.VERTICAL, true); viewRow.setPreferredWidth(32); // Здесь добавляется линейка по вертикали. // Она будет располжена по вертикали слева. jscr.setRowHeaderView(viewRow); jscr.getViewport().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { viewCol.setPreferredWidth(jscr.getViewport().getComponent(0).getWidth()); // а для viewRow я не выполнил изменения размера и поэтому там возникают баги отрисовки } }); // Здесь добавляются кнопки в уголки области прокрутки jscr.setCorner(JScrollPane.UPPER_LEFT_CORNER, new JToggleButton("TL")); jscr.setCorner(JScrollPane.LOWER_LEFT_CORNER, new JToggleButton("BL")); jscr.setCorner(JScrollPane.UPPER_RIGHT_CORNER, new JToggleButton("TR")); jscr.setCorner(JScrollPane.LOWER_RIGHT_CORNER, new JToggleButton("BR")); jf.getContentPane().add(jscr, BorderLayout.CENTER); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } }
При создании области скроллинга, вы можете указать политику появления или отображения полос прокрутки. Так конструктор JscrollPane:
public JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
получает такие параметры, как vsbPolicy и hsbPolicy (они как раз и задают политику появления полос прокрутки). Возможные значения политик перечислены в таблице ниже:
| Политика | Примечание |
| VERTICAL_SCROLLBAR_AS_NEEDED и HORIZONTAL_SCROLLBAR_AS_NEEDED | Режим по умолчанию: полосы прокрутки появляются только тогда, когда в них есть необходимость. Т.е. когда область просмотра меньше, чем клиентская область просматриваемого компонента. |
| VERTICAL_SCROLLBAR_ALWAYS и HORIZONTAL_SCROLLBAR_ALWAYS | Всегда показывать полосы прокрутки. |
| VERTICAL_SCROLLBAR_NEVER и HORIZONTAL_SCROLLBAR_NEVER | Никогда не показывать полосы прокрутки. Такой режим используется, когда мы не хотим разрешить пользователю самостоятельно выполнять прокрукту. Например он использует другой элемент управления, а вы перевызываете методы прокрутки. |
[править] Элемент управления (контейнер) JtabbedPane
Панель с закладками представляется с помощью класса JtabbedPane. Каждая закладка представлена в виде произвольного компонента Swing. Также закладка характеризуется "ярлычком" состоящим из надписи и небольшой картинки иконки.
public static void main(String[] args) { final JFrame jf = new JFrame("scroller pic"); JTabbedPane jtabs = new JTabbedPane(JTabbedPane.LEFT, JTabbedPane.WRAP_TAB_LAYOUT); // Здесь мы создаем набор закладок. В качестве параметра указывается то, // где будут расположены ярлычки этих закладок. // Возможны варианты ориентации по всем 4-ем сторонам света. // Второй параметр управляет тем, что будет происходить // когда закладки не будут помещаться в одну линию. // В примере используется режим WRAP_TAB_LAYOUT. // Это значит, что закладки будут располагаться в несколько линий. // Возможен также и вариант JTabbedPane.SCROLL_TAB_LAYOUT // в этом случае появятся кнопки прокрутки. jf.getContentPane().add(jtabs, BorderLayout.CENTER); File fs[] = new File("C:\\tmp").listFiles( new FileFilter() { public boolean accept(File pathname) { return pathname.getName().toLowerCase().endsWith("jpg") || pathname.getName().toLowerCase().endsWith("gif"); } } ); for (int i = 0; i < fs.length; i++) { try { File f = fs[i]; // При добавлении новой закладки следует указать ее название и то какой // Компонент будет к ней привязан ImageIcon image = new ImageIcon(f.getCanonicalPath()); jtabs.add(f.getCanonicalPath(), new JScrollPane(new JLabel(image)) ); // Теперь я создаю иконку привязанную к ярлыку закладки. // Это уменьшенная до 32*32 px основная картинка jtabs.setIconAt(i, new ImageIcon(image.getImage().getScaledInstance(32, 32, Image.SCALE_AREA_AVERAGING))); } catch (IOException e) { e.printStackTrace(); } } jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); SwingUtilities.invokeLater(new Runnable() { public void run() { jf.setVisible(true); } });
Вот два примера как выглядят наборы закладок при различных стилях (JTabbedPane.SCROLL_TAB_LAYOUT и WRAP_TAB_LAYOUT)
[править] Элемент управления (контейнер) JsplitPane
Последний компонент широко используемый контейнер - JsplitPane. С его помощью мы создаем разделение области компонента на две зоны, в каждой из которых размещается отдельный компонент. С помощью разделителя Splitter-а мы можем изменять размер области.
// Здесь я указываю ориентацию разделителя. Она будет вертикальной JSplitPane jsplt1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT); // Здесь параметр конструктора - тоже ориентация, но уже горизонтальная JSplitPane jsplt2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); // Добавляю левый (верхний) компонент jsplt1.setLeftComponent(new JLabel("<HTML> <B> Left Zone</B>")); // теперь создаем подкомпоненты для вложенной области JSplitPane // сначала левый, затем правый jsplt2.setLeftComponent(new JLabel("<HTML> <B> Left - Left Zone</B>")); jsplt2.setRightComponent(new JLabel("<HTML> <B> Left - Right Zone</B>")); // можно создавать вложенные JSplitPane jsplt1.setRightComponent(jsplt2); // и последний шаг – устанавливаем прапорции мест, // которые будут отведены для каждой из частей контейнера // здесь используется дробное число в долях единицы. // однако возможны варианты и с заданием жескткого количества пикселей (метод одноименный, но получает на вход int) jsplt1.setDividerLocation(0.3); jsplt2.setDividerLocation(0.8); jf.getContentPane().add(jsplt1, BorderLayout.CENTER);
С помощью вызова:
jsplt1.setOneTouchExpandable(true);
Можно изменить немного поменять работу JSplitPane, добавив кнопку "развертывания или сворачивания панели за один клик"
|
|
Subscribe Now! |
|




