Java — Создать объект по нажатию на кнопку


Содержание

Занятие 10

Обработка событий в Swing

Графический интерфейс пользователя включает в себя не только расположение в окне необходимых элементов управления, но и назначение реакции на пользовательские события. Большая честь действий в оконных программах выполняется в ответ на выбор пользователем команд меню, нажатие кнопок, а иногда даже просто в ответ на ввод нового символа в текстовое поле.

Таким образом, при разработке программы необходимо:

  1. Выявить события, в ответ на которые потребуется реакция программы.
  2. Написать код, реализующий эту реакцию (так называемый обработчик событий).
  3. Связать обработчик события с соответствующим событием.

Первый пункт зависит от логики работы приложения и находится всецело на усмотрении программиста. Обработчик события — это, как правило, обычный метод и ничего особенного в его написании нет.

Паттерн проектирования «наблюдатель»

В разных языках программирования и визуальных библиотеках используются самые различные способы привязки процедуры (метода), которая должна вызываться в ответ на некоторое событие, к самому этому событию. В частности, в Delphi процедура просто должна иметь особое название, состоящее из имени компонента и типа обрабатываемого события.

В библиотеке Swing для привязки обработчика события к вызывающему его компоненту используется паттерн проектирования «наблюдатель».

Паттерны проектирования — это стандартные приемы объектно-ориентированного программирования, позволяющие оптимальным образом справиться с нетривиальными, но часто возникающими в программировании ситуации. Паттерн проектирования описывает классы, которые необходимо ввести для разрешения такой ситуации и взаимодействие между классами. В частности, ранее мы рассматривали паттерн проектирования «итератор», позволяющий обойти все элементы коллекции с помощью двух простейших методов в порядке, скрытом в самом итераторе.

Паттерн проектирования «наблюдатель» применяется, когда один объект должен оповещать другие о произошедших с ним изменениях или внешних воздействиях. Такой объект называется наблюдаемым, а объекты, которые следует оповестить — наблюдателями.

Для того, чтобы подобное взаимодействие было возможным, объект-наблюдатель должен иметь метод (или несколько методов) с заранее определенной сигнатурой (именем и параметрами). Когда с наблюдаемым объектом произойдет ожидаемое событие, он вызовет соответствующий метод у своего наблюдателя. В этом методе и будет запрограммирована реакция на событие.

Для того, чтобы наблюдаемый объект мог вызвать метод наблюдателя, он должен знать о том, что такой наблюдатель существует. Поэтому у наблюдаемого предварительно должен быть вызван специальный метод, регистрирующий его наблюдателя.

Заметим, что в данной схеме один наблюдатель может быть зарегистрирован у нескольких объектов (т.е. одинаково реагировать на изменения в каждом из них), а у одного объекта может быть несколько наблюдателей (т.е. при возникновении события выполняется несколько независимых методов-обработчиков). Это весьма увеличивает гибкость программирования.

Механизм обработки событий библиотеки Swing

В контексте графического интерфейса пользователя наблюдаемыми объектами являются элементы управления: кнопки, флажки, меню и т.д. Они могут сообщить своим наблюдателям об определенных событиях, как элементарных (наведение мышкой, нажатие клавиши на клавиатуре), так и о высокоуровневых (изменение текста в текстовом поле, выбор нового элемента в выпадающем списке и т.д.).

Наблюдателями должны являться объекты классов, поддерживающих специальные интерфейсы (вспомним, что в классе наблюдателя должны быть определенные методы, о которых «знает» наблюдаемый и вызывает их при наступлении события). Такие классы в терминологии Swing называются слушателями.

Интерфейс MouseListener и обработка событий от мыши

Мы рассмотрим технологию написания слушателей на примере слушателей событий мыши.

События от мыши — один из самых популярных типов событий. Практически любой элемент управления способен сообщить о том, что на него навели мышь, щелкнули по нему и т.д. Об этом будут оповещен все зарегистрированные слушатели событий от мыши.

Так например, кнопка для входа в систему из примера в конце предыдущей главы должна реагировать на щелчок по ней, проверяя имя и пароль, введенные пользователем.

Слушатель событий от мыши должен реализовать интерфейс MouseListener. В этом интерфейсе перечислены следующие методы:

public void mouseClicked(MouseEvent event) — выполнен щелчок мышкой на наблюдаемом объекте

public void mouseEntered(MouseEvent event) — курсор мыши вошел в область наблюдаемого объекта

public void mouseExited(MouseEvent event) — курсор мыши вышел из области наблюдаемого объекта

public void mousePressed(MouseEvent event) — кнопка мыши нажата в момент, когда курсор находится над наблюдаемым объектом

public void mouseReleased(MouseEvent event) — кнопка мыши отпущена в момент, когда курсор находится над наблюдаемым объектом

Каждый из этих методов получает параметр типа MouseEvent , через который передается дополнительная информация о возникшем событии. Например, можно получить объект, вызвавший данное событие, командой event.getSource() (не забывайте, что один и тот же слушатель может быть зарегистрирован в нескольких объектах и иногда ему может понадобиться узнать, какой именно из них вызвал данный метод). Метод getPoint() вернет координаты точки, в которой находился курсор мыши, когда было инициировано событие. Метод getClickCount() возвращает число сделанных подряд щелчков (имеет смысл только для mouseClicked() и позволяет особым образом обработать двойной, тройной и т.п. щелчок).

Чтобы обработать нажатие на кнопку, требуется описать класс, реализующий интерфейс MouseListener , причем метод mouseClicked() должен содержать обработчик события. Далее необходимо создать объект этого класса и зарегистрировать его как слушателя интересующей нас кнопки. Для регистрации слушателя используется метод addMouseListener(MouseListener listener) .

Опишем класс слушателя в пределах класса окна SimpleWindow , после конструктора. Обработчик события будет проверять, ввел ли пользователь логин «Иван» (пароль проверять не будем) и выводить сообщение об успехе или неуспехе входа в систему (работа стандартных диалоговых окон обсуждается дальше в этой главе):

class MouseL implements MouseListener < public void mouseClicked(MouseEvent event) < if (loginField.getText().equals( "Иван" )) JOptionPane.showMessageDialog( null , "Вход выполнен" ); else JOptionPane.showMessageDialog( null , "Вход НЕ выполнен" ); >public void mouseEntered(MouseEvent event) <> public void mouseExited(MouseEvent event) <> public void mousePressed(MouseEvent event) <> public void mouseReleased(MouseEvent event) <> >

Мы сделали слушателя вложенным классом класса SimpleWindow , чтобы он мог легко получить доступ к его внутренним полям loginField и passwordField . Кроме того, хотя реально мы обрабатываем только одно из пяти возможных событий мыши, описывать пришлось все пять методов (четыре имеют пустую реализацию). Дело в том, что в противном случае класс пришлось бы объявить абстрактным (ведь он унаследовал от интерфейса пустые заголовки методов) и мы не смогли бы создать объект этого класса. А мы должны создать объект слушателя и прикрепить его к кнопке. Для этого в код конструктора SimpleWindow() необходимо добавить команду:

ok.addMouseListener( new MouseL());

Это можно сделать сразу после команды:

JButton ok = new JButton( «OK» );

Создание слушателей с помощью анонимных классов

Чтобы кнопка ok обрела слушателя, который будет обрабатывать нажатие на нее, нам понадобилось описать новый (вложенный) класс. Иногда вместо вложенного класса можно обойтись анонимным. Как вы помните, анонимный класс не имеет имени и в программе может быть создан только один объект этого класса (создание которого совмещено с определением класса). Но очень часто, как и в нашем примере, слушатель пишется для того, чтобы обрабатывать события единственного объекта — в нашем случае кнопки ok , а значит, используется в программе только однажды: во время привязки к этому объекту. Таким образом, мы можем заменить вложенный класс анонимным. Для этого описание класса MouseL можно просто удалить, а команду

ok.addMouseListener( new MouseL());

