Выпадающие списки позволяют пользователю делать выбор из дискретного набора значений. Линейные регуляторы(ползунки) дают возможность выбрать конкретное значение из диапазона возможных, например, любое число из интервала 1-100.
Наиболее часто линейные регуляторы создаются следующим образом:
1 |
JSlider slider = new JSlider(min, max, initialValue); |
Если не указывать минимальное, максимальное и начальное значение, принимаются соответственно величины 0, 100 и 50.
Если линейный регулятор должен располагаться вертикально, используется приведенный ниже конструктор:
1 |
JSlider slider = new JSlider(SwingConstants.VERTICAL, min, max, initialValue); |
Каждый из этих конструкторов создает простой регулятор. В качестве примера можно привести регулятор, который расположен в верхней части окна, представленного на рис.1. Позже мы рассмотрим более сложные варианты линейных регуляторов.
Когда пользователь перемещает ползунок регулятора, значение компонента изменяется в пределах от минимального до максимального. Все слушатели, связанные с линейным регулятором, получают событие ChangeEvent. Для этого чтобы получать извещения об изменении значения регулятора, нужно создать объект, реализующий интерфейс ChangeListener, и вызвать метод addChangeListener(). В этом интерфейсе объявлен лишь один метод stateChanged(). При его выполнении определяется значение регулятора.
1 2 3 4 5 6 |
public void stateChanged(ChangeEvent event) { JSlider slider = (JSlider)event.getSource(); int value = slider.getValue(); ... } |
Линейный регулятор можно дополнить делениями(tic). Например, в программе, рассматриваемой в качестве примера, для второго регулятора производятся следующие установки:
1 2 |
slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); |
Регулятор снабжен основными делениями, следующими через каждые 20 единиц измерения, и вспомогательными, которые следуют через каждые 5 единиц. В данном случае единицы измерения связываются со значениями регулятора и не имеют никакого отношения к пикселям.
Приведенные выше выражения лишь устанавливают деления регулятора. Чтобы вывести их на экран, нужно вызвать следующий метод:
1 |
slider.setpaintTicks(true); |
Основные и вспомогательные деления не зависят друг от друга. Например, можно задать расстановку основных делений через каждые 20 единиц, а вспомогательных — через 7 единиц, хотя такая шкала будет довольно неудобной.
Можно перевести регулятор в режим привязки к делениям. Как только пользователь отпустит ползунок регулятора, он тут же переместится на ближайшее деление. Чтобы задать такой режим работы, нужно вызвать следующий метод:
1 |
slider.setSnapToTicks(true); |
В режиме привязки к делениями компонент работает несколько неожиданно. Пока регулятор не установится точно на деление, обработчик событий изменений получает значения, не соответствующие делениями шкалы. Если же пользователь перемещает ползунок щелчком мыши, то все равно не попадает на ближайшее деление.
С помощью приведенного ниже вызова можно задать метки основных делений:
1 |
slider.setPaintLabels(true); |
Например, если значение регулятора изменяется в пределах от 0 до 100, а шаг основных делений равен 20, на экране появятся метки 0, 20, 40, 60, 80 и 100.
Можно задать и другие типы меток, например строки или пиктограммы(смотрите рис.1). Эта задача не тривиальна. Сначала нужно заполнить хеш-таблицу с ключами типа Integer и значениями типа Component(автоматическое преобразование, реализованное в Java SE 5.0 и последующих версиях, упрощает этот процесс). Затем следует вызвать метод setLabelTable(). Компоненты размещаются под делениями.
Обычно используются объекты класса JLabel. Ниже показано, как можно задать метки делений A, B, C, D, E и F.
1 2 3 4 5 6 |
Hashtable<Integer, Component> labelTable = new Hashtable(Integer, Component>(); labelTable.put(0, new JLabel("A")); labelTable.put(20, new JLabel("B")); ... labelTable.put(100, new JLabel("F")); slider.setLabelTable(labelTable); |
В сегодняшней пример программы показан пример создания регулятора, у которого метками деления являются пиктограммы.
Если деления или их метки не выводятся на экран, проверьте, вызваны ли методы setPaintTicks(true) и setpaintLabels(true).
Четвертый регулятор на рис.1 не имеет «дорожки». Подавить изображение «дорожки», по которой двигается ползунок, можно с помощью вызова:
1 |
slider.setPaintTrack(false); |
Для пятого регулятора на этом рисунке направление движение изменено посредством следующего метода:
1 |
slider.setInverted(true); |
Набор регуляторов, создаваемых в приведенном здесь примере, демонстрирует различные визуальные эффекты. Для каждого регулятора установлен обработчик событий, который отображает текущее значение выбранного регулятора в поле редактирования, расположенном в нижней части окна.
Код программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
import java.awt.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; public class SliderTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { SliderTestFrame frame = new SliderTestFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); } } /** * Фрейм с линейными регуляторами и полем редактирования, * отображающим текущее значение выбранного регулятора. */ class SliderTestFrame extends JFrame { public SliderTestFrame() { setTitle("SliderTest"); setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); sliderPanel = new JPanel(); sliderPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); // Общий слушатель для всех регуляторов. listener = new ChangeListener() { public void stateChanged(ChangeEvent event) { // Обновление поля редактирования при // изменении значения регулятора. JSlider source = (JSlider) event.getSource(); textField.setText("" + source.getValue()); } }; // Добавление простого регулятора. JSlider slider = new JSlider(); addSlider(slider, "Plain"); // Добавление регулятора с основными // и вспомогательными делениями. slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "Ticks"); // Добавление регулятора с привязкой к делениям. slider = new JSlider(); slider.setPaintTicks(true); slider.setSnapToTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "Snap to ticks"); // Добавление регулятора без "дорожки" slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); slider.setPaintTrack(false); addSlider(slider, "No Track"); // Добавление регулятора с обратным направлением движения. slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); slider.setInverted(true); addSlider(slider, "Inverted"); // Добавление регулятора с числовыми метками. slider = new JSlider(); slider.setPaintTicks(true); slider.setPaintLabels(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "Labels"); // Добавление регулятора с буквенными метками. slider = new JSlider(); slider.setPaintTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); Dictionary<Integer, Component> labelTable = new Hashtable<Integer, Component>(); labelTable.put(0, new JLabel("A")); labelTable.put(20, new JLabel("B")); labelTable.put(40, new JLabel("C")); labelTable.put(60, new JLabel("D")); labelTable.put(80, new JLabel("E")); labelTable.put(100, new JLabel("F")); slider.setLabelTable(labelTable); addSlider(slider, "Custom labels"); // Добавление регулятора с метками в виде пиктограмм. slider = new JSlider(); slider.setPaintTicks(true); slider.setPaintLabels(true); slider.setSnapToTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(20); labelTable = new Hashtable<Integer, Component>(); // Добавление изображений карт. labelTable.put(0, new JLabel(new ImageIcon("nine.gif"))); labelTable.put(20, new JLabel(new ImageIcon("ten.gif"))); labelTable.put(40, new JLabel(new ImageIcon("jack.gif"))); labelTable.put(60, new JLabel(new ImageIcon("queen.gif"))); labelTable.put(80, new JLabel(new ImageIcon("king.gif"))); labelTable.put(100, new JLabel(new ImageIcon("ace.gif"))); slider.setLabelTable(labelTable); addSlider(slider, "Icon labels"); // Добавление поля редактирования для // отображения значения регулятора. textField = new JTextField(); add(sliderPanel, BorderLayout.CENTER); add(textField, BorderLayout.SOUTH); } /* * Добавление регулятора в панель и связывание его со слушателем. * @param s Регулятор * @param description Описание регулятора */ public void addSlider(JSlider s, String description) { s.addChangeListener(listener); JPanel panel = new JPanel(); panel.add(s); panel.add(new JLabel(description)); sliderPanel.add(panel); } public static final int DEFAULT_WIDTH = 350; public static final int DEFAULT_HEIGHT = 450; private JPanel sliderPanel; private JTextField textField; private ChangeListener listener; } |