Java GUI Programming

From Sinfronteras
Revision as of 00:52, 22 June 2019 by Adelo Vieira (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

What is Swing

Swing: ia a GUI widget toolkit for Java. It is part of Oracle's Java Foundation Classes (JFC) – an API (Application programming interface) for providing a graphical user interface (GUI) for Java programs. Swing is currently the main user interface package which is used for creating desktop applications.

  • On the Oracle website you can find a wealth of examples covering everything you will ever need to do using a Swing interface.
  • You can find full tutorials and also API documentation for each component.
  • The Oracle website contains so many examples, it really is worth taking the time to have a look through the website to get a feel for what can be done.


AWT (Abstract Window toolkit):

It's the user-interface widget toolkit preceding Swing. The AWT is part of the Java Foundation Classes (JFC) — the standard API for providing a graphical user interface (GUI) for a Java program. Some elements of this are still used.

Introduction to Swing components

The JFrame can be considered to be base to which every other component is added. The JFrame is basically the entire window before anything has actually been added.

Therefore if we wanted to create a simple interface with a text field and a button we would first need to create a JFrame to hold everything and then we would add the JTextField and the JButton to the JFrame.

Some of the components are:

List of Swing components and how to use them: http://docs.oracle.com/javase/tutorial/uiswing/components/componentlist.html

  • JFrame
    • JPanel
    • JLabel
    • JButton
    • JTextField
    • JTextArea
    • JDialog
    • JMenuBar
      • JMenu
      • JMenuItem
    • JComboBox
    • JCheckBox
    • JRadioButon
    • JTable
    • JList
    • JTree


JTextArea and JTextField

A JTextArea is a GUI/Swing component that provides a way to add a multi-line text area to our GUI.

// Constructs a new empty TextArea with the specified number of rows and columns:
JTextArea(int rows, int columns) 

// Constructs a new TextArea with the specified text displayed:
JTextArea(String text)

// Constructs a new TextArea with the specified text and number of rows and columns:
JTextArea(String text, int rows, int columns)

The JTextField is very similar to the JTextArea. The main difference is that the JTextField is only a single line!

JTextField myField = new JTextField();


Accessing data and setting information on a field

To "get" information from a field, we can use the following:

String myString = myField.getText();

Where myField can be a JTextField or JTextArea.

To "set" the information in a JTextField/JTextArea, we can do:

myField.setText(myString);

The same is similar for many other components.


Loyouts

https://openclassrooms.com/courses/apprenez-a-programmer-en-java/positionner-des-boutons

https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html

  • FlowLayout: A flow layout privides a way to arrange components in a directional flow.
  • GridLayout
  • BorderLayout
  • GridBagLayout
  • CardLayout
  • BoxLayout
  • GroupLayout
  • SpringLayout


Events

An event in Java is an object that is created when something changes within a graphical user interface. If a user clicks on a button, clicks on a combo box, or types characters into a text field, etc., then an event triggers, creating the relevant event object https://www.thoughtco.com/event-2034091


How do we make things happen?

  • In graphical user interfaces things happen and change because of events.
  • During this example we will create a button click event which means a message will be sent internally to say that a specific button has been clicked.
  • For our simple example, we want some text to be printed out to the console once a button has been clicked.
  • In order for this to happen, we need create an event generator and register a listener for the button in question.


Listeners

Listeners have the responsibility to "listen" for changes in program state. That is, to listen to Events.

In others words, the job of the listener is to wait for an event to happen, and once it has happened, to cause an event to happen.


How do we make things happen?

When we create a GUI, we often find a need for different things to happen when our program changes state.

Changing state means that the state of the program has changed. In other words something has happened such as the window has been maximised, minimised, a button has been clicked, etc.

To allow us to gain control over these changes (and allow things to happen when state changes) we implement "listeners" into our program whose responsibility it is to "listen" for changes in program state.

When the state of the program changes, events in the program are triggered, or "fired".

By default, nothing happens when these events are fired. It is up to us to choose how we would like to deal with these events.

To decide when to fire these events, we use Listeners to listen for the events.

So, Listeners are used to allow our program to "listen" for certain events in our program (e.g. when a button has been clicked).

The job of the listener is to wait for an event to happen, and once it has happened, to cause an event to happen.

Listeners come in all different forms for specific tasks.

For example: When a program is closed, we may want to perform a save operation on the data which is on screen (e.g save the text the user has typed to a text file). By default, when the program is closed, nothing would happen. To do the above, we would first need to add a listener to frame to say:

  • When the program is closed, run the save operation.
  • To do this, we would need a listener to listen for the close event. When the user clicks "Close" on the program, the event would be fired.
  • To deal with this event, we add a method which is responsible for the close operation, and is called when the user closes the program.

Another example is when a button is clicked. When it happends an event will be "triggered". So, we will need to register a listener to wait and listen for this event to happen and then it will do what we tell it to do!


There are different Listeners for different purposes, such as:


Window Listeners

Window listeners are used to listen for various events which occur when the current window changes state. Hay tres clases principales:

  • WindowListener defines methods that handle most window events, such as the events for opening and closing the window, activation and deactivation of the window, and iconification and deiconification of the window.
This class defines 7 methods:
  • windowOpened
  • windowClosing
  • windowClosed
  • windowIconified
  • windowDeiconified
  • windowActivated
  • windowDeactivated
  • WindowFocusListener contains methods to detect when the window becomes the focus owner or it loses the focus owner status.
  • WindowStateListener has a single method to detect a change to the state of the window, such as when the window is iconified, deiconified, maximized, or restored to normal.


Window Events are:

  • Opening a window - Showing a window for the first time.
  • Closing a window - Removing the window from the screen.
  • Deactivated window - This window has lost focus. (It is no longer the focus owner)
  • Maximizing the window - Increasing a window's size to the maximum allowable size, either in the vertical direction, the horizontal direction, or both directions.
  • Iconifying a window - Reducing the window to an icon on the desktop.
  • Deiconifying a window - Restoring the window to its original size.
  • Activated window (frame or dialog) - This window is either the focused window, or owns the focused window.
  • Focused window - The window which contains the "focus owner".


Event objects are sent to Window methods once a specific event has been fired, for example:

public void windowOpened(WindowEvent e) {
		System.out.println("windowOpened...");
	}

The code above shows a "windowOpened" method which is called when the window is opened. A WindowEvent object called 'e' is being passed to the method. This object gives us information about where and what caused the event to be fired.


El siguiente is an example of a window listener in action: WindowListenerExample.java

You can see that WindowListenerExample.java implements WindowListener class. This provides a way to implement the methods in the WindowListener class.

Next you will see the line:

addWindowListener(this)

This adds the listener to the current frame and when the state of the current frame changes, the event(s) will be fired and passed to the methods which you have implemented!

WindowListenerExample.java
import javax.swing.JFrame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;


public class WindowListenerExample extends JFrame implements WindowListener {

	public WindowListenerExample() {
		
		setSize(300,300);
		setVisible(true);
		
		addWindowListener(this);
		
		repaint();
		validate();
	}
	
	public static void main(String[] args) {
          new WindowListenerExample();
	}
	
	@Override
	public void windowOpened(WindowEvent e) {
		System.out.println("windowOpened...");
	}
	
	@Override
	public void windowActivated(WindowEvent e) {
		System.out.println("windowActivated...");
	}
	
	@Override
	public void windowDeactivated(WindowEvent e) {
		System.out.println("windowDeactivated...");
	}
	
	@Override
	public void windowIconified(WindowEvent e) {
		System.out.println("windowIconified...");
	}
	
	@Override
	public void windowDeiconified(WindowEvent e) {
		System.out.println("windowDeiconified...");	
	}

	@Override
	// Called in response to a user request for the listened-to window to be closed
	public void windowClosing(WindowEvent e) {
	     System.out.println("windowClosing...");	
	}
	
	@Override
	// Called just after the listened-to window has closed.
	public void windowClosed(WindowEvent e) {
		System.out.println("windowClosed...");
	}

}


Key Listeners

The following example prints all related information about the KeyEvent which has just been fired.

If we want to get useful information about this, we need to further process the KeyEvent code.

El siguiente código generaba errores cuando lo copié como lo colocó el Prof. en las diapositivas. Eclipse sugirió add unimplemented methods. Lo hice y se agregaros estos dos métodos:

.
        @Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
	}

