Difference between revisions of "Java"

From Sinfronteras
Jump to: navigation, search
(Design patterns in code)
(GUI Programming)
Line 168: Line 168:
  
 
There is very little content that is needed to make the Jar file run. Inside of this file, you can see that the Main-Class attribute is set to the name of the class file that we want to run when the Jar is double clicked. In the case of this project, the class file that we want to run is called '''Main.class''', so the title Main is used as the value for this attribute. If your class was called MyProgram.class, this would be set to MyProgram.
 
There is very little content that is needed to make the Jar file run. Inside of this file, you can see that the Main-Class attribute is set to the name of the class file that we want to run when the Jar is double clicked. In the case of this project, the class file that we want to run is called '''Main.class''', so the title Main is used as the value for this attribute. If your class was called MyProgram.class, this would be set to MyProgram.
 
==GUI Programming==
 
'''GUI''' stands for Graphical User Interface. The use of pictures rather than just words to represent the input and output of a program.
 
 
'''A Bit of History:'''
 
* Windowing systems started with the first real-time graphic display systems for computers, namely the SAGE Project and Ivan Sutherland's Sketchpad (1963).
 
... Se habla de esto en 3-GUI Programming Lecture 1 Introduction.pdf, no creo que sea importante...
 
 
 
'''Swing:'''
 
 
It's 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.
 
 
<br />
 
===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
 
 
<br />
 
====JTextArea and JTextField====
 
A JTextArea is a GUI/Swing component that provides a way to add a multi-line text area to our GUI.
 
 
<syntaxhighlight lang="java">
 
// 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)
 
</syntaxhighlight>
 
 
The JTextField is very similar to the JTextArea. The main difference is that the JTextField is only a single line!
 
<syntaxhighlight lang="java">
 
JTextField myField = new JTextField();
 
</syntaxhighlight>
 
 
<br />
 
=====Accessing data and setting information on a field=====
 
To "get" information from a field, we can use the following:
 
<syntaxhighlight lang="java">
 
String myString = myField.getText();
 
</syntaxhighlight>
 
 
Where myField can be a '''JTextField''' or '''JTextArea'''.
 
 
To "set" the information in a JTextField/JTextArea, we can do:
 
<syntaxhighlight lang="java">
 
myField.setText(myString);
 
</syntaxhighlight>
 
 
The same is similar for many other components.
 
 
<br />
 
===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
 
 
<br />
 
===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.
 
 
<br />
 
===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:
 
