« Разработка веб-страниц с помощью google gears. Часть 3 | Разработка веб-страниц с помощью google gears. Часть 4 » |
Про java swing - часть 6
Элемент управления (контейнер) 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);
}
}
}
}
}
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);
}
}
public JScrollPane(Component view, int vsbPolicy, int 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);
}
});
Элемент управления (контейнер) 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);
« Разработка веб-страниц с помощью google gears. Часть 3 | Разработка веб-страниц с помощью google gears. Часть 4 » |