Luego el código corrió creo que correctamente.

KeyListenerExample
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;


public class KeyListenerExample extends JFrame implements KeyListener {
      
      public KeyListenerExample(){
            setSize(300,300);
            
            JPanel p = new JPanel();
                  JTextField typingArea = new JTextField(20);
                        typingArea.addKeyListener(this);
                  p.add(typingArea);
            this.add(p);
            
            setVisible(true);
      }
      
      private void displayInfo(KeyEvent e, String keyStatus){
            System.out.println(e);
      }
      
      public static void main(String[] args) {
            new KeyListenerExample();
      }
      
      @Override
      public void keyTyped(KeyEvent e) {
            displayInfo(e, "KEY PRESSED: ");
      }

      @Override
      public void keyPressed(KeyEvent e) {
            // TODO Auto-generated method stub
      }

      @Override
      public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub
      }
}


Mouse Listeners

Mouse events notify when the user uses the mouse (or similar input device) to interact with a component.

Mouse events occur when the cursor enters or exits a component's onscreen area and when the user presses or releases one of the mouse buttons.

To use the mouse listener we implement MouseListener.


Example 1


JFrame

In the example below, this is a very simple GUI using Java. The most important step here is extending the JFrame. This turns our class into a JFrame that we can see.

En un sentido práctico, el JFrame representa nuestra primera ventana. Dentro de ésta podremos agregar todas las ventanas y opciones que queramos.