* [[Java#Window Listeners|Window listeners]] which deal with window related operations
 
* [[Java#Key Listeners|Key listeners]] which deal with keyboard related key presses
 
* [[Java#Mouse Listeners|Mouse listeners]] which deal with clicks, cursor movements, etc.
 
 
<br />
 
====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:'''
 
 
<syntaxhighlight lang="java">
 
public void windowOpened(WindowEvent e) {
 
System.out.println("windowOpened...");
 
}
 
</syntaxhighlight>
 
 
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:
 
<syntaxhighlight lang="java">
 
addWindowListener(this)
 
</syntaxhighlight>
 
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
 
<syntaxhighlight lang="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...");
 
}
 
 
}
 
</syntaxhighlight>
 
 
<br />
 
====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:
 
 
<syntaxhighlight lang="java">
 
.
 
        @Override
 
public void keyPressed(KeyEvent e) {
 
// TODO Auto-generated method stub
 
}
 
 
@Override
 
public void keyReleased(KeyEvent e) {
 
// TODO Auto-generated method stub
 
}
 
</syntaxhighlight>
 
 
Luego el código corrió creo que correctamente.
 
 
KeyListenerExample
 
<syntaxhighlight lang="java">
 
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
 
      }
 
}
 
</syntaxhighlight>
 
 
<br />
 
====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'''.
 
 
<br />
 
===Example 1===
 
 
<br />
 
====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.
 
 
{{#var:codespath}}GUITest/src/GUIaFirstExample.java
 
<syntaxhighlight lang="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();
 
}
 
}
 
</syntaxhighlight>
 
 
<br />
 
====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.
 
 
{{#var:codespath}}GUITest/src/GUIbSecondExample.java
 
<syntaxhighlight lang="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();
 
 
}
 
 
}
 
</syntaxhighlight>
 
 
<br />
 
====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.
 
 
{{#var:codespath}}GUITest/src/GUIcActionListener.java
 
<syntaxhighlight lang="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!");
 
 
}
 
 
}
 
</syntaxhighlight>
 
 
<br />
 
====JMenuBar - JMenu - JMenuItem====
 
 
In Java, the "menu" across the top of the program is called a '''JMenuBar'''.
 
 
{{#var:codespath}}GUITest/src/GUIeJMenuBar.java
 
<syntaxhighlight lang="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();
 
      }
 
     
 
}
 
</syntaxhighlight>
 
 
<br />
 
====JPanel - GridLayout====
 
 
'''JPanel''' class provides a container for adding other components:
 
<syntaxhighlight lang="java">
 
JPanel p1 = new JPanel();
 
p1.setLayout(new FlowLayout());
 
.
 
.
 
.
 
// Agregamos Panel 1 (p1) a nuestro JFrame:
 
this.add(p1);
 
</syntaxhighlight>
 
 
We can style the JPanel if we want:
 
<syntaxhighlight lang="java">
 
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
 
</syntaxhighlight>
 
 
 
The '''GridLayout class''' is a layout manager that lays out a container's components in a rectangular grid:
 
<syntaxhighlight lang="java">
 
GridLayout gridl = new GridLayout(2,2);    // GridLayout(#rows,#columns)
 
this.setLayout(gridl);
 
</syntaxhighlight>
 
 
 
{{#var:codespath}}GUITest/src/GUIfGridLayout.java
 
<syntaxhighlight lang="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();
 
}
 
 
}
 
</syntaxhighlight>
 
 
<br />
 
====BorderLayout====
 
a BorderLayout object has five areas. These areas are specified by the BorderLayout constants:
 
* PAGE_START
 
* PAGE_END
 
* LINE_START
 
* LINE_END
 
* CENTER
 
 
[[File:BorderLayout.png|500px|thumb|center|BorderLayout]]
 
 
{{#var:codespath}}GUITest/src/GUIgBorderLayout.java
 
<syntaxhighlight lang="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();
 
}
 
 
}
 
</syntaxhighlight>
 
 
<br />
 
====Dialog with JOptionPane====
 
https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
 
 
<syntaxhighlight lang="java">
 
JOptionPane.showMessageDialog(frame, "Eggs are not supposed to be green.");
 
</syntaxhighlight>
 
 
 
<syntaxhighlight lang="java">
 
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();
 
}
 
 
}
 
</syntaxhighlight>
 
 
Icons used by JOptionPane:
 
* INFORMATION_MESSAGE
 
* QUESTION_MESSAGE
 
* WARNING_MESSAGE
 
* ERROR_MESSAGE
 
 
<syntaxhighlight lang="java">
 
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)
 
</syntaxhighlight>
 
 
<br />
 
===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:
 
 
[[File:Wireframe_for_a_login_page.png|800px|thumb|center|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.]]
 
 
<br />
 
  
 
==Connecting to a MySQL database using Java==
 
==Connecting to a MySQL database using Java==

Revision as of 15:57, 9 June 2019

Path de los códigos:

Variable definida con:
{{#vardefine:codespath|/home/adelo/1-disco_local/.archivos_programas/eclipse-workspace/}}

Para usar la variable:
{{#var:codespath}}

Instalación de Java

Installing the Default OpenJDK

http://ubuntuhandbook.org/index.php/2018/11/how-to-install-oracle-java-11-in-ubuntu-18-04-18-10/

sudo apt update

sudo apt install default-jdk

Oracle Java Development Kit JDK

https://en.wikipedia.org/wiki/Java_Development_Kit

https://www.oracle.com/technetwork/java/javase/overview/index.html

Es apropiado instalar Oracle JDK. Para GUI Programming, por ejemplo, se necesitan librerías que se encuentran en Oracle JDK.

Hay diferentes Edition:

  • Java Platform, Standard Edition (Java SE) (ésta es la que generalmente necesitamos)
  • Java Platform, Enterprise Edition (Java EE)
  • Java Platform, Micro Edition (Java ME)
  • ...

Installing Oracle JDK on Ubuntu

Installing Oracle JDK (Java EE) on Ubuntu 18.04: http://ubuntuhandbook.org/index.php/2018/11/how-to-install-oracle-java-11-in-ubuntu-18-04-18-10/

En una ocasion, al instalar java-10-oracle la instalación de NetBeans no funcionó correctamente. Esto creo que se debía a que Java-10-oracle era muy reciente para la fecha. Fue por tanto necesario instalar java-8-oracle y configurar la ruta del JDK editando el archivo /usr/local/netbeans-8.2/etc/netbeans.conf

Installing Oracle JDK on Windows

Installing Oracle JDK (Java EE) on Windows:

  • Descargar Java SE de la página oficial de Oracle:
https://www.oracle.com/technetwork/java/index.html
https://www.oracle.com/technetwork/java/javase/downloads/index.html
  • Instalación común sin ninguna remarca.
  • Los archivos se guardan generalmente by default en: C:\Program Files\Java
    • Cuando instalé NetBeans, éste detectó automáticamente la ruta del JDK - JDK for the NetBeans IDE:
C:\Program Files\Java\jdk1.8.0_181

Check your installed java version

java  -version
javac -version


The fallowing command should tell you what is currently providing the Java virtual machine (java) and the Java compiler (javac): https://askubuntu.com/questions/150057/how-can-i-tell-what-version-of-java-i-have-installed

file /etc/alternatives/java /etc/alternatives/javac

Eclipse

Installing Eclipse

Para estar seguro de que estamos instalando la última versión, es apropiado descargar el paquete desde la página oficial, y no instalar la versión que se encuentra en los repositorios de Ubuntu a través de apt-get (pues estar versiones generalmente están desactualizadas).

Página oficial de Eclipse: http://www.eclipse.org/downloads/

En la siguiente página se explica como instalar eclipse en Ubuntu 16.04: http://ubuntuhandbook.org/index.php/2016/01/how-to-install-the-latest-eclipse-in-ubuntu-16-04-15-10/

Para instalarlo hay que simplemente ejecutar el instalador y seguir las instrucciones (como si se tratara de una instalación en Windows).

Luego, para agregar el ejecutable a la lista de comandos, he agregado la siguiente línea en el .bashrc:

PATH=$PATH:/home/adelo/1-system/.1-conf-system/1-archivos_programas-ubuntu/eclipse/java-photon/eclipse:

Combinaciones de teclas

  • Para que coloque los import (luego de haber ingresado un comando que necesite una librería en particular): Ctrl Shif o
  • Run: Ctrl 11
  • Comentar: Ctrl 7
  • Rastrea la variable seleccionada: CTRL k

NetBeans

https://netbeans.org/

https://en.wikipedia.org/wiki/NetBeans

Installing NetBeans on Ubuntu 18.04

https://www.itzgeek.com/how-tos/linux/ubuntu-how-tos/how-to-install-netbeans-ide-on-ubuntu-18-04-ubuntu-17-10.html

Se puede descargar NetBeans manualmente de la página oficial: https://netbeans.org/downloads/

o a través de wget:

wget http://download.netbeans.org/netbeans/8.2/final/bundles/netbeans-8.2-linux.sh

Luego:

sudo bash netbeans-8.2-linux.sh

Durante la instalación es importante seleccionar el directorio en donde se encuentra Java, en mi caso:

/usr/lib/jvm/java-8-oracle
/usr/lib/jvm/java-10-oracle

Con java-10-oracle la instalación no funcionó correctamente. Fue por tanto necesario instalar java-8-oracle y configurar la ruta del JDK editando el archivo /usr/local/netbeans-8.2/etc/netbeans.conf

Uninstall NetBeans

https://askubuntu.com/questions/76908/how-to-uninstall-netbeans

Sólo hay que ejecutar el script uninstall.sh in /usr/local/netbeans-x.x

bash uninstall.sh

Installing NetBeans on Windows 10

  • Descargar NetBeans de la página oficial: https://netbeans.org/downloads/
  • Cuando instalé NetBeans, éste detectó automáticamente la ruta del JDK - JDK for the NetBeans IDE:
C:\Program Files\Java\jdk1.8.0_181
  • Debido a que instalé la versión que tiene todos los componentes, se instaló también el GlassFish Server Open Source Edition. No sé para que es sirve y si sea apropiado instalarlo.

The Darcula plugin

In NetBeans IDE 8.2 you can now go to:

  • Tools > Plugins > Available Plugins > and install the Darcula LAF for NetBeans plugin directly from there.
  • En las versiones 9 y 10 el Plugin no se encuentra disponible por defecto. Es entonces necesario adicionarlo a la lista de "Available Plugins" de la siguiente forma:
https://stackoverflow.com/questions/52688439/changing-theme-in-apache-netbeans-9-0

Jar File

A Jar File (acronym for Java Archive) is format used for archiving java files (merging several java files into one)

The Jar File, provides a method to package our software to give it to the users.

The Jar File can be Runnable. That is, when we double click it, our program will run.


A typical extension to files that we have always seen when working in a Windows environment is the .exe file extension. These files are a single binary executable file that when double clicked will open the program for the user.

In the Java world however things are a little different. There is no native .exe file in Java and we must use the .jar file extension instead. A jar file works exactly the same as a .exe file and when double clicked will run the program.

Jar files come in two different varieties:

  • Simple archive folder
  • Runnable archive folder

A jar file is an acronym for Java Archive. Simple archive folder is a filetype similar to that of the .zip extension. If we want, we can open up a jar file using a program such as WinZip or WinRar and check the contents inside of the jar.

The second variant of this is the ​runnable archive folder​. This type of file is exactly the same as the archive folder, just with one additional file. This extra file is used to define what happens when the user double clicks on the icon. In our case, we will point to the main method in our class file that we want to run. This will kick start the program to run when it is double clicked.

Creating a Jar

Open up your Eclipse and navigate to the project you are currently working on. Note this will only work correctly with an application that has a GUI for the user to see. In this case the project we are looking at is called Sample Program 1.

  • Right click on the project name, and a menu will open.
  • In the menu that opens, click on the Export button.
  • In the window that opens you will see that two different types of JAR file are available:
    • If you wanted to simply package your project to give to someone, you could use the JAR file.
    • In our case, we are interested in the Runnable JAR file, so we will click on this option and then click Next.
  • You will then be passed to a second window where you will be able to specify the details for the runnable Jar file you are about to create:
    • The first of these is the launch configuration. This is the most important step to ensure that your Jar file will open the project when it is double clicked.
      • Select the name of the class you want to run, inside of the project that you have been working on. In this case, you can see that the Main class is selected which is inside of the project titled SampleProgram1 that we are working in.
    • The second step is then to select a location where we would like to export the Jar file to.
    • After you have finished, click Finish at the bottom of the page.
  • A small warning message may pop up, but this is ok. Click Ok to ignore this message.

Exploring the Jar File

Now that we have created the Jar file. If we double click on the file our program will run. However if we want, we can take a look inside of the Jar file. This is easily done by right clicking on the Jar file that we have created and clicking “Open with WinRAR” or whichever program you currently have installed on your system for viewing Zip files.

After WinRAR has opened you will be able to see the contents of the Jar file. In this case you can see the class file from the project that we have been developing. In addition to this, you will see an additional folder titled META-INF. This is the folder where all of the configuration for the Jar file are held. We will go into this folder and take a look around.

Inside of this folder, you will see a file titled MANIFEST.MF. This is the main configuration file for the Jar file we have created. If we open up this file, we can see the details of what is called when we double click on the Jar file to view it.

There is very little content that is needed to make the Jar file run. Inside of this file, you can see that the Main-Class attribute is set to the name of the class file that we want to run when the Jar is double clicked. In the case of this project, the class file that we want to run is called Main.class, so the title Main is used as the value for this attribute. If your class was called MyProgram.class, this would be set to MyProgram.

Connecting to a MySQL database using Java

La conección a la base de datos MySQL la haremos a través de Connector/J. Esta librería no se encuentra por defecto en las librerías de Java y debemos por lo tanto agregarla a nuestro proyecto Java.

Entonces, para realizar la conección debemos:

  1. Crear la base de datos MySQL a la cual queremos conectarnos
  2. Create an Eclipse Java project
  3. Agregar la librería externa Connector/J a nuestro proyecto
  4. Creación de la Clase Java en donde se hará la conexión

Creación de la base de datos MySQL

Luego de haber instalado y configurado MySQL (Instalación de MySQL) debemos crear la base de datos a la cual queremos conectarnos con Java. Para más detalles ver Database#MySQL

En este caso vamos a crear la base de datos "graham" y la tabla "samplelogin".

CREATE DATABASE graham;

USE graham;

CREATE TABLE samplelogin(
   id	 	INT(10)		NOT NULL AUTO_INCREMENT,
   username 	VARCHAR(15)	NOT NULL,
   password 	VARCHAR(15)	NOT NULL,
   PRIMARY KEY(id)
);

INSERT INTO samplelogin VALUES('001','Adelo Vieira','a2930');
INSERT INTO samplelogin VALUES('002','Rachel Smith','r1039');

Creating an Eclipse Java Project to use Connector/J

Before we make a connection to the database we first must create a new Eclipse project.

Creación de un proyecto Java en Eclipse:

  • File > New > Java Project: enter Project name
    • Esto creará una carpeta con el nombre del proyecto y dentro de ésta la carpeta srs
    • ...

Agregar la librería externa Connector/J a nuestro proyecto

Connector/J

MySQL Connector/J (Desarrollado por MySQL) is the official JDBC driver for MySQL (MySQL is now owned by Oracle Corporation).

We will need this additional library to allow us to make a connection from Java to the MySQL database. Java does not come with this library by default so we need to include this ourselves.

Para descargar Connector/J: https://dev.mysql.com/downloads/connector/j/

You will then be brought to a page where you will be asked if you would like to signup or login. This step is not needed, at the end of the page you will see a link that says "No thanks, just start my download". Click this link to skip ahead and begin the download.

Inside this folder you will see lots of different files, but we only need one file from this folder. The file we are interested in is the mysql-connector-java-5.1.44-bin.jar file. This is a single jar file that contains all the compiled source code we need to connect to a database.

Making a reference to Connector/J

  • Now that we have a new project, we can begin the process of adding the new library into the eclipse project. Right click on the project name and click "Properties". This will open a window showing you all of the project specific settings for the application you are developing.
  • Inside the properties dialog that opens, click on the Java Build Path option.
  • Once you have opened the Java Build Path option, next click the Libraries tab. This will show you a list of additional libraries you have already referenced. But because this is a new project, you will not see any libraries yet!
  • On the right hand side of this window click "Add External Jar" and a dialog window will open. Use this window to locate the mysql-connector-java-5.1.44-bin.jar file that you extracted earlier.
  • After you have found the jar file, you will see a new entry will be made under the libraries tab. This is telling you that when you go to compile the software you are building, it will also look for the .jar file you have just pointed to.
  • Click Ok to finish this step.
  • When you have finished making a reference to the library you will see that inside of your project under the Referenced Libraries menu, there will be a reference to the JAR file that you just pointed to in the previous step. You are now ready to start adding some code into your project to connect to the database.

Creación de la Clase Java en donde se hará la conexión

Luego de haber creado el proyecto Java, debemos crear una clase de la siguiente forma:

  • src folder (clic d) > New > Class: enter name and Click OK!

One thing to keep in mind when working with this code is that it is tempting to allow Eclipse to automatically settle of the imports for you. This can cause issues however, because some libraries in Java have the same name as the ones inside the Connector/J library. To prevent any problems, manually add the imports yourself to the top of your program:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

All of the code that we are working on is inside of a try catch statement as we do not know for sure what may happen to the database connection. If the database connection suddenly dropped it would crash our program. To prevent this, we can use a try catch statement and catch the error if anything goes wrong and allow our program to fail gracefully rather than come to a complete crash from an error.


La conexión con la base de datos la haremos a través de DriverManager.getConnection, método que se encuentra en la Librería Connector/J.

MyDBConnection.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MyDBConnection{
	
	public MyDBConnection() throws SQLException{
		
		// La conexi'on con la base de datos se hace a trav'es de esta orden:
           	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/graham?"
    					             	       +"user=root&password=a1640774200");
		
		// Luego de establecer la conexi'on podemos realizar un query sobre la base de datos:
        	Statement stmt = conn.createStatement();
        	ResultSet rs = stmt.executeQuery("select * from samplelogin;");
			
	}

}

En el ejemplo anterior hemos realizado la conexión con la base de datos SQL «graham» y hemos almacenado el resultado de la query en la variable rs. Sin embago, no hemos desplegado el resultado de la query ni hemos hecho nada útil con ella. A continuación se muestran algunas clases que conectan con la base de datos y muestran ejemplos más elaborados.

Creación de la clase ShowingData.java

ShowingData.java
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JTextField;


public class ShowingData extends JFrame  {
	
    public ShowingData(){
    
    	setSize(500,500);
    	setVisible(true);
    	
    	Connection conn = null;
    	Statement stmt = null;
    	ResultSet rs = null;
    	
    	try {
    	    // La conexi'on con la base de datos se hace a trav'es de esta orden:
    	    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/graham?"
    	    				        +"user=root&password=a1640774200");

    	    // Luego de establecer la conexi'on podemos realizar un query sobre la base de datos:
    	    stmt = conn.createStatement();
    	    rs = stmt.executeQuery("select * from samplelogin;");

    	    // El reultado del query se encuentra en el objeto "rs" creado arriba.
    	    // Ahora queremos desplegar la data almacenada en "rs".
    	    // En este ejemplo vamos a desplegar la data en un JTable.
    	    
    	    // Lo primero que hay que hacer es crear una variable de tipo String (una matriz en este caso)
    	    // El n'umero de columnas debe, por supuesto, ser igual al n'umero de columnas de la tabla
    	    // almacenada en "rs". El n'umero de filas debe ser igual o mayor al n'umero de filas de la tabla.
     	    String[][] data = new String[100][3];
     	    
     	    // Ahora vamos a ingresar la data que se encuentra en el objeto "rs" a la matriz "data" creada arriba.
     	    // Para esto vamos a realizar un ciclo que va a recorrer el objeto "rs" e ingresar los valores a "data"
    	    int counter = 0;
    	    while(rs.next()){
    	    	String id = rs.getString("id");      
    	       
    	    	data[counter][0] = id;
    	      
    	        String un = rs.getString("username");
    	    	data[counter][1] = un;    	      
    	        
    	        String pw = rs.getString("password");
    	    	data[counter][2] = pw;
    	        
    	        counter = counter+ 1;
    	    }
    	    
    	    // Ahora que ya tenemos la data almacenada en la matriz "data", podemos desplegarla en una JTable.
    	    // S'ólo debemos antes crear un vector String que contenga el nombre de las columnas:
    	    String[] colNames = {"id" , "username" , "password"};
    	    
    	    // Ahora s'i podemos desplegar la data correctamente en el JTable:
    	    JTable table = new JTable(data , colNames);
    	    
    	    // Tenemos tambi'en que agregamos un JScrollPane a nuestra tabla para poder desplazarnos en ella:
    	    JScrollPane sr = new JScrollPane(table);
    	    
    	    // Por 'ultimo, agregamos nuestra Jtable al JFrame:
    	    this.add(sr);
    	        
    	} 
    	
    	// Handle any errors:
    	catch (SQLException ex) {
    	    System.out.println("SQLException: " + ex.getMessage());
    	    System.out.println("SQLState: " + ex.getSQLState());
    	    System.out.println("VendorError: " + ex.getErrorCode());
    	}
    	
    	
    }
    
	public static void main(String[] args) {
		// TODO Auto-generated method stub
			new ShowingData();
	}

}

Creación de la clase Register.java

En este caso vamos a crear la clase Register.java, la cual permite ingresar datos a una base de datos MySQL utilizando la librería Connector/J.

Register.java
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;


public class Register extends JFrame implements ActionListener{
	
	// make the fields global so we can see them!!
	JTextField username = null;
	JTextField password = null;
	
	public Register(){		

		setSize(400,400);
		setVisible(true);
		this.setLayout(new GridLayout(3,1));

		JLabel un = new JLabel("Username:");
		this.add(un);
		username = new JTextField(20);
		this.add(username);
		
		JLabel pw = new JLabel("Password:");
		this.add(pw);
		password = new JTextField(20);
		this.add(password);
		
		JButton register = new JButton("Register");
		
		register.addActionListener(this);
		
		this.add(register);
		
		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Register();
	}
	
	public void registerNewUser(){
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		}
		
		catch(Exception e ){}
		
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		try {
			// En esta linea debemos ajustar: 
			// El IP (127.0.0.1 si es localhost) y el Port (generalmente el 3306) en donde corre MySQL.
			// El nombre de la base de datos a la cual queremos conectarnos: graham en nuestro ej.
			// El usuario y la clave de MySQL.
			conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/graham?user=root&password=a1640774200");
	    	
			// Do something with the Connection
			stmt = conn.createStatement();
			
			// or alternatively, if you don't know ahead of time that
			// the query will be a SELECT...
			String un = username.getText();
			String pw = password.getText();
			
			// En esta linea debemos ajustar el nombre de la base de datos y la tabla
			// en donde queremos agragar datos. En nuestro ejemplo: graham, samplelogin.
			if (stmt.execute("INSERT INTO `graham`.`samplelogin` (`username`, `password`) VALUES ('"+un+"', '"+pw+"');")) {
			}
		}
		
		// loop over results
		catch (SQLException ex) {
			// handle any errors
			System.out.println("SQLException: " + ex.getMessage());
			System.out.println("SQLState: " + ex.getSQLState());
			System.out.println("VendorError: " + ex.getErrorCode());
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		registerNewUser();
	}
}

Epoch time

Threads

La siguiente es la referencia colocada por el Prof. para este tema: https://docs.oracle.com/javase/tutorial/essential/concurrency/

Threads are used to allow our program to do more than one thing at any one time.

We picture a process which has two tasks that aren't necessarily dependent on each other. They can occur at the same time, each handled by a "thread"

  • Thread.jpg
  • Java thread.png

So, a process (think program) can contain a number of different threads. As the program is running, the processor switches between each of the threads allowing each of them to have some CPU time to run.

For dual (or more) core machines, each thread can be executed on a separate core, so no switching is neceessary. The threads truly run concurrently.

In the previous picture you can also see that Thread number 2 has died off and thread 1 continued on. This is ok.

Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process.

Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files.

Every application has at least one thread — or several, if you count "system" threads that do things like memory management and signal handling. From the programmer’s point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads

The difficulty with threads

  • Threads can be difficult to work with because their behavior can be unpredictable.
  • The order in which they are running may change unless synchronized.

Some methods available in the Thread class

// Changes the name of this thread to be equal to the argument name.
setName(String name) 

// Changes the priority of this thread. Valid values are 1 through 10.
setPriority(int newPriority)

// Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds
sleep(long millis)

// Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
start()

// Causes the current thread to block (pause) until the specified thread terminates.
Thread.join()

// Causes the current thread to block until the specified thread terminates or the specified number of milliseconds passes
Thread.join(long millis)

Creating Threads

We'll see that (just like everything in Java) a thread is just an object. We can create them, use them, etc...

When we want to create threads, two options are available to us:

  • Extend the thread class, or
  • We can implement the Runnable interface


Extend the thread class:

By doing like this we have access to all the methods in the thread class.

We need to extend the thread class and add a run method (Instead of a main method, threads run the run() method):

MyThread.java:
public class MyThread extends Thread {

	public void run(){
		// This is the code that is executed when the thread is started
		// Este es s'olo un c'odigo ejemplo. Aqu'i podr'ia haber cualquier c'odigo
		for (int i=0 ; i < 100000000 ; i++){
			System.out.println(this.getName() + ": " + i);
			
		}
		
	}
	
}

Then, when we want to use our thread (in our standard class: MyProgram.java in our example), we create an instance of the thread, then start it.

MyThread t = new MyThread();
t.start();


Implement the Runnable interface:

To do this we just start by making a regular class, but implement the runnable interface.

After this, we need to add a run() method to the class (Instead of a main method, threads run the run() method):

MyRunnable.java
public class MyRunnable implements Runnable {
	
	public void run(){
		
		for (int i=0 ; i < 100000000 ; i++){
			System.out.println("My Tread implementing the Runnable interface: " + i);
			
		}
		
	}
	
}


Then, in our standard class (MyProgram.java in our example), when we want to use our thread, we just need to create an instance of the thread in case we extended the thread class (as we said above), then start it. However, if we implemented the Runnable interface:

  • We need to create an instance of the Runnable Tread we created:
MyRunnable r = new MyRunnable();
  • After this, we need to create a Thread object and pass the Runnable Tread object we created to it, and then start it:
Thread tr = new Thread(r);
tr.start();


Whatever code is inside the run method will be executed when the thread is started.

For instance, if we would like the thread to sleep for a certain amount of time, we can call:

try{ 
     myThread.sleep(10000);
}catch (InterruptedException e){
     e.printStackTrace();
}


A continuación («MyProgram.java») es la «standad class» en donde vamos a utilizar las «Threads» («MyThread.java» and «MyRunnable.java») creadas arriba:

MyProgram.java:
import javax.swing.JFrame;

public class MyProgram extends JFrame{
	
	public MyProgram(){

		setSize(500,500);
		setVisible(true);
		
//		Object created extending the thread class:
		MyThread t = new MyThread();
		t.setName("t1");
		t.setPriority(10);
		t.start();

//		Object created implementing the runnable interface:		
		MyRunnable r = new MyRunnable();
		Thread tr = new Thread(r);
		tr.start();
		
	}
	public static void main(String[] args) {
		new MyProgram();
	}

}

En el ejemplo anterior hemos creado un JFrame que cuando se abre se ejecuta también el Thread.

Cuando se ejecuta MyProgram.java se debe notar que la ejecución no sigue el orden del código. Es decir, en nuestro ejemplo nuestras Threads sólo imprimen un valores en pantalla. Note que no necesariamente se debe terminar la impresión de todos los valores de la primera Thread en el código antes de comenzar la segunda. Esta característica impredecible de las Threads fue mencionada en The difficulty with threads

A continuación se muestra un ejemplo un poquito más elaborado en el cual la Thread se ejecuta una vez que se hace clic en un botón desplegado en el JFrame. Para esto se implementa el ActionListener

GUIThread.java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class GUIThread extends JFrame implements ActionListener{

	public GUIThread(){
		
		setSize(300,300);
		setVisible(true);
		
		JButton btn = new JButton("Button");
		btn.addActionListener(this);
		this.add(btn);
		
	}
	
	public static void main(String[] args) {
	    // TODO Auto-generated method stub
            new GUIThread();
	}
	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("Button");
		
		MyThread x = new MyThread();
		x.start();
			
	}

}

Daemon thread

Daemon thread in Java are those thread which runs in background and mostly created by JVM* for performing background task like Garbage collection and other house keeping tasks. Difference between Daemon and Non Daemon(User Threads) is also an interesting multi-threading interview question, which asked mostly on fresher level java interviews.

(*) A Java virtual machine (JVM) is an abstract computing machine that enables a computer to run a Java program.

  • In one line main difference between daemon thread and user thread is that as soon as all user thread finish execution java program or JVM terminates itself, JVM doesn't wait for daemon thread to finish the execution. As soon as last non daemon thread finished JVM terminates no matter how many Daemon thread exist or running inside JVM.
  • Another difference between daemon thread and user thread is that Daemon Thread are treated differently than User Thread when JVM terminates, finally blocks are not called, Stacks are not unwounded and JVM just exits.
  • Thread inherits its daemon nature from the Thread which creates it (i.e. parent Thread). If the main thread is a non daemon thread, any other thread created from it will remain non-daemon until explicitly made daemon by calling setDaemon(true).
  • Thread.setDaemon(true) makes a Thread daemon but it can only be called before starting Thread in Java. It will throw IllegalThreadStateException if corresponding Thread is already started and running.
  • Daemon Threads are suitable for doing background jobs like housekeeping, Though I have yet to use it for any practical purpose in application code. Let us know if you have used daemon thread in your java application for any practical purpose.


Ejemplos clásicos para comprender el concepto de Thread

Los siguientes problemas fueron abordados por el Prof. para explicar el concepto the Thread.

Expanding our program across multiple files (Classes)

Although we have developing all of our code inside a single java file, it is common practice to break the application down into smaller individual classes.

We will only ever have one main method. In this case, our Login.java is the file that will have the main method. No other class should have a main method!

Para integrar distintas «class» lo único que tenemos que hacer es tener los archivos en el mismo directorio y crear una instancia de la «class». En el siguiente ejemplo hemos creado una instancia de la «class» ShosingData en Login.java. En este caso, si se cumple el IF, se ejecutará «ShowingData.java».

Fracmento de /home/adelo/1-disco_local/.archivos_programas/eclipse-workspace/DBtest/src/Login.java
if(un.equals("Nathalie")){
        ShowingData d = new ShowingData();
}

Passing Object References

Ahora que nuestro programa está formado por diferentes archivos (diferentes class), veremos que en ocasiones, cuando creamos una «instance» de una class (Ej: «BasicShowData.java») dentro de, por ejemplo, «BasicLogin.java», podría ser necesario que «BasicShowData.java» colecte información de «BasicLogin.java». To do this, we will pass a reference across from the BasicLogin.java page to the «BasicShowData.java» page that will allow us to call back to the «BasicLogin.java» and access any variables or methods that it may have.

Note que inside «», when we click the "Login" button, the actionListener method is then called and the BasicShowData class is just being created. Instead of just creating the «BasicShowData()» class, we are going to pass a reference to «this» current class that we are in (BasicLogin.java class). En otras palabras, cuando en «BasicLogin.java» creamos la instance de «BasicShowData()» vamos a pasar una referencia de la clase donde estamos («BasicLogin.java») a través de «this»:

In BasicLogin.java:

BasicShowData d = new BasicShowData(this);

Now, in the «BasicShowData class», we must change the default constructor to catch «this» reference:

public BasicShowData(BasicLogin ref) {

De esta forma, la instancia de «BasicShowData class» puede acceder to all the variables and fields of the current class («BasicLogin.java»).

/home/adelo/1-disco_local/.archivos_programas/eclipse-workspace/PassingObjectReferences/src/BasicLogin.java
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class BasicLogin extends JFrame implements ActionListener{
	JTextField username = null;
	JTextField password = null;
	
	public BasicLogin(){
		
		setSize(300,300);
		setVisible(true);
		
		this.setLayout(new GridLayout(3,2));
		
		JLabel un = new JLabel("Username");
		this.add(un);
		
		username = new JTextField(20);
		this.add(username);
		
		JLabel pw = new JLabel("Password");
		this.add(pw);
		password = new JTextField(20);
		this.add(password);
		
		JButton button = new JButton("Login!");
		button.addActionListener(this);
		this.add(button);
		
		validate();
		repaint();
	}
	public static void main(String[] args){
		
		new BasicLogin();

	}
	@Override
	public void actionPerformed(ActionEvent arg0){
		// TODO Auto-generated method stub
		BasicShowData d = new BasicShowData(this);
	}

}


/home/adelo/1-disco_local/.archivos_programas/eclipse-workspace/PassingObjectReferences/src/BasicShowData.java
import javax.swing.JFrame;
import javax.swing.JLabel;

public class BasicShowData extends JFrame {

	public BasicShowData(BasicLogin ref) {
		
		String username = ref.username.getText();
		
		setSize(300,300);
		
		setVisible(true);
		
		JLabel tx = new JLabel("They logged in as: " + username);
		this.add(tx);
	}
}