Про swing - часть 6

Материал из Dom.

Перейти к: навигация, поиск

[править] Элемент управления (контейнер) JscrollPane

Данные элементы представляют контейнеры для других элементов или контейнеров. Область прокрутки – не только набор полос и находящийся внутри элемент. Фактически область прокрутки состоит из 7 зон – одна из них центральная в которой находится сам элемент управления, две зоны образуют заголовок и левую границу и еще четыре – уголки прямоугольника, согласно приведенному рисунку.

Изображение:swing_5_3.png

Следующий пример был взят и творчески адаптирован на основании 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) Изображение:swing_5_5.png

Изображение:swing_5_6.png

[править] Элемент управления (контейнер) 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, добавив кнопку "развертывания или сворачивания панели за один клик"

Изображение:swing_5_6_1.png

Изображение:swing_5_6_2.png

Subscribe Now!

...

ObMachine projects & articles (java, flash, flex, php, ...)  -- black-zorro.com


Личные инструменты
Навигация