GUITest/src/GUIaFirstExample.java
import javax.swing.JFrame;


public class GUIaFirstExample extends JFrame{
	
	public GUIaFirstExample(){
		this.setSize(500,500);
		this.setVisible(true);
	}
	
	public static void main(String[] args){
		// TODO Auto-generated method stub
		new GUIaFirstExample();
	}
}


FlowLayout - JButton

En el siguiente código hemos ajustado el Layout del Frame. El Layout define la organización de los elementos que serán incorporados al Frame. En este primer ejemplo configurado un FlowLayout en nuestro JFrame. The FlowLayout is a very simple layout manager that simply places each component in a line from left to right on the JFrame.

GUITest/src/GUIbSecondExample.java
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.FlowLayout;


public class GUIbSecondExample extends JFrame {
	
	public GUIbSecondExample() {
		this.setSize(500,500);
		this.setVisible(true);
		this.setLayout(new FlowLayout());               // Set the layout of the JFrame
		
		JButton test = new JButton( "Sample Text" );    // Making the button
		
		this.add(test);                                 // Adding the button to the JFrame
		
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new GUIbSecondExample();
		
	}
	
}


ActionListener - actionPerformed

Although we have buttons added to the JFrame, if we want to respond to clicks, we must add the implements ActionListener.

public void actionPerformed(). This is the method that will be used to handle click events that are fired

Refreshing the page: Whenever we add new buttons or components to a JFrame, when the program is run sometimes it will not be updated and show the correct GUI. To ensure that after we added components to a JFrame that we always see the correct output, we can call the validate() and repaint() method after the components have been added. This tells the JFrame to refresh and ensure that everything on the screen is correct.

GUITest/src/GUIcActionListener.java
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class GUIcActionListener extends JFrame implements ActionListener {
	
	public GUIcActionListener() {
		this.setSize(500,500);
		this.setVisible(true);
		this.setLayout(new FlowLayout());
		
		JButton test = new JButton("Sample Text");    // Making the button
		
		test.addActionListener(this);                 // Turn the listening on
		test.setActionCommand("test");                // Give it an ID
		
		this.add(test);                               // Adding the button to the JFrame
		
		// This tells the JFrame to refresh after we added components (ver nota arriba):
		validate();
		repaint();
		
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new GUIcActionListener();
		
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("test button clicked!");
		
	}
	
}


JMenuBar - JMenu - JMenuItem

In Java, the "menu" across the top of the program is called a JMenuBar.

GUITest/src/GUIeJMenuBar.java
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class GUIeJMenuBar extends JFrame{
      
      public GUIeJMenuBar() {
            
            this.setVisible(true);
            this.setTitle("Notepad");
            this.setSize(500,500);
            
            
            // Make the bar for the menu
            JMenuBar bar = new JMenuBar();
            this.setJMenuBar(bar);
            
            
            // First JMenu
            JMenu file = new JMenu("File");
            bar.add(file);
            
            JMenuItem open = new JMenuItem("Open");
            file.add(open);
            
            JMenuItem close = new JMenuItem("Close");
            file.add(close);
            
            
            // Second JMenu
            JMenu about = new JMenu("About");
            bar.add(about);
            
            JMenuItem aboutus = new JMenuItem("About us");
            about.add(aboutus);
            
            JMenuItem moreinfo = new JMenuItem("More info");
            about.add(moreinfo);
            
            
            repaint();
            
      }
      public static void main(String[] args) {
            // TODO Auto-generated method stub
            new GUIeJMenuBar();
      }
      
}


JPanel - GridLayout

JPanel class provides a container for adding other components:

JPanel p1 = new JPanel();
p1.setLayout(new FlowLayout());
.
.
.
// Agregamos Panel 1 (p1) a nuestro JFrame:
this.add(p1);

We can style the JPanel if we want:

panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));


The GridLayout class is a layout manager that lays out a container's components in a rectangular grid:

GridLayout gridl = new GridLayout(2,2);    // GridLayout(#rows,#columns)
this.setLayout(gridl);


GUITest/src/GUIfGridLayout.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;


public class GUIfGridLayout extends JFrame{

	public GUIfGridLayout(){
		
		this.setSize(600,600);
		this.setVisible(true);
		
		// // Layout for the overall Jframe
		GridLayout gridl = new GridLayout(2,2);
		this.setLayout(gridl);
		
		
		
		// // Panel 1 - with its own layout
		JPanel p1 = new JPanel();
		p1.setLayout(new FlowLayout());
		
		JButton button1 = new JButton("Uno");
		p1.add(button1);
		
		JButton secondButtonOnPanel = new JButton("Segundo boton");
		p1.add(secondButtonOnPanel);
		
		// Agregamos Panel 1 (p1) a nuestro JFrame
		this.add(p1);
		
		
		
		// // Panel 2
		JPanel p2 = new JPanel();
		
		JButton button2 = new JButton("Dos");
		p2.add(button2);
		
		// Agregamos ps a nuestro JFrame
		this.add(p2);
		

		
		// // Botones directamente sobre el JFrame
		JButton button3 = new JButton("Tres");
		this.add(button3);
		
		JButton button4 = new JButton("Cuatro");
		this.add(button4);
				
	}

	public static void main(String[] args){
		// TODO Auto-generated method stub
         new GUIfGridLayout();
	}

}


BorderLayout

a BorderLayout object has five areas. These areas are specified by the BorderLayout constants:

  • PAGE_START
  • PAGE_END
  • LINE_START
  • LINE_END
  • CENTER
BorderLayout
GUITest/src/GUIgBorderLayout.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JButton;


public class GUIgBorderLayout extends JFrame {
	
	public GUIgBorderLayout() {
		
		this.setVisible(true);
		this.setSize(600,600);
		this.setLayout(new BorderLayout());
		
		JPanel top = new JPanel();
		    JButton clickme = new JButton("Click me");
		    top.add(clickme);
		    
		    JButton anotherclick = new JButton("Other");
		    top.add(anotherclick);
		    this.add(top, BorderLayout.PAGE_START);
		
		JPanel bottom = new JPanel();
	            JButton bottomButton = new JButton("Bottom Button");
		    bottom.add(bottomButton);
		    this.add(bottom, BorderLayout.PAGE_END);
		
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
         new GUIgBorderLayout();
	}

}


Dialog with JOptionPane

https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html

JOptionPane.showMessageDialog(frame, "Eggs are not supposed to be green.");


import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.ImageIcon;

public class GUIiDialog extends JFrame {
	
	public GUIiDialog() {
		String imagepath="/home/adelo/1-disco_local/1-mis_archivos/1-pe/1-ciencia/"
		+ "2-computacion/3-mediawiki/sinfronteras/pangea_day1-redim.png";
		JOptionPane.showMessageDialog(this,                 // Reference to current frame, or this
			"Un proyecto SinFronteras",                 // Message
			"JOptionPane custom dialog",                // Title			
			JOptionPane.INFORMATION_MESSAGE,            // Style of icon we want to use
			new ImageIcon(imagepath));
	}
	
	public static void main(String[] args) {
		new GUIiDialog();
	}
	
}

Icons used by JOptionPane:

  • INFORMATION_MESSAGE
  • QUESTION_MESSAGE
  • WARNING_MESSAGE
  • ERROR_MESSAGE
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.JOptionPane;
import javax.swing.ImageIcon;


