Adding events to Swing Components can be an annoying task, especially for Java beginners. Swing-Events with Annotations was designed to facilitate this task, for both expert and beginner programmers, allowing them to focus on business logic and not on Controllers. Controllers for Swing components can be difficult to manage or understand, Swing-Events offer classes to standardize several Listeners and events used by these components.
Listener
Swing-Events also offer a simple solution to add Listeners to Swing components tagging one or more methods with an Annotation that includes a source component and an event class supported by this.
Many standalone applications use Swing Components and their development can take a long time for solving the implementation of events. Swing-Events apply a Command Design Pattern partially that simplifies the using and the implementation of Listeners for Swing components and helps reduce the time of development. Swing-Events, in contrast to EventBus or events-on-fire, add Listeners to Swing Components dynamically with Annotations located in each method supporting multiple Swing Components, Listeners, and Events.
Swing-Events simplify the events call. For example, to create a typical call for a Swing component like a JButton, an ActionListener should be added:
JButton
ActionListener
final JLabel messageLabel = new JLabel(); JButton action1Button = new JButton("Action 1"); action1Button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 1 from JButton"); } });
The previous example is easy to understand because there is a single JButton component. However, it can be complex when more JButtons are included in the application. Either adding an ActionListener for each JButton or just one ActionListener for all JButtons can be confusing as well as can mix up the GUI (View) with the events (Controller). It is difficult to maintain or scale. Using Swing-Events you get the following:
JLabel messageLabel = new JLabel(); JButton action1Button = new JButton("Action 1"); @SwingEvent(sources="action1Button") public void invokeActionPerformed1() { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 1 from JButton"); }
Swing-Events is able to link several components to a common method when they implement the same Listener:
JLabel messageLabel = new JLabel(); JButton action1Button = new JButton("Action 1"); JButton action2Button = new JButton("Action 2"); @SwingEvent(sources={"action1Button","action2Button"}) public void invokeActionPerformed1() { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 1 from JButton1 or JButton2"); }
It is possible to link several methods to one or more components too:
JLabel messageLabel = new JLabel(); JButton action1Button = new JButton("Action 1"); JButton action2Button = new JButton("Action 2"); @SwingEvent(sources={"action1Button","action2Button"}) public void invokeActionPerformed1() { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 1 from JButton1 or JButton2"); } @SwingEvent(sources="action1Button") public void invokeActionPerformed2() { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 2 from JButton1"); }
To retrieve the source event object, this can be included as param in the annotated method:
JLabel messageLabel = new JLabel(); JButton action1Button = new JButton("Action 1"); @SwingEvent(sources="action1Button") public void invokeActionPerformed1(ActionEvent e) { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 1 from " + e.getSource()); }
To define a Listener Command or Events ID, they should be included into the Annotation (default Listener command is ActionCommand.class but it can be adjusted according to the Swing Component - see attached table):
JLabel messageLabel = new JLabel(); JButton action1Button = new JButton("Action 1"); @SwingEvent(sources="action1Button", command=ActionCommand.class, eventIds=ActionEvent.ACTION_PERFORMED) public void invokeActionPerformed1() { // Display message in JLabel. messageLabel.setText("Invoking ActionPerformed 1 from JButton"); }
Below there are other examples using Swing-Events (they are included in the demo):
JLabel messageLabel = new JLabel(); JFrame View = new JFrame(); // Simple JFrame Listener for the WindowClosing event. @SwingEvent(sources="View", command=WindowCommand.class, eventIds=WindowEvent.WINDOW_CLOSING) public void invokeWindowClosingAndClosed() { messageLabel.setText("Invoking WindowClosing from JFrame"); }
JLabel messageLabel = new JLabel(); // Muliple Events Id for the same Listener Command. @SwingEvent(sources="trayIcon", command=MouseCommand.class, eventIds={MouseEvent.MOUSE_PRESSED,MouseEvent.MOUSE_RELEASED}) public void invokeMousePressedAndReleasedFromTrayIcon(MouseEvent e) { if (e.isPopupTrigger()) { messageLabel.setText("Invoking MousePressed and MouseReleased from TrayIcon " + "(Position: " + e.getX() + "," + e.getY() + ")"); } }
JLabel messageLabel = new JLabel(); // Create a TableModel to display a data model on a JTable. DefaultTableModel tableModel = new DefaultTableModel( new Object [][]{null, null, null}, new String [] {"Title 1", "Title 2", "Title 3"}); JTable table = new JTable(tableModel); ListSelectionModel tableRowSelectionModel = table.getSelectionModel(); // Retrieve ListSelectionModel from JTable firing the valueChange event when a row is selected. @SwingEvent(sources="table", command=ListSelectionCommand.class) public void invokeRowValueChanged() { messageLabel.setText("Invoking ValueChanged from Row ListSelectionModel " + "(Index: " + tableRowSelectionModel.getLeadSelectionIndex() + ")"); }
JLabel messageLabel = new JLabel(); JFrame View = new JFrame(); JRootPane rootPane = View.getRootPane(); // Close application when the Escape key is pressed with the new KeyStrokeCommand Listener. // KeyStrokeCommand supports keys & modifiers (alt, shift, control, meta, altGraph or combined) @SwingEvent(sources="rootPane", command=KeyStrokeCommand.class, eventIds={JComponent.WHEN_IN_FOCUSED_WINDOW, KeyEvent.VK_ESCAPE}) public void invokeActionPerformedFromViewWithEscapeKey() { messageLabel.setText("Invoking actionPerformed from View with the Escape key."); }
Swing-Events support several components that are shown in the next table:
Swing-Events apply Command Design Pattern partially. It offers a Command interface which makes it easier to construct general components to execute method calls. Every Concrete Command object implements a defined Listener from the Java API for Swing Components. Swing-Events include:
This is the classes diagram for the project:
Besides, this project includes a simple demo using annotations based on the MVC architecture. MVC (Model-View-Controller) is an architecture pattern separating information from its processing. For the demo, MVC is represented by three classes:
Listeners