И.Н. Блинов, В.С. Романчик - Основы программирования на языке Java (1160783), страница 10
Текст из файла (страница 10)
В неактивном состоянии компонент типа JComboBox занимает столько места, чтобы показывать только текущий выбранный элемент. Для определения выбранного элемента можно вызвать метод getSelectedItem()или getSelectedIndex().// пример #3 : выпадающий список : MyComboBox.javaimport java.awt.*;import java.awt.event.*;import javax.swing.*;public class MyComboBox extends JApplet implements ItemListener{JLabel lbl;JComboBox cb;public void init(){lbl = new JLabel("0");cb = new JComboBox();Container c = getContentPane();60c.setLayout(new FlowLayout());cb.addItem("11"); cb.addItem("22");cb.addItem("33"); cb.addItem("44");cb.addItemListener(this);c.add(cb);c.add(lbl);}public void itemStateChanged(ItemEvent ie) {int arg = Integer.valueOf((String)ie.getItem()).intValue();double res = Math.pow(arg, 2); //возведение в квадратlbl.setText(Double.toString(res));}}При выборе элемента списка генерируется событие ItemEvent ипосылается всем блокам прослушивания, зарегистрированным дляприема уведомлений о событиях данного компонента.
Каждый блокпрослушивания реализует интерфейс ItemListener. Этот интерфейсопределяет метод itemStateChanged(). Объект ItemEvent передаетсяэтому методу в качестве аргумента. Приведенная программа позволяет выбрать из списка число, возводит его в квадрат и выводит его вобъект JLabel. Здесь также следует обратить внимание на способыпреобразования строковой информации в числовую и обратно.В следующем примере рассмотрено отслеживание изменения состояния объекта JСheckBox./* пример #4 : отслеживание изменения состояния флажка :MyCheckBox.java */import java.applet.*;import java.awt.*;import javax.swing.*;import java.awt.event.*;public class MyCheckBox extends JApplet implements ItemListener{CheckBox cb;JLabel lbl;public void init() {cb = new JCheckBox();lbl = new JLabel("инициализация");Container c = getContentPane();c.setLayout(new FlowLayout());cb.addItemListener(this);c.add(cb);61c.add(lbl);}public void itemStateChanged(ItemEvent ie) {String msg;if(ie.getStateChange() == ItemEvent.SELECTED) msg = "True";else msg = "False";lbl.setText(msg);}}Здесь приведены метод getStateChange(), извлекающий из объектаItemEvent константу состояния, в данном случае SELECTED, прослушиваемого объекта JCheckBox.Если требуются радиокнопки для получения поведения, вида "исключающее или", необходимо добавить их в "группу кнопок".
Но, какпоказывает приведенный ниже пример, любая AbstractButton можетбыть добавлена в ButtonGroup.Для предотвращения повтора большого количества кода этот пример использует рефлексию для генерации различных типов кнопок.Это происходит в makeMyPanel(), которая создает группу кнопок иJPanel. Второй аргумент для makeMyPanel() − это массив String. Длякаждого String, в JPanel добавляется кнопка класса, соответствующего первому аргументу:// пример #5 : различные типы кнопок и флажков: DiffButtons.javaimport javax.swing.*;import java.awt.*;import java.awt.event.*;import javax.swing.border.*;import java.lang.reflect.*;public class DiffButtons extends JApplet {static String[] str = {"первый","второй","все", };public void init() {Container c = getContentPane();c.setLayout(new FlowLayout());c.add(makeMyPanel(JButton.class, str));c.add(makeMyPanel(JToggleButton.class, str));c.add(makeMyPanel(JCheckBox.class, str));c.add(makeMyPanel(JRadioButton.class, str));}static JPanel makeMyPanel(Class aCl, String[] str) {ButtonGroup b = new ButtonGroup();62JPanel p = new JPanel();String title = aCl.getName();title = title.substring(title.lastIndexOf('.') + 1);p.setBorder(new TitledBorder(title));for(int j = 0; j < str.length; j++) {AbstractButton abs = new JButton("ошибка");try {Constructor cons = aCl.getConstructor(new Class[] { String.class});abs = (AbstractButton)cons.newInstance(new Object[]{str[j]});} catch(Exception e) {System.err.println("нельзя создать: "+aCl); }b.add(abs);p.add(abs);}return p;}}Заголовок для бордюра берется из имени класса, от которого отсекается вся информация о пути.
AbstractButton инициализируется спомощью JButton, которая имеет метку "ошибка", так что если игнорируется сообщение исключения, то проблема видна на экране. МетодgetConstructor() производит объект Constructor, который принимаетмассив аргументов типов в массиве Class, переданномgetConstructor(). Затем все, что нужно сделать − это вызватьnewInstance(), передав этот массив элементов Object, содержащийреальные аргументы (в этом случае просто String из массива str).Здесь немного усложнен простой процесс.
Для получения поведениякнопок, вида "исключающее или" создается группа кнопок и добавляется каждая кнопка, для которой определено поведение в группе. После запуска программы видно, что все кнопки, за исключениемJButton, показывают поведение, вида "исключающее или".Упражнения1.
Создать форму с несколькими кнопками так, чтобы надпись на первойкнопке при ее нажатии передавалась на следующую, и т.д.2. Создать выпадающий список так, чтобы при выборе элемента списка на экране появлялись GIF-изображения, двигающиеся по апплету.3. По экрану движутся одна за одной строки из массива строк. Направлениедвижения и значение каждой строки выбирается случайным образом.634. Строка составляется из символов появляющихся из разных углов апплета ивыстраювающихся друг за другом. Процесс циклически повторяется.5. По апплету движется окружность. При касании границы она отражается отнее с эффектом упругого сжатия.6.
Направление движения прямоугольника по экрану изменяется щелчком поклавише мыши случайным образом. При этом каждый второй щелчок меняет цветфона.7. Длина дуги окружности изменяется нажатием клавиш от 1 до 9.8. Клавиши “вверх”, “вниз”, “вправо”, “влево” двигают в соответствующемнаправлении линию. При достижении границ апплета линия появляется с противоположной стороны.9. Окружность “убегает” от указателя мыши. При приближении на некотороерасстояние окружность появляется в другом месте апплета.10. Квадрат на экране движется к указателю мыши, когда последний находится в границах апплета.11.
ПОТОКИ И МНОГОПОТОЧНОСТЬК большинству современных Web-приложений выдвигаются требования одновременной поддержки многих пользователей и разделения информационных ресурсов. Потоки – средство, которое поможеторганизовать одновременное выполнение нескольких задач с помощью многопоточности – использования нескольких потоков управления в одной программе. Например, метод repaint() создает поток, обновляющий экран, в то время как программа выполняется. Способдобавить анимацию в апплет – использование потока. Этот потокможно запускать, когда апплет становится видимым, и останавливать,когда он невидим. Поток создаёт анимационный эффект повторениемвызова метода paint() и отображением вывода в новой позиции.
Существуют два способа запуска класса в потоке: расширение классаThread и реализация интерфейса Runnable.// пример #1 : расширение класса Thread : Talk.javaclass Talk extends Thread {public void run() {for (int i = 0; i < 8; i++) { System.out.println("Talking");try {Thread.sleep(400);//остановка на 400 миллисекунд }catch (InterruptedException e) {System.out.println("метод sleep() не работает - "+e); }}}}При реализации интерфейса Runnable необходимо определить абстрактный метод run(), который содержится в интерфейсе. Например:64// пример #2 : реализация интерфейса Runnable : TalkWalk.javaclass Walk implements Runnable {public void run() {for (int i = 0; i < 8; i++) { System.out.println("Walking");try { Thread.sleep(300); } catch (InterruptedException e) {System.out.println(“ метод sleep() не работает - ”+e);}}}}public class TalkWalk extends JApplet {Talk talk = new Talk(); //новый потокThread walk = new Thread(new Walk());//новый потокpublic void init() {talk.start();walk.start(); }}Использование двух потоков для объектов классов Talk и Walkприводит к поочередному выводу строк: Talking Walking.При запуске программы объект класса Thread может быть в одномиз четырёх состояний: "новый", "работоспособный", "неработоспособный" и "пассивный".
При создании потока он получает состояние"новый" и не выполняется. Для перевода потока из состояния "новый"в состояние "работоспособный" cледует выполнить метод start(), который вызывает метод run() – основное тело потока. ИнтерфейсRunnable не имеет метода start(), а только единственный метод run().Поэтому для запуска такого потока как Walk следует создать объекткласса Thread и передать поток Walk его конструктору:Thread walk = new Thread(new Walk());Поток переходит в состояние "неработоспособный" вызовом методов suspend(), sleep(), wait() или методов ввода/вывода, которые предполагают задержку.
Поток переходит в "пассивное" состояние, есливызван метод stop() или метод run() завершил выполнение. Послеэтого, чтобы выполнить поток еще раз, необходимо создать новую копию потока. Для задержки потока на некоторое время (в миллисекундах) можно перевести его в режим ожидания с помощью методаsleep().
Метод sleep() генерирует прерывание InterruptedException,которое программа может перехватить. Рассмотрим пример:// пример #3 : остановка потока : SuspendResume.javaimport javax.swing.*;import java.awt.*;class MyThread extends Thread {public void run(){65while (true) {try { sleep(400); } catch (InterruptedException e) {}System.out.println("Thread работает!");}}}public class SuspendResume extends JApplet {MyThread mythread = new MyThread ();public void init(){mythread.start();}public boolean mouseDown(Event evt, int x, int y) {mythread.suspend();System.out.println("Thread остановлен");return(true);}public boolean mouseUp(Event evt, int x, int y) {System.out.println("Thread возобновлен");mythread.resume();return(true);}}Метод suspend() позволяет приостановить выполнение потока, пока не возникло какое-либо событие, например, пока не нажата кнопка.Выполнение возобновляется вызовом метода resume().Потоку можно назначить приоритет от 0 (константа MIN_PRIORITY) до 10 (MAX_PRIORITY) с помощью метода setPriority(),получить приоритет можно с помощью метода getPriority().// пример #4 : установка приоритета : ThreadPriority.javaimport javax.swing.*;class MyThread extends Thread {myThread(String name){ super(name); }public void run(){for (int i = 0; i < 8; i++){ System.out.println(getName() + " " + i);try { sleep(10); }catch (InterruptedException e) {}}}}public class ThreadPriority extends JApplet {MyThread min_thread = new MyThread ("Thread Min");66MyThread max_thread = new MyThread ("Thread Max");MyThread norm_thread = new MyThread ("Thread Norm");public void init(){min_thread.setPriority(Thread.MIN_PRIORITY);max_thread.setPriority(Thread.MAX_PRIORITY);norm_thread.setPriority(Thread.NORM_PRIORITY);min_thread.start(); max_thread.start(); norm_thread.start();}}Поток с более высоким приоритетом может монополизировать вывод на консоль.
Приостановить выполнение потока можно с помощьюметода sleep() класса Thread. Альтернативный способ состоит в вызове метода yield(), который делает паузу и позволяет другим потокамвыполнить свою задачу.// пример #5 : запуск и остановка потоков : InfiniteThread.javaimport java.applet.Applet;public class InfiniteThread extends Applet implements Runnable{Thread myThread;public void init() {System.out.println("в методе init() – старт thread");myThread = new Thread(this);myThread.start();}public void start(){System.out.println("в методе start() – продолжение thread");myThread.resume();}public void stop() {System.out.println("в методе stop() – приостановка thread");myThread.suspend();}public void destroy() {System.out.println("в методе destroy() – уничтожение thread");myThread.resume();myThread.stop();}public boolean mouseDown(java.awt.Event e, int x, int y){System.out.println("число потоков " + myThread.activeCount());return true;}67public void run() {int i = 0;for( ; ; ) { i++;System.out.println("В потоке " + i + " раз");try { myThread.sleep(1000); } catch (InterruptedException e) {}}}}Использование потоков в апплетахОчень часто возникает ситуация, когда много потоков, обращающихся к некоторому общему ресурсу, начинают мешать друг другу.Например, когда один поток читает запись из файла, а другой записывает информацию в файл.