public class GUIiDialog extends JFrame implements ActionListener{
	
	public GUIiDialog() {
		this.setSize(500,500);
		this.setVisible(true);
		this.setLayout(new FlowLayout());
		
		// First button
		JButton test = new JButton("Dialog wiht my own image");        // Making the button
		test.addActionListener(this);                                  // Turn the listening on
		test.setActionCommand("test");                                 // Give it an ID
		this.add(test);                                                // Adding the button to the JFrame
		
		// Second button
		JButton test2 = new JButton("Multiple Buttons on a Dialog");
		test2.addActionListener(this);
		test2.setActionCommand("test2");
		this.add(test2);
		
		validate();
		repaint();
		
	}
	
	public static void main(String[] args){
		// TODO Auto-generated method stub
		new GUIiDialog();
	}	
	
	@Override
	public void actionPerformed(ActionEvent e){
		// TODO Auto-generated method stub
		if(e.getActionCommand().equals("test")){
			String imagepath="/home/adelo/1-disco_local/1-mis_archivos/1-pe/1-ciencia/"
				+ "2-computacion/3-mediawiki/sinfronteras/pangea_day1-redim.png";
			JOptionPane.showMessageDialog(this,
				"Your RSS feed has been published", 
			    "RSS Feed Published", 
			    JOptionPane.ERROR_MESSAGE,  // *
	        	new ImageIcon(imagepath));
			
		}
		
		else if(e.getActionCommand().equals("test2")){
			Object[] options = {"Yes, please","No, thanks","No eggs, no ham!"};
				int n = JOptionPane.showOptionDialog(this,
				"Would you like some green eggs to go with that ham?",
				"A silly question",
				JOptionPane.YES_NO_CANCEL_OPTION,
				JOptionPane.QUESTION_MESSAGE,
				null,
				options,
				options[2]);
				
		}
		
	}

}
// * INFORMATION_MESSAGE, QUESTION_MESSAGE, WARNING_MESSAGE, ERROR_MESSAGE
//   (No user ImageIcon si queremos que estas opciones tengan efecto)


Wireframes & Planning

Le wireframe ou maquette fonctionnelle est un schéma utilisé lors de la conception d'une interface pour définir les zones et composants qu'elle doit contenir. À partir d'un wireframe peut être réalisée l'interface proprement dite par un graphiste. La démarche de recourir à des wireframes s'inscrit dans une recherche d'ergonomie. Elle est surtout utilisée dans le cadre du développement logiciel et des sites et applications Web. Le wireframe consiste concrètement en un croquis, un collage papier ou un schéma numérique.

  • When we need to use a design pattern, putting in thought at an early stage such as the planning state of an application is the best as you can easily decide what the interactions between each of the MVC components will be.
  • When developing wireframes for an application, there is no single standard that is always followed. Developers all have their own approaches when they want to design how an application front end and back end will work.
  • The idea is to minimise the amount of confusion during the development process by creating detailed diagrams about each of the different screens which will be shown to the user.
  • Remember, the developer's job is to build and time costs money. Our main aim during the planning stage and designing the wireframes is to remove as much confusion as possible and never leave the developer asking questions such as "What does this button do?" or "What GUI component should this be?"
  • The less questions the developer asks, the faster the software will be developed.
  • Our main aim is to get the client to sign off on the mockup drawings that we have created and ensure they know that what we show them is exactly what they will get.
  • If they ask for any more alterations, we can tell them that it is beyond the original agreed upon specification!
  • If you give a developer your Wireframe, they should be able to start creating code with little hassle. This is our main objective
  • Our wireframes should include information such as:
    • What the layout will be
    • What components will be used
    • What text the user will see
    • What happens when we click a button or follow a link
    • What error messages the user will get
    • What validation will be applied.
  • The more detail you add the better! There is no single right way to do this, you can go as simple as Google Draw or use a piece of software that was designed for the job such as https://moqups.com/ or http://site.mockito.org/

Let’s look at a very simple wireframe for a login page, with an outline of the different pieces of information which will be included in the diagrams:

Very simple Wireframe for a login page. Additional information can also be added to the wireframes such as the type of components that will be used. E.g., JTextField, JTextArea or Button.