ok.addMouseListener( new MouseListener() < public void mouseClicked(MouseEvent event) < if (loginField.getText().equals( "Иван" )) JOptionPane.showMessageDialog( null , "Вход выполнен" ); else JOptionPane.showMessageDialog( null , "Вход НЕ выполнен" ); >public void mouseEntered(MouseEvent event) <> public void mouseExited(MouseEvent event) <> public void mousePressed(MouseEvent event) <> public void mouseReleased(MouseEvent event) <> >);

Новый вариант выглядит более громоздко, чем первый. Злоупотребление анонимными классами может сделать программу плохо читаемой. Однако в результате все действия с кнопкой (создание, настройка ее внешнего вида и команды обработки щелчка по ней) не разнесены, как в случае вложенных классов, а находятся рядом, что облегчает сопровождение (внесение изменений) программы. В случае простых (в несколько строк) обработчиков разумно делать выбор в пользу анонимных классов.

Вообще, можно реализовать интерфейс слушателя в любом классе, добавив к его описанию директиву implements MouseListener и определив в нем необходимые методы. В частности, это может быть сам класс окна SimpleWindow. Но чаще всего пользуются анонимными и вложенными классами (не в последнюю очередь благодаря наличию адаптеров (см. далее).

Класс MouseAdapter

Программа стала выглядеть загроможденной главным образом из-за того, что помимо полезного для нас метода mouseClicked() нам пришлось определять пустые реализации всех остальных, не нужных методов. В принципе, этого можно избежать.

Класс MouseAdapter реализует интерфейс MouseListener , определяя пустые реализации для каждого из его методов. Можно унаследовать своего слушателя от этого класса и переопределить те методы, которые нам нужны.

В результате предыдущее описание слушателя будет выглядеть более компактно:

Общая структура слушателей

Кроме слушателей MouseListener визуальные компоненты Swing поддерживают целый ряд других слушателей (заметим, что в разных компонентах набор возможных слушателей может отличаться).

Каждый слушатель должен реализовывать интерфейс ***Listener , где *** — тип слушателя. Практически каждому из этих интерфейсов (за исключением тех, в которых всего один метод) соответствует пустой класс-заглушка ***Adapter . Каждый метод интерфейса слушателя принимает один параметр типа ***Event , в котором собрана вся информация, относящаяся к событию. Мы не будем подробно рассматривать методы получения этой информации. Как правило их немного и их назначение легко понять, а перечень методов даст контекстная подсказка Eclipse.

Чтобы привязать слушателя к объекту (который поддерживает соответствующий тип слушателей) используется метод add***Listener(***Listener listener) .

Например, слушатель MouseListener должен реализовать интерфейс с таким же именем, которому соответствует класс-заглушка MouseAdapter . Методы этого интерфейса обрабатывают параметр типа MouseEvent , а регистрируется слушатель методом addMouseListener(MouseListener listener) . Мы не будем повторять эту информацию для других типов слушателей, они работают аналогично.

Слушатель фокуса FocusListener

Слушатель FocusListener отслеживает моменты, когда объект получает фокус (то есть становится активным) или теряет его. Концепция фокуса очень важна для оконных приложений. В каждый момент времени в окне может быть только один активный (находящийся в фокусе) объект, который получает информацию о нажатых на клавиатуре клавишах (т.е. реагирует на события клавиатуры), о прокрутке колесика мышки и т.д. Пользователь активирует один из элементов управления нажатием мышки или с помощью клавиши Tab (переключаясь между ними).

Интерфейс FocusListener имеет два метода:

public void focusGained(FocusEvent event) — вызывается, когда наблюдаемый объект получает фокус

public void focusLost(FocusEvent event) — вызывается, когда наблюдаемый объект теряет фокус.

Слушатель колесика мышки MouseWheelListener

Слушатель MouseWheelListener оповещается при вращении колесика мыши в тот момент, когда данный компонент находится в фокусе. Этот интерфейс содержит всего один метод:

public void mouseWheelMoved(MouseWheelEvent event) .

Слушатель клавиатуры KeyListener

Слушатель KeyListener оповещается, когда пользователь работает с клавиатурой в тот момент, когда данный компонент находится в фокусе. В интерфейсе определены методы:

public void mouseKeyTyped(KeyEvent event) — вызывается, когда с клавиатуры вводится символ

public void mouseKeyPressed(KeyEvent event) — вызывается, когда нажата клавиша клавиатуры

public void mouseKeyReleased(KeyEvent event) — вызывается, когда отпущена клавиша клавиатуры.

Аргумент event этих методов способен дать весьма ценные сведения. В частности, команда event.getKeyChar() возвращает символ типа char , связанный с нажатой клавишей. Если с нажатой клавишей не связан никакой символ, возвращается константа CHAR_UNDEFINED . Команда event.getKeyCode() возвратит код нажатой клавиши в виде целого числа типа int . Его можно сравнить с одной из многочисленных констант, определенных в классе KeyEvent : VK_F1 , VK_SHIFT , VK_D , VK_MINUS и т.д. Методы isAltDown() , isControlDown() , isShiftDown() позволяют узнать, не была ли одновременно нажата одна из клавиш-модификаторов Alt, Ctrl или Shift.

Упражнение.

В окне входа в систему добавьте возможность, чтобы при нажатии клавиши Esc в окне ввода логина его содержимое очищалось.

Слушатель изменения состояния ChangeListener

Слушатель ChangeListener реагирует на изменение состояния объекта. Каждый элемент управления по своему определяет понятие «изменение состояния». Например, для панели со вкладками JTabbedPane это переход на другую вкладку, для ползунка JSlider — изменение его положения, кнопка JButton рассматривает как смену состояния щелчок на ней. Таким образом, хотя событие это достаточно общее, необходимо уточнять его специфику для каждого конкретного компонента. В интерфейсе определен всего один метод:

public void stateChanged(ChangeEvent event) .

Слушатель событий окна WindowListener

Слушатель WindowListener может быть привязан только к окну и оповещается о различных событиях, произошедших с окном:

public void windowOpened(WindowEvent event) — окно открылось.

public void windowClosing(WindowEvent event) — попытка закрытия окна (например, пользователя нажал на крестик). Слово «попытка» означает, что данный метод вызовется до того, как окно будет закрыто и может воспрепятствовать этому (например, вывести диалог типа «Вы уверены?» и отменить закрытие окна, если пользователь выберет «Нет»).

public void windowClosed(WindowEvent event) — окно закрылось.

public void windowIconified(WindowEvent event) — окно свернуто.

public void windowDeiconified(WindowEvent event) — окно развернуто.

public void windowActivated(WindowEvent event) — окно стало активным.

public void windowDeactivated(WindowEvent event) — окно стало неактивным.

Слушатель событий компонента СomponentListener

Слушатель ComponentListener оповещается, когда наблюдаемый визуальный компонент изменяет свое положение, размеры или видимость. В интерфейсе четыре метода:

public void componentMoved(ComponentEvent event) — вызывается, когда наблюдаемый компонент перемещается (в результате вызова команды setLocation() , работы менеджера размещения или еще по какой-то причине).

public void componentResized(ComponentEvent event) — вызывается, когда изменяются размеры наблюдаемого компонента.

public void componentHidden(ComponentEvent event) — вызывается, когда компонент становится невидимым.

public void componentShown(ComponentEvent event) — вызывается, когда компонент становится видимым.

Слушатель выбора элемента ItemListener

Слушатель ItemListener реагирует на изменение состояния одного из элементов, входящих в состав наблюдаемого компонента. Например, выпадающий список JComboBox состоит из множества элементов и слушатель реагирует, когда изменяется выбранный элемент. Также данный слушатель оповещается при выборе либо отмене выбора флажка JCheckBox или переключателя JRadioButton , изменении состояния кнопки JToggleButton и т.д. Слушатель обладает одним методом:

Цукерберг рекомендует:  Вакансии Ticketland.ru МТС

public void itemStateChanged(ItemEvent event) .

Универсальный слушатель ActionListener

Среди многочисленных событий, на которые реагирует каждый элемент управления (и о которых он оповещает соответствующих слушателей, если они к нему присоединены), есть одно основное, вытекающее из самой сути компонента и обрабатываемое значительно чаще, чем другие. Например, для кнопки это щелчок на ней, а для выпадающего списка — выбор нового элемента.

Для отслеживания и обработки такого события может быть использован особый слушатель ActionListener , имеющий один метод:

public void actionPerformed(ActionEvent event) .

У использования ActionListener есть небольшое преимущество в эффективности (так, при обработке нажатия на кнопку не надо реагировать на четыре лишних события — ведь даже если методы-обработчики пустые, на вызов этих методов все равно тратятся ресурсы). А кроме того очень удобно запомнить и постоянно использовать один класс с одним методам и обращаться к остальным лишь в тех относительно редких случаях, когда возникнет такая необходимость.

Обработка нажатия на кнопку ok в нашем примере легко переписывается для ActionListener:

Работа с меню в библиотеке Swing

Неотъемлемой частью современных оконных программ является меню, представляющее собой удобно сгруппированный набор команд. Меню бывает двух типов: главное и контекстное. Главное меню располагается вдоль верхней границы окна и содержит команды, относящиеся ко всему приложению (точнее, все команды, которые можно выполнить, работая с данным окном). Контекстное меню вызывается нажатием правой кнопки мышки на конкретном объекте и содержит команды, которые могут быть применены именно к этому объекту.

Создание главного меню

Главное меню окна представлено в Swing классом JMenuBar . По сути своей этот класс представляет собой панель с менеджером расположения BoxLayout (по горизонтали), в которую можно добавлять не только элементы меню, но и что угодно: хоть выпадающие списки, хоть панели с закладками. Однако для удобства пользования программой предпочтительнее использовать «традиционные» возможности меню.

Главное меню должно быть присоединено к окну методом setJMenuBar(JMenuBar menuBar) .

Элементами главного меню являются обычные меню — выпадающие прямоугольные блоки команд — объекты класса JMenu . Конструктор JMenu(String title) принимает один параметр: название меню, которое будет отображаться в строке главного меню. *

Меню, в свою очередь, состоит из пунктов меню, представленных классом JMenuItem . По логике работы пункты меню аналогичны кнопке JButton , то есть, при нажатии на него пользователем выполняется какое-то действие.

У класса JMenuItem есть наследники. Класс JCheckBoxMenuItem по логике работы аналогичен флажку JCheckBox — то есть, прямо в меню можно установить или сбросить какой-либо параметр логического типа. Класс JRadioButtonMenuItem эмулирует переключатель, позволяя выбрать только одну из нескольких альтернатив.

Создать элемент меню можно пустым конструктором JMenuItem либо (что более востребовано) одним из конструкторов, в которые передается текст и/или значок элемента меню: JMenuItem(String text) , JMenuItem(Icon icon) , JMenuItem(String text, Icon icon) . Конечно, в любой момент текст и значок можно сменить методами setText(String text) и setIcon(Icon icon) соответственно.

Элемент добавляется в меню методом add(JMenuItem item) класса JMenu . Чтобы отделить группы взаимосвязанных элементов меню, можно добавить между ними разделитель методом addSeparator() класса JMenu .

Кроме того, в меню можно добавить и другое меню. В этом случае образуется последовательность вложенных друг в друга подменю, что довольно часто встречается в современных программах. Но не следует увлекаться: глубина вложенности более трех уровней скорее всего приведет к неудобствам пользования программой.

Создадим главное меню окна, состоящее из двух подменю: «Файл» и «Правка», причем в меню «Правка» поместим выпадающее подменю. Кроме того, воспользуемся знаниями о менеджере расположения главного меню, чтобы добавить с правого края значок (наподобие того, как это сделано в браузере Internet Explorer).

Обработка команд меню

Как было сказано, каждый элемент меню по сути представляет собой кнопку, поэтому реагирует на те же события и позволяет присоединять к себе тех же слушателей, что и кнопка. * Поэтому мы можем назначить реакцию на команды меню точно также, как делали это выше. Например, чтобы при выборе в меню элемента «Выйти» программа прекращала свою работу, следует заменить в примере команду

fileMenu.add( new JMenuItem( «Выйти» ));

на последовательность команд:

JMenuItem exit = new JMenuItem( «Выйти» ); exit.addActionListener( new ActionListener() < public void actionPerformed(ActionEvent event) < System.exit(0); >>); fileMenu.add(exit);

Командой System.exit(0) прекращается работа текущего приложения.

Создание контекстного меню

Контекстное (или всплывающее) меню реализовано в классе JPopupMenu , очень похожему на класс JMenu . Отличительным методом этого класса является метод show(Component comp, int x, int y) , отображающий меню в точке с заданными координатами относительно границ заданного компонента.

Как уже отмечалось, контекстное меню, как правило, отображается при щелчке правой кнопкой мыши над компонентом. Таким образом, чтобы отобразить меню, требуется добавить к этому компоненту слушателя мыши.

Рассмотрим пример, в котором к уже созданному нами окну добавляется метка с надписью и контекстное меню из двух элементов, связанное с этой меткой. Необходимо добавить в конструктор перед последней командой ( setSize ) следующий код:

label = new JLabel( «КНИЖКА» , new ImageIcon( «1.gif» ), JLabel.RIGHT); JPanel panel = new JPanel(); panel.add(label); popup = new JPopupMenu(); popup.add( new JMenuItem( «Прочитать» )); popup.add( new JMenuItem( «Сжечь» )); label.addMouseListener( new MouseAdapter() < public void mouseClicked(MouseEvent event) < if (SwingUtilities.isRightMouseButton(event)) popup.show(label, event.getX(), event.getY()); >>); setContentPane(panel);

При этом в определении класса окна следует ввести два поля:

JPopupMenu popup; JLabel label;

Это необходимо для того, чтобы анонимный класс-слушатель мог обратиться к метке и к контекстному меню.

Приведенный пример также иллюстрирует применение полезного метода isRightMouseButton(MouseEvent event) , определенного в классе вспомогательных утилит SwingUtilities . Метод получает информацию о событии мыши и отвечает на вопрос, была ли нажата именно правая кнопка мыши. Методы getX() и getY() возвращают координаты курсора мыши относительно наблюдаемого компонента.

Интерфейс Action (действие) и класс AbstractAction

Очень часто одна и та же команда дублируется в графическом интерфейсе в нескольких местах. Например, команда «Копировать» может присутствовать в главном меню окна, в контекстном меню некоторого объекта, а также в виде кнопки на инструментальной панели. Это необходимо для удобства пользования программой. Однако, привязывать ко всем этим объектам (кнопкам и командам меню) одинаковых слушателей довольно утомительно. Более того, все эти команды одинаково должны реагировать на изменения состояния программы: если копирование по каким-то причинам становится невозможным, то все элементы управления, представляющие данную команду, должны сделаться неактивными.

Для упрощения работы в таких ситуациях предусмотрен интерфейс Action . Он собирает в одном месте все, что относится к некоторому действию: обработчик, показатель активности, всплывающую подсказку, значок и т.д.

Интерфейс Action унаследован от интерфейса ActionListener , поэтому его главный метод — actionPerformed(ActionEvent event) . Именно здесь программируется само действие. Но помимо этого посредством метода putValue(String key, Object value) можно задать одно из дополнительных свойств действия. Первый параметр — строковый идентификатор свойства. Он может принимать одно из значений, описанных в константах интерфейса Action . Второй параметр — объект, представляющий собой значение свойства.

Основные свойства интерфейса Action (точнее, соответствующие им константы):

NAME — имя действия,

SMALL_ICON — значок, соответствующий действию,

SHORT_DESCRIPTION — краткое описание действия (для всплывающей подсказки).

Метод setEnabled(boolean enabled) позволяет сделать действие активным или неактивным.

На основе созданного действия можно создавать некоторые элементы управления, передавая это действие в качестве единственного параметра конструктора. К таким элементам управления, в частности, относятся элементы меню и кнопки.

Недостаток интерфейса Action — в нем слишком много вспомогательных абстрактных методов (их семь, в том числе setEnabled() и putValue() ) и программировать их достаточно утомительно. Поэтому обычно используется реализующий данный интерфейс класс AbstractAction , в котором «не заполнен» единственный метод — actionPerformed() , а его все равно необходимо определить для программирования сути действия.

Здесь в окне описаны два внутренних класса-действия, одно из которых — это выход из программы. Объект этого класса, exitAction, является внутренним полем класса-окна и на его основе создается пункт меню и две кнопки. Второй класс-действие активирует и деактивирует объект exitAction (при этом изменяется соответствующий действию текст). Запустите пример и пронаблюдайте за тем, как выглядят и ведут себя объекты на основе Action , а затем внимательно проанализируйте его.

Стандартные диалоговые окна

Класс JOptionPane

Неотъемлемой частью большинства программ являются небольшие диалоговые окна: для вывода пользователю сообщения (например, сообщения об ошибке), для вопроса, ответ на который важен для выполнения текущего действия (например, просьба подтвердить или отменить запрашиваемую операцию). Эти диалоги могут быть запрограммированы вручную на основе класса JFrame . Однако ввиду того, что они являются типичными для многих программ, Swing предоставляет в распоряжение программиста несколько готовых классов для работы с ними.

Чаще всего используется класс JOptionPane , содержащий несколько статических методов, отображающих стандартные диалоги.

Метод showMessageDialog() выводит на экран диалоговое окно, информирующее пользователя. Оно содержит надпись, значок и кнопку ОК. Существует несколько разновидностей этого метода с разными наборами параметров. Самый простой из них showMessageDialog(Component component, Object content) требует указания компонента, над которым должно появиться диалоговое окно и содержимого окна. Чаще всего содержимым окна является некоторая строка, а вместо первого параметра передается null — тогда окно появляется по центру экрана. Более «продвинутый» вариант showMessageDialog(Component component, Object content, String title, int type) позволяет задать также свой заголовок окна и выбрать его тип (влияет на иконку в окне): сообщение об ошибке ( ERROR_MESSAGE ), предупреждение ( WARNING_MESSAGE ), информация ( INFORMATION_MESSAGE ).

Диалоговое окно является модальным. Это значит, что пока пользователь не нажмет в этом окне кнопку OK, программа окажется заблокирована — пользователь не сможет работать с другими окнами.

Пронаблюдаем действие метода на простом примере:


Кнопка button сделана полем класса окна, чтобы можно было получить к ней доступ из анонимного класса-слушателя.

Другое часто используемое диалоговое окно — окно вопроса. В этом окне несколько кнопок, одну из которых пользователь должен нажать. В программу, вызывающую это диалоговое окно, возвращается информация о выборе пользователя, на основе которой и строится дальнейший ход работы программы.

Данное окно отображается методом showConfirmDialog(Component component, Object content) . Параметры этого метода идентичны по смыслу параметрам showMessageDialog() , но в диалоговом окне появится не одна кнопка, а три: «Yes», «No» и «Cancel». Более того, метод возвращает значение, которое можно сравнить с константами YES_OPTION , NO_OPTION и CANCEL_OPTION . Логику работы с этим методом проиллюстрирует пример:

Метод имеет еще четыре разновидности с разным набором параметров, позволяющих изменять заголовок и значок окна, а также набор кнопок.

Класс JFileChooser

Swing содержит готовое окно для выбора файла (полезное, например, для программирования пункта меню Файл Открыть). Объект класса JFileChooser создается простым конструктором без параметров, после чего может выводиться на экран методом showOpenDialog() . Этот метод возвращает результат действий пользователя по выбору файла, который сравнивается с одной из следующих констант:

APPROVE_OPTION — выбор файла прошел успешно. Теперь можно методом getFile() получить выбранный файл.

CANCEL_OPTION — пользователь отменил выбор файла, щелкнув на кнопке Cancel.

ERROR_OPTION — при выборе файла произошла ошибка, либо пользователь закрыл диалоговое окно крестиком.

Метод showSaveDialog() отображает то же самое окно, но теперь оно работает в режиме сохранения. Пользователь выбирает директорию для сохранения файла и может ввести его имя. Метод возвращает результат того же типа, что и showOpenDialog() . Если выбор пути для сохранения прошел успешно, вызов метода getFile() вернут путь, куда пользователь желает сохранить файл.

Следует иметь в виду, что сам класс JFileChooser ничего не открывает и не сохраняет. Он только возвращает путь к выбранному пользователем файлу. А открыть его или сохранить файл в заданном месте должна уже сама программа.

Метод setDialogTitle(String title) позволяет задать окну заголовок.

Java Eclipse пример оконного приложения — создание окна, задание размеров, добавление надписей и кнопок, вывод сообщения

Primary tabs

Forums:

Далее пример урока 8 по программированию на Java.

Это пример содержит 5 классов (в проекте вам надо будет создать пять классов), предварительно создав два пакета пакета.

пакет TestForm

Этот пакет содержит два класса.

класс FormStart (создаёт «рамку», задаёт её размеры и запрашивает холст):

класс MainFormAppearance ( в одном своём методе задаёт внешность холста и возвращает ссылку на холст):

В этом пакете будут расположены 3 класса-действия (действий), которые мы будем «прикреплять» к создаваемым кнопкам (см. класс выше MainFormAppearance)

Класс CsvListener:

класс ParceListener:


Класс TestActionListener:

Swing, слушаем нажатия клавиш

Swing KeyListener, слушаем нажатия клавиш

Для прослушивания нажатий клавиш, существует специальный интерфейс KeyListener:

Каждый метод, реализованный интерфейсом KeyListener, вызывается определенным событием, вместе с которым передается экземпляр KeyEvent. KeyEvent содержит в себе всю информацию о нажатой клавише и о модификаторах, таких как Alt, Ctrl, Shift:

Дополнительно про KeyEvent можно почитать тут.

У каждой клавиши есть свой цифровой код, например, код пробела 32, клавиша вправо имеет код 39. Всегда можно посмотреть эти коды, выполнив команду:

Кроме того, класс KeyEvent содержит коды всех клавиш в статических переменных, все они начинаются на VK_

Можно и нужно использовать эти переменные для сравнения:

Короткие нажатия

Когда дело касается только обработки нажатой клавиши, достаточно поместить необходимый код в метод keyTyped() интерфейса KeyListener.

Длинные одновременные нажатия

Другое дело, когда нам необходимо обрабатывать не только нажатие, но еще и его длительность и скорее всего сразу у нескольких клавиш одновременно. В этом случае приходится вводить дополнительные переменные, на каждую отслеживаемую клавишу:

Такой подход позволяет реализовывать составные действия, например, длительное движение вправо-вверх одновременно. Необходимо правильно отлавливать события с клавиатуры. Когда зажата клавиша, мы получаем событие в метод keyPressed и записываем эту информацию в переменную. С этого момента мы считаем, что клавиша непрерывно нажата. Если клавиша будет отпущена, мы получим событие в метод keyReleased и обновим об этом информацию в переменной.

Некий движок, управляющий нашей программой и живущий в отдельном потоке не слушает нажатия клавиш напрямую. Вместо этого, он работает с переменными, которые мы любезно для него подготовили.

Подключаем слушатель

Остается только повесить наш класс слушателя нажатий на какой-нибудь компонент Swing, например на JFrame:

Живой пример

Перед вами код, реализующий отрисовку змейки. Голова управляется «стрелками».

динамически добавлять JLabel в пользовательский интерфейс в Java по нажатию кнопки, используя один объект

Я пытаюсь создавать ярлыки каждый раз при нажатии кнопки. Расположение этикеток должно быть изменено. Он должен быть выше друг друга при каждом нажатии. Но это не работает. Не создавая ярлык. Я не могу даже создать один JLabel из кода слушателя нажатия кнопки. Но выполнение происходит внутри самого внутреннего оператора «если».

1 ответ

Вызов revalidate и repaint в контейнере после добавления JLabel скажет GUI позиционировать новый компонент и перекрасить контейнер так, чтобы он отображался. например,

В вашем случае повторная проверка не является абсолютно необходимой, поскольку вы не используете менеджер макетов, но все же это хорошая идея, чтобы включить его, так как вы должны использовать менеджеры макетов, поскольку нулевые макеты опасны и хрупки.

Введение в браузерные события

Событие – это сигнал от браузера о том, что что-то произошло. Все DOM-узлы подают такие сигналы (хотя события бывают и не только в DOM).

Вот список самых часто используемых DOM-событий, пока просто для ознакомления:

События мыши:

  • click – происходит, когда кликнули на элемент левой кнопкой мыши (на устройствах с сенсорными экранами оно происходит при касании).
  • contextmenu – происходит, когда кликнули на элемент правой кнопкой мыши.
  • mouseover / mouseout – когда мышь наводится на / покидает элемент.
  • mousedown / mouseup – когда нажали / отжали кнопку мыши на элементе.
  • mousemove – при движении мыши.
Цукерберг рекомендует:  25 IT-профессий будущего, достойных внимания.

События на элементах управления:

  • submit – пользователь отправил форму .
  • focus – пользователь фокусируется на элементе, например нажимает на .

Клавиатурные события:

  • keydown и keyup – когда пользователь нажимает / отпускает клавишу.

События документа:

  • DOMContentLoaded – когда HTML загружен и обработан, DOM документа полностью построен и доступен.

CSS events:

  • transitionend – когда CSS-анимация завершена.

Существует множество других событий. Мы подробно разберём их в последующих главах.

Обработчики событий

Событию можно назначить обработчик, то есть функцию, которая сработает, как только событие произошло.

Именно благодаря обработчикам JavaScript-код может реагировать на действия пользователя.

Есть несколько способов назначить событию обработчик. Сейчас мы их рассмотрим, начиная с самого простого.

Использование атрибута HTML

Обработчик может быть назначен прямо в разметке, в атрибуте, который называется on .

Например, чтобы назначить обработчик события click на элементе input , можно использовать атрибут onclick , вот так:

При клике мышкой на кнопке выполнится код, указанный в атрибуте onclick .

Обратите внимание, для содержимого атрибута onclick используются одинарные кавычки, так как сам атрибут находится в двойных. Если мы забудем об этом и поставим двойные кавычки внутри атрибута, вот так: onclick=»alert(«Click!»)» , код не будет работать.

Атрибут HTML-тега – не самое удобное место для написания большого количества кода, поэтому лучше создать отдельную JavaScript-функцию и вызвать её там.

Следующий пример по клику запускает функцию countRabbits() :

Как мы помним, атрибут HTML-тега не чувствителен к регистру, поэтому ONCLICK будет работать так же, как onClick и onCLICK … Но, как правило, атрибуты пишут в нижнем регистре: onclick .

Использование свойства DOM-объекта

Можно назначать обработчик, используя свойство DOM-элемента on .

К примеру, elem.onclick :

Если обработчик задан через атрибут, то браузер читает HTML-разметку, создаёт новую функцию из содержимого атрибута и записывает в свойство.

Этот способ, по сути, аналогичен предыдущему.

Обработчик всегда хранится в свойстве DOM-объекта, а атрибут – лишь один из способов его инициализации.

Эти два примера кода работают одинаково:

Так как у элемента DOM может быть только одно свойство с именем onclick , то назначить более одного обработчика так нельзя.

В примере ниже назначение через JavaScript перезапишет обработчик из атрибута:

Кстати, обработчиком можно назначить и уже существующую функцию:

Убрать обработчик можно назначением elem.onclick = null .

Доступ к элементу через this

Внутри обработчика события this ссылается на текущий элемент, то есть на тот, на котором, как говорят, «висит» (т.е. назначен) обработчик.

В коде ниже button выводит своё содержимое, используя this.innerHTML :

Частые ошибки

Если вы только начинаете работать с событиями, обратите внимание на следующие моменты.

Функция должна быть присвоена как sayThanks , а не sayThanks() .

Если добавить скобки, то sayThanks() – это уже вызов функции, результат которого (равный undefined , так как функция ничего не возвращает) будет присвоен onclick . Так что это не будет работать.

…А вот в разметке, в отличие от свойства, скобки нужны:

Это различие просто объяснить. При создании обработчика браузером из атрибута, он автоматически создаёт функцию с телом из значения атрибута: sayThanks() .

Так что разметка генерирует такое свойство:

Используйте именно функции, а не строки.

Назначение обработчика строкой elem.onclick = «alert(1)» также сработает. Это сделано из соображений совместимости, но делать так не рекомендуется.

Не используйте setAttribute для обработчиков.

Такой вызов работать не будет:

Регистр DOM-свойства имеет значение.

Используйте elem.onclick , а не elem.ONCLICK , потому что DOM-свойства чувствительны к регистру.

addEventListener

Фундаментальный недостаток описанных выше способов назначения обработчика –- невозможность повесить несколько обработчиков на одно событие.

Например, одна часть кода хочет при клике на кнопку делать её подсвеченной, а другая – выдавать сообщение.

Мы хотим назначить два обработчика для этого. Но новое DOM-свойство перезапишет предыдущее:

Разработчики стандартов достаточно давно это поняли и предложили альтернативный способ назначения обработчиков при помощи специальных методов addEventListener и removeEventListener . Они свободны от указанного недостатка.

Синтаксис добавления обработчика:

Для удаления обработчика следует использовать removeEventListener :

Для удаления нужно передать именно ту функцию-обработчик которая была назначена.

Вот так не сработает:

Обработчик не будет удалён, т.к. в removeEventListener передана не та же функция, а другая, с одинаковым кодом, но это не важно.

Вот так правильно:

Обратим внимание – если функцию обработчик не сохранить где-либо, мы не сможем её удалить. Нет метода, который позволяет получить из элемента обработчики событий, назначенные через addEventListener .

Метод addEventListener позволяет добавлять несколько обработчиков на одно событие одного элемента, например:

Как видно из примера выше, можно одновременно назначать обработчики и через DOM-свойство и через addEventListener . Однако, во избежание путаницы, рекомендуется выбрать один способ.

Существуют события, которые нельзя назначить через DOM-свойство, но можно через addEventListener .

Например, таково событие transitionend , то есть окончание CSS-анимации.

Вы можете проверить это, запустив код в примере ниже. В большинстве браузеров, сработает лишь второй обработчик, но не первый.

Объект события

Чтобы хорошо обработать событие, могут понадобиться детали того, что произошло. Не просто «клик» или «нажатие клавиши», а также – какие координаты указателя мыши, какая клавиша нажата и так далее.

Когда происходит событие, браузер создаёт объект события, записывает в него детали и передаёт его в качестве аргумента функции-обработчику.

Пример ниже демонстрирует получение координат мыши из объекта события:

Некоторые свойства объекта event :

event.type Тип события, в данном случае «click» . event.currentTarget Элемент, на котором сработал обработчик. Значение – обычно такое же, как и у this , но если обработчик является функцией-стрелкой или при помощи bind привязан другой объект в качестве this , то мы можем получить элемент из event.currentTarget . event.clientX / event.clientY Координаты курсора в момент клика относительно окна, для событий мыши.

Есть также и ряд других свойств, в зависимости от типа событий, которые мы разберём в дальнейших главах.

При назначении обработчика в HTML, тоже можно использовать объект event , вот так:

Это возможно потому, что когда браузер из атрибута создаёт функцию-обработчик, то она выглядит так: function(event) < alert(event.type) >. То есть, её первый аргумент называется «event» , а тело взято из атрибута.

Объект-обработчик: handleEvent

Мы можем назначить обработчиком не только функцию, но и объект при помощи addEventListener . В этом случае, когда происходит событие, вызывается метод объекта handleEvent .

Как видим, если addEventListener получает объект в качестве обработчика, он вызывает object.handleEvent(event) , когда происходит событие.

Мы также можем использовать класс для этого:

Здесь один и тот же объект обрабатывает оба события. Обратите внимание, мы должны явно назначить оба обработчика через addEventListener . Тогда объект menu будет получать события mousedown и mouseup , но не другие (не назначенные) типы событий.

Метод handleEvent не обязательно должен выполнять всю работу сам. Он может вызывать другие методы, которые заточены под обработку конкретных типов событий, вот так:

Теперь обработка событий разделена по методам, что упрощает поддержку кода.

Итого

Есть три способа назначения обработчиков событий:


  1. Атрибут HTML: onclick=». » .
  2. DOM-свойство: elem.onclick = function .
  3. Специальные методы: elem.addEventListener(event, handler[, phase]) для добавления, removeEventListener для удаления.

HTML-атрибуты используются редко потому, что JavaScript в HTML-теге выглядит немного странно. К тому же много кода там не напишешь.

DOM-свойства вполне можно использовать, но мы не можем назначить больше одного обработчика на один тип события. Во многих случаях с этим ограничением можно мириться.

Последний способ самый гибкий, однако нужно писать больше всего кода. Есть несколько типов событий, которые работают только через него, к примеру transtionend и DOMContentLoaded . Также addEventListener поддерживает объекты в качестве обработчиков событий. В этом случае вызывается метод объекта handleEvent .

Не важно, как вы назначаете обработчик – он получает объект события первым аргументом. Этот объект содержит подробности о том, что произошло.

Мы изучим больше о событиях и их типах в следующих главах.

Обработка событий

Некоторые программы с применением JavaScript event работают напрямую с вводимыми пользователем данными. Момент возникновения и порядок таких взаимодействий не могут быть предсказаны заранее.

Обработчики событий

Реагировать на нажатие клавиши можно, постоянно считывая ее состояние, чтобы поймать момент нажатия клавиши, прежде чем она снова не будет отпущена.

Именно так обрабатывался ввод данных на примитивных машинах. Более прогрессивным является определение нажатия клавиши и его постановка в очередь. Затем программа может периодически проверять очередь новых событий и реагировать на то, что там находит. В таком случае программа должна не забывать просматривать очередь и делать это часто.

В период от нажатия клавиши и до обнаружения программой этого события, она фактически не отвечает на запросы. Такой подход называется поллингом ( опросом ).

Большинство программистов стараются избегать его, если это возможно.

Самым лучшим способом считается реализация системы, которая дает коду возможность реагировать на события, когда они происходят. Браузеры реализуют ее, предоставляя возможность регистрировать функции обработчиков для конкретных JavaScript event :

Функция addEventListener регистрируется таким образом, что ее второй аргумент вызывается всякий раз, когда происходит событие, описанное первым аргументом.

События и узлы DOM

Каждый обработчик событий браузера регистрируется в контексте. При вызове функции addEventListener она вызывается как метод для всего окна, так как в браузере глобальный диапазон эквивалентен объекту window . Каждый элемент DOM имеет свой собственный метод addEventListener , который позволяет отслеживать события именно в этом элементе:

В данном примере обработчик подключен к узлу кнопки. JavaScript mouse events приводит в действие обработчик, а клик в остальной части документа — нет.

Установив для узла атрибут onclick , мы получим тот же результат. Но узел имеет только один атрибут onclick , поэтому можно зарегистрировать для каждого узла только один обработчик. Метод addEventListener позволяет добавлять любое количество обработчиков. Так мы застрахованы от случайной замены обработчика, который уже был зарегистрирован.

Метод removeEventListener , вызывается с аргументами, аналогичными addEventListener . Он удаляет обработчик:

Чтобы отменить функцию обработчика, мы задаем для нее имя ( например, once ). Так мы передаем ее как в addEventListener , так и в removeEventListener .

Объекты событий

Хотя мы не упоминали об этом в приведенных выше примерах, в функции обработчиков JavaScript event передается аргумент: объект события. Он предоставляет дополнительную информацию о событии. Например, если мы хотим знать, какая клавиша мыши была нажата, нужно получить значение свойства объекта события which :

Информация, хранящаяся в объекте, различается зависимости от типа события. Свойство объекта type всегда содержит строку, идентифицирующую событие (например, « click » или « mousedown «).

Распространение

Обработчики событий ( например, JavaScript touch events ), зарегистрированные для родительских узлов, также будут принимать события, которые происходят в дочерних элементах. Если была нажата кнопка, находящаяся внутри абзаца, обработчики событий абзаца также получат событие click .

Событие распространяется от узла, в котором оно произошло, в родительский узел и в корень документа. После того, как все обработчики, зарегистрированные в конкретном узле, вступили в действие по очереди, возможность реагировать на событие получают обработчики, зарегистрированные для всего окна.

В любой момент обработчик события может вызвать для объекта события метод stopPropagation , чтобы предотвратить распространение события дальше. Это может быть полезно, когда у вас есть кнопка внутри другого интерактивного элемента, и вы не хотите, чтобы при нажатии кнопки активировалось поведение, заданное для клика мышью по внешним элементам.

В следующем примере мы регистрируем обработчики « MouseDown » как для кнопки, так и для абзаца. При клике правой клавишей ( JavaScript mouse events ) обработчик вызывает метод stopPropagation , который предотвращает запуск обработчика абзаца. При нажатии на кнопку другой клавишей мыши запускаются оба обработчика:

Большинство объектов событий имеют свойство target , которое указывает на узел, в котором они возникли. Вы можете использовать это свойство, чтобы случайно не обрабатывать какое-то событие, которое распространяется вверх из узла.

Также можно использовать JavaScript event target , чтобы расширить диапазон события определенного типа. Например, если у вас есть узел, содержащий длинный список кнопок, более удобно зарегистрировать один обработчик клика для внешнего узла и использовать свойство target , чтобы отслеживать, была ли нажата кнопка, а не регистрировать экземпляры обработчика для всех кнопок:

Действия по умолчанию

Со многими событиями связаны действия по умолчанию. Если вы нажмете на ссылку, то перейдете к целевому элементу ссылки. Если нажмете стрелку вниз, браузер прокрутит страницу вниз. Если вы кликните правой клавишей мыши, откроется контекстное меню.

Для большинства типов событий обработчики JavaScript event вызываются до выполнения действий по умолчанию. Если не нужно, чтобы выполнялось поведение по умолчанию, нужно вызвать для объекта события метод preventDefault .

Его использовать для реализации пользовательских сочетаний клавиш или контекстных меню. Или, чтобы переопределить поведение, которое ожидают пользователи. Ниже приводится ссылка, по которой нельзя перейти:

Старайтесь не делать так, если у вас нет на это веских причин.

В зависимости от браузера некоторые события не могут быть перехвачены. В Google Chrome , например, сочетание клавиш ( event keycode JavaScript ) для закрытия текущей вкладки ( Ctrl-W или Command-W ) не может быть обработано с помощью JavaScript .

События клавиш

Когда пользователь нажимает клавишу на клавиатуре, браузер запускает событие « keydown «. Когда он отпускает клавишу, срабатывает событие « keyup «:

Также это событие срабатывает, когда пользователь нажимает и удерживает клавишу, или пока клавиша удерживается. Например, если требуется увеличить скорость персонажа в игре, нажав на клавишу со стрелкой, и снова уменьшить ее, отпустив клавишу, то нужно быть осторожным, чтобы не увеличивать скорость каждый раз, пока клавиша нажата.

В предыдущем примере использовано свойство объекта event keycode JavaScript . С его помощью определяется, какая именно клавиша была нажата или отпущена. Ноне всегда очевидно, как привести числовой код клавиши к фактической клавише.

Для считывания значений клавиш букв и цифр используется код символа Unicode . Он связан с буквой ( в верхнем регистре ) или цифрой, обозначенной на клавише. Метод charCodeAt для строк позволяет получить это значение:

С другими клавишами связаны менее предсказуемые коды клавиш. Лучший способ определить нужный код, это поэкспериментировать. Зарегистрировать обработчик события нажатия клавиши, который фиксирует коды клавиш, которые он получает, и нажать нужную клавишу.

Такие клавиши, как Shift , Ctrl , Alt порождают события, как обычные клавиши. Но при отслеживании комбинаций клавиш также можно определить, нажаты ли эти клавиши, по свойствам событий клавиатуры и JavaScript mouse events : shiftKey , ctrlKey , altKey и metaKey :

События « keydown » и « keyup » предоставляют информацию о фактическом нажатии клавиш. Но что, если нам нужен сам вводимый текст? Получать текст из кодов клавиш неудобно. Для этого существует событие, « keypress «, которое срабатывает сразу после « keydown «. Оно повторяется вместе с « keydown «, пока клавиша нажата. Но только для клавиш, с помощью которых производится ввод символов.

Свойство charCode в объекте события содержит код, который может быть интерпретирован, как код символа Unicode . Мы можем использовать функцию String.fromCharCode , чтобы преобразовать этот код в строку из одного символа.

Узел DOM , в котором происходит событие зависит, от того элемента, который находился в фокусе ввода при нажатии клавиши. Обычные узлы не могут находиться в фокусе ввода ( если не установить для них атрибут tabindex ), но такие элементы, как ссылки, кнопки и поля формы, могут.

Если никакой конкретный элемент не выделен фокусом ввода, то в качестве целевого узла для событий клавиши и JavaScript touch events выступает document.body .

Цукерберг рекомендует:  C#. Быстрый старт. Основы языка C# на примере разработки небольшой игры

Клики мыши

Нажатие клавиши мыши также приводит в действие ряд событий. События « mousedown » и « mouseup » похожи на « keydown » и « keyup «. Они запускаются, когда нажата и отпущена клавиша мыши. Данные события возникают в узлах DOM, на которые был наведен указатель мыши, когда возникло событие.

Для общего узла, к которому относилось как нажатие, так и освобождение клавиши мыши, после события « mouseup » запускается событие « click «. Например, если нажать клавишу мыши на одном пункте, а затем переместить курсор на другой пункт и отпустить кнопку, то событие « click » будет происходить в элементе, который содержит оба эти пункта.

Если два клика возникли близко друг к другу, также запускается событие « dblclick » ( двойной клик ). Оно возникает после второго клика. Чтобы получить точную информацию о месте, где произошло событие мыши, нужно получить значение свойств pageX и pageY , которые содержат координаты события ( в пикселях ) относительно левого верхнего угла документа.

Ниже приведена реализация примитивной программы для рисования. Каждый раз при нажатии мыши в документе ( под курсором ) добавляется точка:

Свойства clientX и clientY подобны pageX и pageY , но они относятся к видимой части документа. Они могут использоваться для сравнения координат мыши с координатами, возвращаемыми функцией getBoundingClientRect .

Движение мыши

Каждый раз, когда перемещается курсов мыши, срабатывает событие « mousemove » из набора JavaScript mouse events . Оно может быть использовано для отслеживания положения мыши. Это применяется при реализации возможности перетаскивания элементов мышью.

В следующем примере программа выводит на экран панель и устанавливает обработчики событий таким образом, что при перетаскивании эта панель становится уже или шире:

Обратите внимание, что обработчик « mousemove » зарегистрирован для всего окна. Даже если во время изменения размеров мышь выходит за пределы панели, мы все равно обновляем ширину панели и прекращаем JavaScript touch events , когда клавиша мыши была отпущена.

Мы должны прекратить изменение размера панели, когда пользователь отпускает клавишу мыши. К сожалению, не все браузеры устанавливают для событий « mousemove » свойство which . Существует стандартное свойство buttons , которое предоставляет аналогичную информацию, но оно также поддерживается не во всех браузерах. К счастью, все основные браузеры поддерживают что-то одно: либо buttons , либо which . Функция buttonPressed в приведенном выше примере сначала пытается использовать свойство buttons , и, если оно не доступно, переходит к which .

Когда курсор мыши наводится или покидает узел, запускаются события « mouseover » или « mouseout «. Они могут использоваться для создания эффектов при наведении курсора мыши, вывода какой-нибудь подписи или изменения стиля элемента.

Чтобы создать такой эффект, недостаточно просто начать его отображение при возникновении события « mouseover » и завершить после события « mouseout «. Когда мышь перемещается от узла к одному из его дочерних элементов, для родительского узла происходит событие « mouseout «. Хотя указатель мыши не покинул диапазон распространения узла.

Что еще хуже, эти JavaScript event распространяются так же, как и другие события. Когда мышь покидает один из дочерних узлов, для которого зарегистрирован обработчик, возникнет событие « mouseout «.

Чтобы обойти эту проблему, можно использовать свойство объекта события relatedTarget . В случае возникновения события « mouseover » оно указывает, на какой элемент был наведен курсор мыши до этого. А в случае возникновения « mouseout » — к какому элементу перемещается указатель. Мы будем изменять эффект наведения мыши только, когда relatedTarget находится вне нашего целевого узла.

В этом случае мы изменяем поведение, потому что курсор мыши был наведен на узел из-за его пределов ( или наоборот ):

Функция isInside отслеживает родительские связи заданного узла или пока не будет достигнута верхняя часть документа ( когда node равен нулю ). Либо не будет найден родительский элемент, который нам нужен.

Эффект наведения гораздо проще создать с помощью псевдоселектора CSS :hover , как показано в следующем примере. Но когда эффект наведения предполагает что-то более сложное, чем просто изменение стиля целевого узла, тогда нужно использовать прием с использованием событий « mouseover » и « mouseout » ( JavaScript mouse events ):

События прокрутки

Каждый раз, когда элемент прокручивается, в нем срабатывает JavaScript scroll event . Его можно использовать для отслеживания того, что в данный момент просматривает пользователь; для отключения анимации, расположенной вне окна просмотра.

В следующем примере мы выводим индикатор прогресса в правом верхнем углу документа и обновляем его, чтобы он по частям заливался другим цветом по мере прокрутки страницы вниз:

Установив для элемента свойство position или fixed , мы получим тот же результат, что и при установке position:absolute . Но так мы также блокируем прокрутку элемента вместе с остальной частью документа. В результате индикатор прогресса будет статически закреплен в верхнем углу. Внутри него находится еще один элемент, размер которого изменяется в соответствии с текущим прогрессом.

В качестве единиц измерения при установке ширины мы используем % , а не рх , чтобы размеры элемента изменялись пропорционально размеру индикатора прогресса.

Глобальная переменная innerHeight содержит высоту окна, которую мы должны вычесть из общей доступной прокручиваемой высоты документа. Нельзя прокручивать окно ниже при достижении нижней части документа. С innerHeight также может использоваться innerWidth . Разделив pageYOffset ( текущую позицию окна прокрутки ) на максимально допустимую позицию прокрутки и умножив на 100, мы получаем процент для индикатора прогресса.

Вызов preventDefault для JavaScript scroll event не предотвращает прокрутку. Обработчик события вызывается только после того, как происходит прокручивание.

События фокуса ввода

Когда элемент находится в фокусе ввода, браузер запускает в нем событие « focus «. Когда фокус ввода снимается, запускается событие « blur «.

Эти два события не имеют распространения. Обработчик родительского элемента не уведомляется, когда дочерний элемент выделяется фокусом ввода.

В следующем примере выводится подсказка для текстового поля, которое в данный момент находится в фокусе ввода:

Объект окна получает события « focus » и « blur «, когда пользователь переходит или покидает вкладку, окно браузера, в котором выводится документ.

Событие загрузки

Когда завершается загрузка страницы, для объектов тела документа и окна возникает JavaScript event «load» . Оно используется для планирования инициализации действий, для которых требуется загрузка всего документа. Не забывайте, что содержимое

Иногда нужно отменить функцию, которую мы запланировали. Это делается путем сохранения значения, возвращаемого функцией setTimeout , и вызова для нее clearTimeout :

Функция cancelAnimationFrame работает так же, как clearTimeout . Она вызывается значением, возвращаемым requestAnimationFrame , чтобы отменить кадр ( если он еще не был вызван ).

Похожий набор функций, setInterval и clearInterval используется для установки таймера, который должен повторять действие каждые X миллисекунд:

Дробление

Некоторые типы событий могут запускаться много раз в течение короткого периода времени ( например, « mousemove » и javascript scroll event ). При обработке таких событий, нужно быть осторожным, чтобы это не происходило очень долго, иначе обработчик будет выполнять действие столько времени, что взаимодействие с документом станет медленным и скачкообразным.

Если нужно сделать что-то нестандартное в таком обработчике, можно использовать setTimeout , чтобы быть уверенными, что это не растянется слишком надолго. Это обычно называют дроблением события. Существует несколько отличающихся друг от друга подходов к дроблению.

В первом примере мы хотим сделать что-то, когда пользователь печатает. Но не хотим делать это после каждого события нажатия клавиши. Когда пользователь быстро печатает, нужно подождать, пока не произойдет пауза. Вместо немедленного выполнения действия в обработчике события мы устанавливаем задержку. Мы также очищаем предыдущую задержку ( если таковая имеется ). Если события происходят через короткие интервалы времени ( меньше, чем установленная нами задержка ), то задержка от предыдущего события отменяется:

Передача неопределенного значения для clearTimeout или его вызов для задержки, которая уже запущена, не даст никакого результата. Нам больше не нужно быть осторожными относительно того, когда его вызывать, мы просто делаем это для каждого события.

Можно использовать иной сценарий, если нужно разделить ответы небольшим промежутком времени. Но чтобы при этом они запускались во время серии событий, а не только после нее. Например, можно отправлять в ответ на события « mousemove » ( JavaScript mouse events ) текущие координаты мыши, но только через каждые 250 миллисекунд:

Заключение

Обработчики событий позволяют обнаруживать и реагировать на события, над которыми мы не имеем прямого контроля. Для регистрации такого обработчика используется метод addEventListener .

Каждое событие относится к определенному типу (« keydown «, « focus » и так далее ), который идентифицирует его. Большинство событий вызывается для конкретного элемента DOM , а затем распространяются на родительские узлы элемента. Это позволяет обработчикам, связанным с этими элементами, обрабатывать их.

Когда вызывается обработчик, ему передается объект события с дополнительной информацией о действии. Этот объект также содержит методы, позволяющие остановить дальнейшее распространение события ( stopPropagation ) или предотвратить обработку события браузером по умолчанию ( preventDefault ).

Нажатие клавиш порождает события « keydown «, « keypress » и « keyup «. Нажатие мыши порождает события « mousedown «, « mouseup » и « click «. Перемещение мыши — « mousemove «, « mouseenter » и « mouseout «.

JavaScript scroll event можно определить с помощью события « scroll «, а смена фокуса — « focus » и « blur «. После завершения загрузки документа для окна возникает событие « load «.

Только одна часть JavaScript программы может работать одновременно. Обработчики событий и другие запланированные скрипты должны дожидаться, когда закончится выполнение других скриптов в очереди.

Данная публикация представляет собой перевод статьи « Handling Events » , подготовленной дружной командой проекта Интернет-технологии.ру

Загрузка информации в JTable по нажатию на кнопку

Разработка настольных приложений на я. /

Swing, AWT & SWT

21 дек 2013 09:04

Есть swing-овое окошко, в нем есть кнопка и табличка. Есть некий класс сущностей, есть список этих сущностей.

Задача такая: по одному нажатию кнопки один раз загрузить список в таблицу и при повторном нажатии не дублировать данные в этой же таблице.

Ниже приведен код, требующий поправки.
В нем как раз сделано так что при каждом нажатии кнопки появляются данные (одни и те же).
А надо сделать так, чтобы они там появлялись один раз .

Подскажите, пожалуйста, как это сделать в моем случае. Подобных примеров особо не нашел в инете.

Java Graphic как дорисовать объект в JPanel при нажатии на кнопку

Как при нажатии на кнопку в интерфейсе дорисовать еще что либо в JPanel с помощью Graphics?

import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main <

public static void main(String[] args) <
// TODO Auto-generated method stub

JFrame myFrame = new JFrame();

GraphicPanel drawPanel = new GraphicPanel();

JButton buttonLentaMinus = new JButton(«Draw more lines»);

динамически добавлять JLabel в пользовательский интерфейс в Java по нажатию кнопки, используя один объект

Я пытаюсь создавать ярлыки каждый раз при нажатии кнопки. Расположение этикеток должно быть изменено. Он должен быть выше друг друга при каждом нажатии. Но это не работает. Не создавая ярлык. Я не могу даже создать один JLabel из кода слушателя нажатия кнопки. Но выполнение происходит внутри самого внутреннего оператора «если».

1 ответ

Вызов revalidate и repaint в контейнере после добавления JLabel скажет GUI позиционировать новый компонент и перекрасить контейнер так, чтобы он отображался. например,

В вашем случае повторная проверка не является абсолютно необходимой, поскольку вы не используете менеджер макетов, но все же это хорошая идея, чтобы включить его, так как вы должны использовать менеджеры макетов, поскольку нулевые макеты опасны и хрупки.

Блог только про Java

Учимся программировать на Java с нуля

Как создать переключатели в Java

В предыдущем примере пользователь мог установить оба флажка, один из них или ни одного. Во многих ситуациях необходимо выбрать только один из предложенных вариантов. Если пользователь установит другой флажок, то предыдущий флажок будет сброшен.

Такую группу флажков часто называют группой переключателей(radio button). Эти кнопки напоминают переключатели диапазонов на радиоприемниках — при нажатии на одной из таких кнопок ранее нажатая кнопка возвращается в исходное состояние.

На рис.1 показан типичный пример окна программы, содержащей группу переключателей. Пользователь может выбрать размер шрифта — Small(Малый), Medium(Средний), Large(Большой) и Extra large(Очень большой). Разумеется, выбрать можно лишь один размер.

Рис.1. Группа переключателей.

Пакет Swing позволяет легко реализовать группы переключателей. Для этого нужно создать для каждой группы по одному объекту ButtonGroup. Затем в группе переключателей необходимо добавить объекты типа JRadioButton. Объект класса ButtonGroup предназначен для того, чтобы отключать ранее выбранный переключатель, если пользователь щелкнул на новой кнопке.

Второй параметр конструктора принимает значение true, если изначально переключатель должен быть включен, и false — если выключен. Отметим, что объект типа ButtonGroup управляет лишь поведением переключателей. Если нужно объединить несколько групп переключателей, их следует поместить в контейнер, например объект класса JPanel.

Рис.2. Флажки опций

Смотрите на рис.1 и рис.2, обратите внимание что переключатели отличаются по внешнему виду от флажков опций. Флажки опций изображают в виде квадратов, причем для установленных флажков внутри имеется галочка, в то время как переключатели имеют круглую форму: включенные — с точкой внутри, а выключенные — без обозначений.

Механизм извещения о наступлении событий, связанных с переключателями, точно такой же, как и для любых других кнопок. Если пользователь включил переключатель, соответствующий объект генерирует событие. В рассматриваемом здесь примере установлен слушатель, задающий конкретный размер шрифта.

Сравните этот обработчик с обработчиком для флажка опций. Каждому переключателю соответствует свой объект-слушатель. Каждый объект-слушатель точно знает, что нужно делать — установить конкретный размер шрифта.

Для флажков ситуация иная. Оба флажка в нашем примере были связаны с одним и тем же слушателем. Он вызывал метод, определяющий текущее состояние обоих флажков.

Можно ли реализовать такой подход для переключателей? Зададим один слушатель, устанавливающий конкретный размер шрифта:

Однако предпочтительнее использовать отдельные объекты-слушатели поскольку они более явно связывают размер шрифта с конкретным переключателем.

В группе может быть выбран только один переключатель. Хорошо бы сразу знать, какой именно, не поверяя каждый переключатель в группе. Поскольку объект класса ButtonGroup управляет всеми переключателями, было бы удобно, если бы он давал нам ссылку на выбранный переключатель. Действительно, в классе ButtonGroup есть метод getSelection(), но этот метод не возвращает ссылку на выбранный переключатель.

Вместо этого он возвращает ссылку на объект класса ButtonModel — модель, связанную с этим переключателем. К сожалению, все методы класса ButtonModel не представляют собой ничего ценного. Интерфейс ButtonModel наследует метод getSelectedObjects() из интерфейса ItemSelectable, возвращающий совершенно бесполезную ссылку null.

Метод getActionCommand() выглядит предпочтительнее, поскольку позволяет определить текстовую строку, связанную с переключателем.

Однако команда в модели этого переключателя снова представляет собой нулевую ссылку null. Только если программист явно задаст команды для каждого переключателя с помощью метода setActionCommand(), установив значение, соответствующее каждой команде, впоследствии можно будет определить команду включенного переключателя с помощью метода buttonGroup.getSelection().getActionCommand().

Ниже представлен полный исходный код программы, позволяющий установить размер шрифта с помощью переключателей:

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих