Diferència entre revisions de la pàgina «DAM-M3-UF5. Interfícies Gràfiques d'Usuari (GUI)»

De Wiki IES Marianao. Departament Informàtica
Dreceres ràpides: navegació, cerca
(Esdeveniments)
(Sistema de delegació d’esdeveniments)
 
(26 revisions intermèdies per 3 usuaris que no es mostren)
Línia 17: Línia 17:
 
JFC (Java Foundation Classes) inclou les característiques necessàries per crear GUI. Els paquets que s’utilitzen habitualment per a desenvolupar aplicacions gràfiques són
 
JFC (Java Foundation Classes) inclou les característiques necessàries per crear GUI. Els paquets que s’utilitzen habitualment per a desenvolupar aplicacions gràfiques són
  
* java.awt.* : Abstract Window Toolkit. Components gràfics del SDK per crear GUI.
+
* <code>java.awt.*</code>: Abstract Window Toolkit. Components gràfics del SDK per crear GUI.
  
* java.awt.event.* : Tractament dels esdeveniments associats
+
* <code>java.awt.event.*</code>: Tractament dels esdeveniments associats
  
* javax.swing.* : Ampliació dels components gràfics per crear GUI
+
* <code>javax.swing.*</code>: Ampliació dels components gràfics per crear GUI
  
 
Java és un llenguatge multiplataforma i per tant les seves eines gràfiques són també multiplataforma.
 
Java és un llenguatge multiplataforma i per tant les seves eines gràfiques són també multiplataforma.
Línia 27: Línia 27:
 
Enllaç bàsic i indispensable!!!
 
Enllaç bàsic i indispensable!!!
 
http://java.sun.com/docs/books/tutorial/uiswing/index.html
 
http://java.sun.com/docs/books/tutorial/uiswing/index.html
 
  
 
=== Contenidors ===
 
=== Contenidors ===
Línia 33: Línia 32:
 
Un contenidor és un element base, dins del qual es poden afegir altres elements, els contenidors també actuen com components i es poden afegir dins altres contenidors.
 
Un contenidor és un element base, dins del qual es poden afegir altres elements, els contenidors també actuen com components i es poden afegir dins altres contenidors.
  
Els Contenidors hereten de la classe abstracta java.awt.Container. Exemples són:
+
Els Contenidors hereten de la classe abstracta <code>java.awt.Container</code>. Exemples són:
  
* '''Frames''' (classe javax.swing.JFrame). Finestra principal
+
* '''Frames''' (classe <code>javax.swing.JFrame</code>). Finestra principal
  
* '''Panels''' (classe javax.swing.JPanel). Panells on col·locar els components dins la finestra
+
* '''Panels''' (classe <code>javax.swing.JPanel</code>). Panells on col·locar els components dins la finestra
  
* '''Applets''' (classe javax.swing.JApplet). Applets per afegir a pàgines web.
+
* '''Applets''' (classe <code>javax.swing.JApplet</code>). Applets per afegir a pàgines web.
  
 +
<html>
 
<pre>
 
<pre>
public class FrameSimple extends JFrame {
+
<code class='java'>
 +
public class FrameSimple extends JFrame {
 +
 
 +
private static final long serialVersionUID = 1L;
 +
 
 +
public FrameSimple() {
 +
super();
 +
initialize();
 +
}
  
    public FrameSimple() {
+
private void initialize() {
        super();
+
setTitle("Simple Frame"); // Títol de la finestra
        initialize();
+
setSize(350, 200); // Tamany
    }
+
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 +
// pack(); // Ajusta la finestra a la mida dels controls, però ara no en té
 +
setVisible(true); // Mostra
 +
}
  
    private void initialize() {
+
public static void main(String[] args) {
        this.setTitle("Finestra Simple");
+
new FrameSimple();
        this.setSize(350,200); //Mida
+
}
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        this.setTitle("Finestra simple"); //Títol
 
        this.setVisible(true); // Propietat de visibilitat
 
    }
 
  
    public static void main (String args[]) {
 
        FrameSimple mainFrame = new FrameSimple();
 
    }
 
 
}
 
}
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
==== Nivells de contenidors ====
 
==== Nivells de contenidors ====
Línia 68: Línia 74:
 
Java utilitza una estructura per nivells per col·locar els diferents elements gràfics, abans de començar a col·locar els components cal estructurar el contenidor.
 
Java utilitza una estructura per nivells per col·locar els diferents elements gràfics, abans de començar a col·locar els components cal estructurar el contenidor.
  
Normalment el primer contenidor serà un JFrame o JApplet, anomenats Top-Level Containers, i a partir d’aquest es crea una estructura jeràrquica amb diferents contenidors.
+
Normalment el primer contenidor serà un <code>JFrame</code> o <code>JApplet</code>, anomenats Top-Level Containers, i a partir d’aquest es crea una estructura jeràrquica amb diferents contenidors.
  
 
[[ File: contenidors1.png]]
 
[[ File: contenidors1.png]]
  
  
Per exemple una estructura típica inclou un JFrame dins del qual tenim per una banda el contenidor (ContentPane) on s’afegeixen els diferents components i un menú.
+
Per exemple una estructura típica inclou un <code>JFrame</code> dins del qual tenim per una banda el contenidor (<code>ContentPane</code>) on s’afegeixen els diferents components i un menú.
  
  
El ContentPane es pot crear a partir d’un JPanel per exemple ''setContentPane(contentPane)'' o obtenir el que hi ha per defecte ''toplevelContainer.getContentPane(): Container''.
+
El <code>ContentPane</code> es pot crear a partir d’un <code>JPanel</code> per exemple <i><code>setContentPane(contentPane)</code></i> o obtenir el que hi ha per defecte <i><code>toplevelContainer.getContentPane(): Container</code></i>.
 
 
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
         JPanel contentPane = new JPanel(new BorderLayout());
 
         JPanel contentPane = new JPanel(new BorderLayout());
        //... crear components
+
 
         JLabel l = new JLabel("Hola");
+
         JLabel label = new JLabel("Hola"); // Crem una etiqueta amb text 'Hola'
         contentPane.add(l, BorderLayout.CENTER);
+
         contentPane.add(label, BorderLayout.CENTER); // Afegim la etiqueta al centre del panel
 
        
 
        
         this.setContentPane(contentPane);
+
         setContentPane(contentPane); // Afegim el panel al Frame
 +
</code>
 
</pre>
 
</pre>
 
+
</html>
  
 
=== Components ===
 
=== Components ===
Línia 95: Línia 103:
 
Hi ha molts tipus de components o controls, tants com et puguis imaginar.
 
Hi ha molts tipus de components o controls, tants com et puguis imaginar.
  
* '''Etiquetes de text'''. Classe javax.swing.JLabel
+
* '''Etiquetes de text'''. Classe <code>javax.swing.JLabel</code>
  
* '''Botons'''. Classe javax.swing.JButon
+
* '''Botons'''. Classe <code>javax.swing.JButon</code>
  
* '''Àrees de text'''. Classe javax.swing.JTextField
+
* '''Àrees de text'''. Classe <code>javax.swing.JTextField</code>
  
* '''Selecció'''. Classe javax.swing.JChoice
+
* '''Selecció'''. Classe <code>javax.swing.JChoice</code>
  
* '''Checkboxes'''. Classe javax.swing.JCheckbox. Agrupats o no en un Checkboxgroup (classe java.awt.CheckboxGroup)
+
* '''Checkboxes'''. Classe <code>javax.swing.JCheckbox</code>. Agrupats o no en un <code>CheckboxGroup</code> (classe <code>java.awt.CheckboxGroup</code>)
  
* '''Llistes'''. Classe java.swing.JList
+
* '''Llistes'''. Classe <code>java.swing.JList</code>
  
* '''Menús'''. Classe javax.swing.JMenu
+
* '''Menús'''. Classe <code>javax.swing.JMenu</code>
  
* '''Selector de color'''. Classe javax.swing.JColorChooser
+
* '''Selector de color'''. Classe <code>javax.swing.JColorChooser</code>
  
* '''Selector de fitxers'''. Classe javax.swing.JFileChooser
+
* '''Selector de fitxers'''. Classe <code>javax.swing.JFileChooser</code>
  
 
[[ File: components1.png]]
 
[[ File: components1.png]]
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
public class Contenidor extends JPanel {
 
public class Contenidor extends JPanel {
 
     public Contenidor() {
 
     public Contenidor() {
Línia 122: Línia 132:
 
         etiqueta.setBackground(Color.CYAN);
 
         etiqueta.setBackground(Color.CYAN);
 
         etiqueta.setForeground(new Color(255,0,0));
 
         etiqueta.setForeground(new Color(255,0,0));
 +
        etiqueta.setOpaque(true);
 +
        etiqueta.setFont(new Font("SansSerif", Font.BOLD, 24));
 
         this.add(etiqueta);
 
         this.add(etiqueta);
 
         JTextArea text = new JTextArea("Camp de Text", 10, 10);
 
         JTextArea text = new JTextArea("Camp de Text", 10, 10);
Línia 131: Línia 143:
  
 
// Afegir el contenidor al Top-Level
 
// Afegir el contenidor al Top-Level
//this.setContentPane(new Contenidor());
+
// this.setContentPane(new Contenidor());
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
=== Organitzadors de components ===
 
=== Organitzadors de components ===
Línia 142: Línia 156:
 
{| border="1"
 
{| border="1"
 
| [[File: border.png]]
 
| [[File: border.png]]
| '''java.awt.BorderLayout'''. Administrador per defecte dels contenidors Frames. Depenent de la zona respecta o no les dimensions dels components
+
| <b><code>java.awt.BorderLayout</code></b>. Administrador per defecte dels contenidors Frames. Depenent de la zona respecta o no les dimensions dels components
 
|-
 
|-
 
| [[File: flow.png]]
 
| [[File: flow.png]]
| '''java.awt.FlowLayout'''. Administrador per defecte dels contenidors Panels. Els components es disposen un darrera l’altre, per ordre i quan no caben una nova línia, respecta dimensions dels components
+
| <b><code>java.awt.FlowLayout</code></b>. Administrador per defecte dels contenidors Panels. Els components es disposen un darrera l’altre, per ordre i quan no caben una nova línia, respecta dimensions dels components
 
|-
 
|-
 
| [[File: grid.png]]
 
| [[File: grid.png]]
| '''java.awt.GridLayout'''. Disposa els elements en una matriu de files i columnes. No respecta dimensions dels components
+
| <b><code>java.awt.GridLayout</code></b>. Disposa els elements en una matriu de files i columnes. No respecta dimensions dels components
 
|-
 
|-
 
| [[File: spring1.png]]  [[File: spring2.png]]
 
| [[File: spring1.png]]  [[File: spring2.png]]
| '''java.awt.SpringLayout'''. És molt flexible, es basa en disposar els elements respecte altres elements o respecte el propi contenidor. Més complex de configurar que els anteriors, però necessari per dissenyar interfícies complexes.
+
| <b><code>java.awt.SpringLayout</code></b>. És molt flexible, es basa en disposar els elements respecte altres elements o respecte el propi contenidor. Més complex de configurar que els anteriors, però necessari per dissenyar interfícies complexes.
 
|-
 
|-
 
| Sense contenidor
 
| Sense contenidor
| '''Null''', També és possible crear un contenidor sense organitzador. És poc recomanable
+
| <b><code>null</code></b>, També és possible crear un contenidor sense organitzador. És poc recomanable
 
|}
 
|}
  
 
Exemples,
 
Exemples,
 
+
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
//Exemple BorderLayout
 
//Exemple BorderLayout
  
Línia 215: Línia 230:
 
         this.add(boto1);
 
         this.add(boto1);
 
         this.add(boto2);
 
         this.add(boto2);
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
=== Aparença (Look and Feel)  ===
 
=== Aparença (Look and Feel)  ===
Línia 231: Línia 248:
 
Per exemple,
 
Per exemple,
  
<pre>
+
<html>
 +
<!-- HE DESACTIVAT AIXÒ I L'HE CANVIAT PER UN EXEMPLE QUE TROBO MÉS INTERESSANT ;-)
 
     public static void main (String args[]) {
 
     public static void main (String args[]) {
 
         try {
 
         try {
Línia 248: Línia 266:
 
         FrameSimple mainFrame = new FrameSimple();
 
         FrameSimple mainFrame = new FrameSimple();
 
     }
 
     }
 +
-->
 +
<pre>
 +
<code class='java'>
 +
public class LookAndFeels {
 +
 +
public static void main(String[] args) throws Exception {
 +
 +
System.out.println("Default LookAndFeel:");
 +
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 +
 +
int x = 0;
 +
int y = 0;
 +
 +
System.out.println("Installed LookAndFeels:");
 +
 +
for (LookAndFeelInfo lfInfo : UIManager.getInstalledLookAndFeels()) {
 +
 +
String lfClass = lfInfo.getClassName();
 +
System.out.println(lfClass);
 +
UIManager.setLookAndFeel(lfClass);
 +
 +
// Fem una finestra d'exemple
 +
JFrame window = new FrameSimple();
 +
window.setTitle(lfInfo.getName());
 +
window.setLocation(x, y);
 +
x += 50;
 +
y += 50;
 +
}
 +
}
 +
}
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
=== Esdeveniments ===
 
=== Esdeveniments ===
Línia 260: Línia 310:
 
* Font de l’esdeveniment, control sobre el qual es produeix l’esdeveniment
 
* Font de l’esdeveniment, control sobre el qual es produeix l’esdeveniment
  
* Esdeveniment (Event), generat per una acció de l’usuari sobre un control
+
* Esdeveniment (<code>Event</code>), generat per una acció de l’usuari sobre un control
  
* Controlador d’esdeveniments o oient (Listener), objecte associat al control, que gestiona els esdeveniments.
+
* Controlador d’esdeveniments o oient (<code>Listener</code>), objecte associat al control, que gestiona els esdeveniments.
  
 
La font de l’esdeveniment crea un objecte Event que envia al controlador, i aquest respon a l’esdeveniment, en aquest sentit es diu que el control delega la gestió de l’esdeveniment.
 
La font de l’esdeveniment crea un objecte Event que envia al controlador, i aquest respon a l’esdeveniment, en aquest sentit es diu que el control delega la gestió de l’esdeveniment.
Línia 268: Línia 318:
 
Els paquets utilitzats per a la gestió d’esdeveniments són:
 
Els paquets utilitzats per a la gestió d’esdeveniments són:
  
''java.awt.event''
+
<code>java.awt.event</code>
  
''javax.swing.event'' (Classes i interfases afegides a l’anterior)
+
<code>javax.swing.event</code> (Classes i interfases afegides a l’anterior)
  
 
Dins els paquets hi ha:
 
Dins els paquets hi ha:
  
* Les classes per gestionar els objectes esdeveniments (Sufix Event).
+
* Les classes per gestionar els objectes esdeveniments (Sufix <code>Event</code>).
  
* Les interfases controladores d’esdeveniments, cal implementar-ne tots els mètodes (Sufix Listener)
+
* Les interfases controladores d’esdeveniments, cal implementar-ne tots els mètodes (Sufix <code>Listener</code>)
  
* Classe abstractes que implementen els mètodes dels controladors buits, per evitar haver d’implementar tots els mètodes de les interfases que en tenen més d’un (Sufix Adapter)
+
* Classe abstractes que implementen els mètodes dels controladors buits, per evitar haver d’implementar tots els mètodes de les interfases que en tenen més d’un (Sufix <code>Adapter</code>)
  
 
En una aplicació un controlador pot gestionar varis esdeveniments si implementa vàries interfaces, però només un si hereta l'adaptador corresponent.
 
En una aplicació un controlador pot gestionar varis esdeveniments si implementa vàries interfaces, però només un si hereta l'adaptador corresponent.
  
Per exemple en el cas d’un '''botó''', l’esdeveniment habitual és '''ActionEvent''', i el controlador que gestiona aquests tipus d'esdeveniments és el '''ActionListener''', que només té un mètode:
+
Per exemple en el cas d’un '''botó''', l’esdeveniment habitual és <code>ActionEvent</code>, i el controlador que gestiona aquests tipus d'esdeveniments és el <code>ActionListener</code>, que només té un mètode:
  
''void actionPerformed(ActionEvent e)''
+
<code>void actionPerformed(ActionEvent e)</code>
  
 
Primer cal implementar el controlador
 
Primer cal implementar el controlador
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
class CtrlEvent implements ActionListener
 
class CtrlEvent implements ActionListener
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
Després cal afegir una instància d’aquest com a controlador d’un o múltiples components, cada component tindrà els seus mètodes per afegir controladors que corresponguin.
 
Després cal afegir una instància d’aquest com a controlador d’un o múltiples components, cada component tindrà els seus mètodes per afegir controladors que corresponguin.
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
Componentqualsevol.addActionListener(new CtrlEvent());
 
Componentqualsevol.addActionListener(new CtrlEvent());
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
Finalment cal escriure els mètodes del controlador que interessin.
 
Finalment cal escriure els mètodes del controlador que interessin.
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
class ECtrlEvent implements ActionListener {
 
class ECtrlEvent implements ActionListener {
  
Línia 309: Línia 369:
 
       }
 
       }
 
}
 
}
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
A la següent taula es mostra les Classes i Interfaces més comuns
 
A la següent taula es mostra les Classes i Interfaces més comuns
Línia 322: Línia 384:
 
|-
 
|-
 
| Finestres
 
| Finestres
| JFrame
+
| <code>JFrame</code>
| valign="TOP" | void addWindowListener(WindowListener l)
+
| <code>void addWindowListener(WindowListener l)</code>
| WindowEvent
+
| <code>WindowEvent</code>
| WindowListener
+
| <code>WindowListener</code>
  
 
 
  
WindowAdapter
+
<code>WindowAdapter</code>
 
|-
 
|-
| Botons
+
| Botons
| JButton
+
| <code>JButton</code>
| valign="TOP" | void addActionListener(ActionListener l)
+
| valign="TOP" | <code>void addActionListener(ActionListener l)</code>
| ActionEvent
+
| <code>ActionEvent</code>
| ActionListener
+
| <code>ActionListener</code>
 
|-
 
|-
| Check Box
+
| Check Box
| JCheckbox
+
| <code>JCheckbox</code>
| valign="TOP" | void addItemListener(ItemListener l)
+
| valign="TOP" | <code>void addItemListener(ItemListener l)</code>
| ItemEvent
+
| <code>ItemEvent</code>
| ItemListener
+
| <code>ItemListener</code>
 
|-
 
|-
| valign="TOP" | List
+
| valign="TOP" | List
| valign="TOP" | JList
+
| valign="TOP" | <code>JList</code>
| valign="TOP" | void addListSelectionListener(ListSelectionListener listener)
+
| valign="TOP" | <code>void addListSelectionListener(ListSelectionListener listener)</code>
| ListSelectionEvent
+
| <code>ListSelectionEvent</code>
| ListSelectionListener
+
| <code>ListSelectionListener</code>
 
|-
 
|-
 
| Text Field
 
| Text Field
| JTextField
+
| <code>JTextField</code>
| void addCaretListener(CaretListener listener)
+
| <code>void addCaretListener(CaretListener listener)</code>
| CaretEvent
+
| <code>CaretEvent</code>
| CaretListener
+
| <code>CaretListener</code>
 
|-
 
|-
 
| Text Area
 
| Text Area
| JTextArea
+
| <code>JTextArea</code>
| valign="TOP" | void addCaretListener(CaretListener listener)
+
| valign="TOP" | <code>void addCaretListener(CaretListener listener)</code>
| valign="TOP" | CaretEvent
+
| valign="TOP" | <code>CaretEvent</code>
| valign="TOP" | CaretListener
+
| valign="TOP" | <code>CaretListener</code>
 
|}
 
|}
  
Línia 375: Línia 437:
 
|-
 
|-
 
| Ratolí
 
| Ratolí
| void addMouseListener(MouseListener l)
+
| <code>void addMouseListener(MouseListener l)</code>
| MouseEvent
+
| <code>MouseEvent</code>
| MouseListener
+
| <code>MouseListener</code>
  
 
 
  
MouseAdapter
+
<code>MouseAdapter</code>
 
|-
 
|-
 
| Ratolí
 
| Ratolí
| void addMouseMotionListener(MouseMotionListener l)
+
| <code>void addMouseMotionListener(MouseMotionListener l)</code>
| MouseEvent
+
| <code>MouseEvent</code>
| MouseMotionListener
+
| <code>MouseMotionListener</code>
  
 
 
  
MouseMotionAdapter
+
<code>MouseMotionAdapter</code>
 
|}
 
|}
  
Línia 396: Línia 458:
 
Per exemple, es pot implmentar el controlador en el propi contenidor
 
Per exemple, es pot implmentar el controlador en el propi contenidor
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
public class Contenidor extends JPanel implements ActionListener {
 
public class Contenidor extends JPanel implements ActionListener {
 
     private JButton boto1;
 
     private JButton boto1;
Línia 424: Línia 488:
 
     }
 
     }
 
}
 
}
 +
</code>
 
</pre>
 
</pre>
 
+
</html>
  
 
O també es pot implementar en una classe específica
 
O també es pot implementar en una classe específica
  
 +
<html>
 
<pre>
 
<pre>
 +
<code class='java'>
 
public class Contenidor extends JPanel {
 
public class Contenidor extends JPanel {
 
     private JButton boto1;
 
     private JButton boto1;
Línia 463: Línia 530:
 
     }
 
     }
 
}
 
}
 +
</code>
 +
</pre>
 +
</html>
 +
 +
O també amb una classe anònima
 +
 +
<html>
 +
<pre>
 +
<code class='java'>
 +
public class Contenidor extends JPanel {
 +
    private JButton boto1;
 +
    private JButton boto2;
 +
    private JLabel text;
 +
 
 +
    public Contenidor() {
 +
        super();
 +
        boto1 = new JButton( "Acció1" );
 +
        boto2 = new JButton( "Acció2" );
 +
        text = new JLabel("Text qualsevol");
 +
        boto1.addActionListener(new ActionListener() {
 +
 +
            public void actionPerformed(ActionEvent e)
 +
            {
 +
                //Execute when button is pressed
 +
                System.out.println("You clicked the button");
 +
            }
 +
        });
 +
     
 +
        this.add(boto1);
 +
        this.add(text);
 +
    }
 +
}
 +
</code>
 
</pre>
 
</pre>
 +
</html>
  
 
=== Menús ===
 
=== Menús ===
Línia 471: Línia 572:
  
 
El menú es col·loca directament al Top-Level Container, obrint una nova branca de descendència a part del contingut Content.
 
El menú es col·loca directament al Top-Level Container, obrint una nova branca de descendència a part del contingut Content.
 +
 +
[[File: Contenidors1.png]]
 +
 +
 +
El menú a Swing es compon de diversos elements:
 +
 +
* '''JMenuBar''': És la barra de menú on es col·loquen les diferents entrades.
 +
 +
* '''Jmenu''': Cadascuna de les entrades a la barra de menú.
 +
 +
* '''JMenuItem''': Els diferents ítems dins de cada entrada del menú.
 +
 +
Per exemple es pot crear un menú de la següent manera
 +
 +
<pre>
 +
public class Menu extends JMenuBar implements ActionListener {
 +
    private JMenu fileMenu = null;
 +
    private JMenuItem exitMenuItem = null;
 +
 +
    public Menu() {
 +
        super();
 +
        initialize();
 +
    }
 +
 +
    private void initialize() {
 +
        fileMenu = new JMenu();
 +
        fileMenu.setText("Arxiu");
 +
        exitMenuItem = new JMenuItem();
 +
        exitMenuItem.setText("Exit");
 +
        exitMenuItem.addActionListener(this);
 +
        fileMenu.add(exitMenuItem);
 +
        this.add(fileMenu);
 +
    }
 +
 +
    public void actionPerformed(ActionEvent e) {
 +
        System.exit(0);
 +
    }
 +
}
 +
 +
 +
//Per afegir-lo al Top-Level Container
 +
 +
 +
    toplevelcontainer.setJMenuBar(new Menu());
 +
 +
</pre>
 +
 +
 +
=== Altres controls ===
 +
 +
==== JTable ====
 +
 +
Listeners  implementats
 +
 +
<pre>
 +
public class LaMevaTaula extends PlantillaVista implements ActionListener, ListSelectionListener, MouseListener {
 +
</pre>
 +
 +
 +
Components
 +
<pre>
 +
text = new JTextField(50);
 +
 +
String[] COLUMN_NAMES = {"Camp 1", "Camp 2", "Camp 3"};
 +
 +
dataModel = new DefaultTableModel(new Object[0][0], COLUMN_NAMES) {
 +
public boolean isCellEditable(int row, int col) { return false; }
 +
};
 +
 +
taula = new JTable(dataModel);
 +
taula.getSelectionModel().addListSelectionListener(this);
 +
taula.addMouseListener(this);
 +
DefaultTableCellRenderer leftRenderer = new DefaultTableCellRenderer();
 +
leftRenderer.setHorizontalAlignment( SwingConstants.LEFT );
 +
taula.getColumnModel().getColumn(0).setPreferredWidth(600);
 +
taula.getColumnModel().getColumn(0).setCellRenderer(leftRenderer);
 +
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
 +
centerRenderer.setHorizontalAlignment( SwingConstants.CENTER );
 +
taula.getColumnModel().getColumn(1).setPreferredWidth(100);
 +
taula.getColumnModel().getColumn(1).setCellRenderer(centerRenderer);
 +
taula.getColumnModel().getColumn(2).setPreferredWidth(100);
 +
taula.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
 +
taula.setIntercellSpacing(new Dimension(8,8));
 +
taula.setRowHeight(taula.getRowHeight()+10);
 +
taula.setFillsViewportHeight(true);
 +
taula.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 +
JScrollPane staula = new JScrollPane(taula);
 +
staula.setPreferredSize(new Dimension(800,100));
 +
staula.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
 +
staula.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
 +
</pre>
 +
 +
 +
Gestió esdeveniments
 +
 +
<pre>
 +
public void actionPerformed(ActionEvent e) {
 +
String textSenseEspais = text.getText().trim();
 +
 +
if ("Desar".equals(e.getActionCommand())) {
 +
if ("".equals(textSenseEspais)) {
 +
JOptionPane.showMessageDialog(pare, "Cal indicar alguna cosa", "Error", JOptionPane.ERROR_MESSAGE);
 +
} else {
 +
Object[] rowData = new Object[3];
 +
rowData[0] = text.getText();
 +
rowData[1] = 0;
 +
rowData[2] = dataModel.getRowCount();
 +
dataModel.addRow(rowData);
 +
text.setText("");
 +
}
 +
return;
 +
}
 +
 +
if ("Esborrar".equals(e.getActionCommand())) {
 +
int[] row = taula.getSelectedRows();
 +
if (row.length == 0) {
 +
JOptionPane.showMessageDialog(pare, "No hi ha cap fila seleccionada", "Error", JOptionPane.ERROR_MESSAGE);
 +
return;
 +
}
 +
for (int i = row.length - 1; i >= 0; i--) {
 +
JOptionPane.showMessageDialog(pare, "Fila esborrada " + (String) dataModel.getValueAt(row[i], 0), "Correcte", JOptionPane.INFORMATION_MESSAGE);
 +
dataModel.removeRow(row[i]);
 +
}
 +
return;
 +
}
 +
}
 +
 +
public void valueChanged(ListSelectionEvent e) {
 +
/* Canvia la selecció */
 +
int viewRow = taula.getSelectedRow();
 +
if (viewRow >= 0) {
 +
int modelRow = taula.convertRowIndexToModel(viewRow);
 +
text.setText((String) dataModel.getValueAt(modelRow, 0)); // Posar el valor de la fila seleccionada al camp de text
 +
}
 +
 +
}
 +
 +
public void mouseClicked(MouseEvent e) {
 +
/* Doble click */
 +
if (e.getClickCount() > 1) {
 +
int row = taula.getSelectedRow();
 +
int column = taula.getSelectedColumn();
 +
JOptionPane.showMessageDialog(pare, "Valor " + (String) dataModel.getValueAt(row, column), "Info", JOptionPane.INFORMATION_MESSAGE);
 +
}
 +
}
 +
 +
public void mouseEntered(MouseEvent e) {}
 +
 +
public void mouseExited(MouseEvent e) {}
 +
 +
public void mousePressed(MouseEvent e) {}
 +
 +
public void mouseReleased(MouseEvent e) {}
 +
</pre>
 +
 +
 +
==== JDialog ====
 +
 +
 +
Crida per obrir el diàleg i capturar resposta (Click en un botó "Obrir")
 +
 +
<pre>
 +
if ("Obrir".equals(e.getActionCommand())) {
 +
      ExempleDialog dialeg = new ExempleDialog(pare, "Titol dialeg exemple", this);
 +
      PanellDialeg content = new PanellDialeg(dialeg);
 +
      dialeg.setContentPane(content);
 +
      dialeg.setVisible(true);
 +
      if (dialeg.getResultat() == true) {
 +
          // Accions si OK ...
 +
      }
 +
}
 +
 +
</pre>
 +
 +
 +
Codi del diàleg
 +
 +
 +
<pre>
 +
 +
public class ExempleDialog extends JDialog {
 +
    private boolean resultat;
 +
 
 +
    public ExempleDialog(JFrame pare, String titol, Component rel) {
 +
        super(pare, titol, true);
 +
        resultat = false;
 +
     
 +
        this.setLocationRelativeTo(rel);
 +
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
 +
        this.setSize(new Dimension(400,400));
 +
        this.setMinimumSize(new Dimension(350,400));
 +
    }
 +
 
 +
    public boolean getResultat() {
 +
        return resultat;
 +
    }
 +
 
 +
    public void tancarDialeg(boolean correcte) {
 +
        resultat = correcte;
 +
        setVisible(false);
 +
        dispose();
 +
    }
 +
}
 +
 +
</pre>
 +
 +
 +
Codi del panell del diàleg
 +
 +
 +
<pre>
 +
 +
public class PanellDialeg extends JPanel implements ActionListener {
 +
    private ExempleDialog dialeg;
 +
    private JButton btnOk;
 +
    private JButton btnKo;
 +
     
 +
    public PanellDialeg(ExempleDialog dialeg) {
 +
        this.dialeg = dialeg;
 +
        initalizePanel();
 +
    }
 +
 +
    private void initalizePanel() {
 +
        this.setLayout(new BorderLayout());
 +
        JLabel ltitol = new JLabel("Exemple");
 +
        this.add(ltitol, BorderLayout.NORTH);
 +
 +
        JPanel sur = new JPanel(new GridLayout(0,2));
 +
        btnOk = new JButton("Desar");
 +
        btnKo = new JButton("Cancelar");
 +
        btnOk.addActionListener(this);
 +
        btnKo.addActionListener(this);
 +
        sur.add(btnOk);
 +
        sur.add(btnKo);
 +
 +
        this.add(sur, BorderLayout.SOUTH);
 +
    }
 +
 
 +
    public void panelInitialFocus() {
 +
        btnOk.requestFocusInWindow();
 +
    }
 +
 
 +
    public void actionPerformed(ActionEvent e) {
 +
        if ("Desar".equals(e.getActionCommand())) dialeg.tancarDialeg(true);
 +
        else dialeg.tancarDialeg(false);
 +
    }
 +
 +
}
 +
 +
</pre>
 +
 +
 +
==== JXDatePicker ====
 +
 +
 +
Llibreria SwingX que inclou components millorats i ampliacions de java Swing (La tendència actual sembla la migració a JavaFX)
 +
 +
 +
https://swingx.java.net/
 +
 +
 +
Per exemple
 +
 +
<pre>
 +
JXDatePicker dateQualsevol = new JXDatePicker(new Date());
 +
dateQualsevol.setName("datePicker");
 +
dateQualsevol.setLinkDay(new Date(), "Data {0}");
 +
dateQualsevol.addActionListener(this);
 +
</pre>
 +
 +
=== Transformació JFrame a JApplet ===
 +
 +
Pas 1. Canviar l'herència
 +
 +
Pas 2. Posar el codi d'inicialització al mètode init( ) de l'Applet
 +
 +
Pas 3. Posar el codi de finalització (Si hi ha) al mètode stop( ) de l'Applet
 +
 +
pas 4. Esborrar operacions específiques de Jframe (setVisible per exemple)
 +
 +
pas 5. Esborrar elements específics d'aplicacions d'escriptori (Botó sortir per exemple o menús)

Revisió de 13:38, 10 feb 2021

torna M3 - Programació

Interfícies gràfiques. GUI

Introducció

Un dels aspectes importants actualment alhora de crear aplicacions és la part gràfica, a continuació es descriuen els mecanismes bàsics de Java per al desenvolupament de GUI (Graphic User Interface).

Una GUI és una Interfase que permet a l’usuari comunicar-se amb el sistema.

Les aplicacions d’entorn gràfic de Java es componen de tres conceptes que es relacionen

Contenidors + Components + Esdeveniments

JFC (Java Foundation Classes) inclou les característiques necessàries per crear GUI. Els paquets que s’utilitzen habitualment per a desenvolupar aplicacions gràfiques són

  • java.awt.*: Abstract Window Toolkit. Components gràfics del SDK per crear GUI.
  • java.awt.event.*: Tractament dels esdeveniments associats
  • javax.swing.*: Ampliació dels components gràfics per crear GUI

Java és un llenguatge multiplataforma i per tant les seves eines gràfiques són també multiplataforma.

Enllaç bàsic i indispensable!!! http://java.sun.com/docs/books/tutorial/uiswing/index.html

Contenidors

Un contenidor és un element base, dins del qual es poden afegir altres elements, els contenidors també actuen com components i es poden afegir dins altres contenidors.

Els Contenidors hereten de la classe abstracta java.awt.Container. Exemples són:

  • Frames (classe javax.swing.JFrame). Finestra principal
  • Panels (classe javax.swing.JPanel). Panells on col·locar els components dins la finestra
  • Applets (classe javax.swing.JApplet). Applets per afegir a pàgines web.


public class FrameSimple extends JFrame {

	private static final long serialVersionUID = 1L;

	public FrameSimple() {
		super();
		initialize();
	}

	private void initialize() {
		setTitle("Simple Frame"); // Títol de la finestra
		setSize(350, 200); // Tamany
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// pack(); // Ajusta la finestra a la mida dels controls, però ara no en té
		setVisible(true); // Mostra
	}

	public static void main(String[] args) {
		new FrameSimple();
	}

}

Nivells de contenidors

Java utilitza una estructura per nivells per col·locar els diferents elements gràfics, abans de començar a col·locar els components cal estructurar el contenidor.

Normalment el primer contenidor serà un JFrame o JApplet, anomenats Top-Level Containers, i a partir d’aquest es crea una estructura jeràrquica amb diferents contenidors.

Contenidors1.png


Per exemple una estructura típica inclou un JFrame dins del qual tenim per una banda el contenidor (ContentPane) on s’afegeixen els diferents components i un menú.


El ContentPane es pot crear a partir d’un JPanel per exemple setContentPane(contentPane) o obtenir el que hi ha per defecte toplevelContainer.getContentPane(): Container.


        JPanel contentPane = new JPanel(new BorderLayout());

        JLabel label = new JLabel("Hola"); // Crem una etiqueta amb text 'Hola'
        contentPane.add(label, BorderLayout.CENTER); // Afegim la etiqueta al centre del panel
       
        setContentPane(contentPane); // Afegim el panel al Frame

Components

Un component és tot allò que es pot pintar a una pantalla i és susceptible de rebre esdeveniments.

Hi ha molts tipus de components o controls, tants com et puguis imaginar.

  • Etiquetes de text. Classe javax.swing.JLabel
  • Botons. Classe javax.swing.JButon
  • Àrees de text. Classe javax.swing.JTextField
  • Selecció. Classe javax.swing.JChoice
  • Checkboxes. Classe javax.swing.JCheckbox. Agrupats o no en un CheckboxGroup (classe java.awt.CheckboxGroup)
  • Llistes. Classe java.swing.JList
  • Menús. Classe javax.swing.JMenu
  • Selector de color. Classe javax.swing.JColorChooser
  • Selector de fitxers. Classe javax.swing.JFileChooser

Components1.png


public class Contenidor extends JPanel {
    public Contenidor() {
        super();
        JLabel etiqueta = new JLabel( "Etiqueta qualsevol", SwingConstants.CENTER );
        etiqueta.setBackground(Color.CYAN);
        etiqueta.setForeground(new Color(255,0,0));
        etiqueta.setOpaque(true);
        etiqueta.setFont(new Font("SansSerif", Font.BOLD, 24));
        this.add(etiqueta);
        JTextArea text = new JTextArea("Camp de Text", 10, 10);
        this.add(text);
        JButton boto = new JButton( "Acció1" );
        this.add(boto);
    }
}

// Afegir el contenidor al Top-Level
// this.setContentPane(new Contenidor());

Organitzadors de components

Els Layout managers (Organitzadors de components), s’encarreguen de gestionar l’esquema general dels components dins els contenidors (a la pantalla), dimensions, alineació, etc...

Els principals són:

Border.png java.awt.BorderLayout. Administrador per defecte dels contenidors Frames. Depenent de la zona respecta o no les dimensions dels components
Flow.png java.awt.FlowLayout. Administrador per defecte dels contenidors Panels. Els components es disposen un darrera l’altre, per ordre i quan no caben una nova línia, respecta dimensions dels components
Grid.png java.awt.GridLayout. Disposa els elements en una matriu de files i columnes. No respecta dimensions dels components
Spring1.png Spring2.png java.awt.SpringLayout. És molt flexible, es basa en disposar els elements respecte altres elements o respecte el propi contenidor. Més complex de configurar que els anteriors, però necessari per dissenyar interfícies complexes.
Sense contenidor null, També és possible crear un contenidor sense organitzador. És poc recomanable

Exemples,


//Exemple BorderLayout

        this.setLayout(new BorderLayout());
               
        JButton boto1 = new JButton( "boto1" );
        JButton boto2 = new JButton( "boto2");
        JButton boto3 = new JButton( "boto3" );
               
        this.add(boto1, BorderLayout.NORTH);
        this.add(boto2, BorderLayout.SOUTH );
        this.add(boto3, BorderLayout.CENTER);

//Exemple FlowLayout

        this.setLayout(new FlowLayout());
           
        JButton boto1 = new JButton( "boto1" );
        JButton boto2 = new JButton( "boto2" );
        JButton boto3 = new JButton( "boto3" );
           
        this.add(boto1);
        this.add(boto2);
        this.add(boto3);

//Exemple GridLayout

        this.setLayout(new GridLayout(0, 2)); // files (0-Tantes com necessàries) i columnes
               
        JButton boto1 = new JButton( "boto1" );
        JButton boto2 = new JButton( "boto2");
        JButton boto3 = new JButton( "boto3" );
           
        this.add(boto1);
        this.add(boto2);
        this.add(boto3);

//Exemple SpringLayout

        SpringLayout layout = new SpringLayout();
        this.setLayout(layout);
               
        JButton boto1 = new JButton( "boto1" );
        JButton boto2 = new JButton( "boto2");
               
        layout.putConstraint(SpringLayout.WEST, boto1, 5, SpringLayout.WEST, this);
        // Est del botó 1 a 5 de l'est del contenidor
        layout.putConstraint(SpringLayout.NORTH, boto1, 10, SpringLayout.NORTH, this);
        // Nord del botó 1 a 10 del nord del contenidor
        layout.putConstraint(SpringLayout.WEST, boto2, 0, SpringLayout.WEST, boto1);
        // Est del botó 2 igual que est botó 1
        layout.putConstraint(SpringLayout.NORTH, boto2, 10, SpringLayout.SOUTH, boto1);
        // Nord del botó 1 a 10 del nord del contenidor

        this.add(boto1);
        this.add(boto2);

Aparença (Look and Feel)

L’arquitectura de Swing permet modificar l’aparença de l’aplicació i adaptar-la a diferents entorns, així es disposa de les següents configuracions:

  • CrossPlatformLookAndFeel: L’aparença de Java per defecte (“Metal”) és igual per a totes les plataformes.
  • SystemLookAndFeel: L’aparença de la plataforma on s’executa l’aplicació.
  • Synth: Permet crear una aparença personalitzada a partir d’un fitxer XML.
  • Multiplexing: Per mantenir múltiples aparences alhora.

Per exemple,


public class LookAndFeels {

	public static void main(String[] args) throws Exception {

		System.out.println("Default LookAndFeel:");
		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

		int x = 0;
		int y = 0;

		System.out.println("Installed LookAndFeels:");

		for (LookAndFeelInfo lfInfo : UIManager.getInstalledLookAndFeels()) {
			
			String lfClass = lfInfo.getClassName();
			System.out.println(lfClass);
			UIManager.setLookAndFeel(lfClass);

			// Fem una finestra d'exemple
			JFrame window = new FrameSimple();
			window.setTitle(lfInfo.getName());
			window.setLocation(x, y);
			x += 50;
			y += 50;
		}
	}
}

Esdeveniments

Un esdeveniment és qualsevol acció que pot ser tractada pel programa, els esdeveniments són activats per alguna acció de l’usuari (Polsar un botó, prémer una tecla, maximitzar una finestra) i són detectats i comunicats a l’aplicació pel sistema Operatiu.

Sistema de delegació d’esdeveniments

Java tracta els esdeveniments de manera delegada, on intervenen

  • Font de l’esdeveniment, control sobre el qual es produeix l’esdeveniment
  • Esdeveniment (Event), generat per una acció de l’usuari sobre un control
  • Controlador d’esdeveniments o oient (Listener), objecte associat al control, que gestiona els esdeveniments.

La font de l’esdeveniment crea un objecte Event que envia al controlador, i aquest respon a l’esdeveniment, en aquest sentit es diu que el control delega la gestió de l’esdeveniment.

Els paquets utilitzats per a la gestió d’esdeveniments són:

java.awt.event

javax.swing.event (Classes i interfases afegides a l’anterior)

Dins els paquets hi ha:

  • Les classes per gestionar els objectes esdeveniments (Sufix Event).
  • Les interfases controladores d’esdeveniments, cal implementar-ne tots els mètodes (Sufix Listener)
  • Classe abstractes que implementen els mètodes dels controladors buits, per evitar haver d’implementar tots els mètodes de les interfases que en tenen més d’un (Sufix Adapter)

En una aplicació un controlador pot gestionar varis esdeveniments si implementa vàries interfaces, però només un si hereta l'adaptador corresponent.

Per exemple en el cas d’un botó, l’esdeveniment habitual és ActionEvent, i el controlador que gestiona aquests tipus d'esdeveniments és el ActionListener, que només té un mètode:

void actionPerformed(ActionEvent e)

Primer cal implementar el controlador


class CtrlEvent implements ActionListener

Després cal afegir una instància d’aquest com a controlador d’un o múltiples components, cada component tindrà els seus mètodes per afegir controladors que corresponguin.


Componentqualsevol.addActionListener(new CtrlEvent());

Finalment cal escriure els mètodes del controlador que interessin.


class ECtrlEvent implements ActionListener {

      public void actionPerformed(ActionEvent e) {

             System.out.println("actionPerformed()");

      }
}

A la següent taula es mostra les Classes i Interfaces més comuns

Control Classe Mètode Esdeveniment Interface o Adapter
Finestres JFrame void addWindowListener(WindowListener l) WindowEvent WindowListener


WindowAdapter

Botons JButton void addActionListener(ActionListener l) ActionEvent ActionListener
Check Box JCheckbox void addItemListener(ItemListener l) ItemEvent ItemListener
List JList void addListSelectionListener(ListSelectionListener listener) ListSelectionEvent ListSelectionListener
Text Field JTextField void addCaretListener(CaretListener listener) CaretEvent CaretListener
Text Area JTextArea void addCaretListener(CaretListener listener) CaretEvent CaretListener


Els esdeveniment del ratolí es poden programar sobre qualsevol control donat que s’hereten de la classe ComponentEvent.


Control Mètode Esdeveniment Interface o Adapter
Ratolí void addMouseListener(MouseListener l) MouseEvent MouseListener


MouseAdapter

Ratolí void addMouseMotionListener(MouseMotionListener l) MouseEvent MouseMotionListener


MouseMotionAdapter


Per exemple, es pot implmentar el controlador en el propi contenidor


public class Contenidor extends JPanel implements ActionListener {
    private JButton boto1;
    private JButton boto2;
    private JLabel text;
   
    public Contenidor() {
        super();
        boto1 = new JButton( "Acció1" );
        boto1.addActionListener(this);
        boto2 = new JButton( "Acció2" );
        boto2.addActionListener(this);
        text = new JLabel("Text qualsevol");
       
        this.add(boto1);
        this.add(boto2);
        this.add(text);
    }

    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        if ("Acció1".equals(e.getActionCommand()))
            text.setText("botó 1 clicat");
        if ("Acció2".equals(e.getActionCommand()))
            text.setText("botó 2 clicat");
           
    }
}

O també es pot implementar en una classe específica


public class Contenidor extends JPanel {
    private JButton boto1;
    private JButton boto2;
    private JLabel text;
   
    public Contenidor() {
        super();
        boto1 = new JButton( "Acció1" );
        boto2 = new JButton( "Acció2" );
        text = new JLabel("Text qualsevol");
        boto1.addActionListener(new Esdeveniments(text));
        boto2.addActionListener(new Esdeveniments(text));
       
        this.add(boto1);
        this.add(boto2);
        this.add(text);
    }
}

class Esdeveniments implements ActionListener {
    private JLabel text;
   
    public Esdeveniments (JLabel text) {
        this.text = text;
    }
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        if ("Acció1".equals(e.getActionCommand()))
            text.setText("botó 1 clicat");
        if ("Acció2".equals(e.getActionCommand()))
            text.setText("botó 2 clicat");
    }
}

O també amb una classe anònima


public class Contenidor extends JPanel {
    private JButton boto1;
    private JButton boto2;
    private JLabel text;
   
    public Contenidor() {
        super();
        boto1 = new JButton( "Acció1" );
        boto2 = new JButton( "Acció2" );
        text = new JLabel("Text qualsevol");
        boto1.addActionListener(new ActionListener() {
 
            public void actionPerformed(ActionEvent e)
            {
                //Execute when button is pressed
                System.out.println("You clicked the button");
            }
        });
      
        this.add(boto1);
        this.add(text);
    }
}

Menús

Els menús són un tipus de control més, la diferència amb la resta és la situació dins la jerarquia d’elements.

El menú es col·loca directament al Top-Level Container, obrint una nova branca de descendència a part del contingut Content.

Contenidors1.png


El menú a Swing es compon de diversos elements:

  • JMenuBar: És la barra de menú on es col·loquen les diferents entrades.
  • Jmenu: Cadascuna de les entrades a la barra de menú.
  • JMenuItem: Els diferents ítems dins de cada entrada del menú.

Per exemple es pot crear un menú de la següent manera

public class Menu extends JMenuBar implements ActionListener {
    private JMenu fileMenu = null;
    private JMenuItem exitMenuItem = null;

    public Menu() {
        super();
        initialize();
    }

    private void initialize() {
        fileMenu = new JMenu();
        fileMenu.setText("Arxiu");
        exitMenuItem = new JMenuItem();
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(this);
        fileMenu.add(exitMenuItem);
        this.add(fileMenu);
    }

    public void actionPerformed(ActionEvent e) {
        System.exit(0);
    }
}


//Per afegir-lo al Top-Level Container


     toplevelcontainer.setJMenuBar(new Menu());


Altres controls

JTable

Listeners implementats

public class LaMevaTaula extends PlantillaVista implements ActionListener, ListSelectionListener, MouseListener {


Components

text = new JTextField(50);

String[] COLUMN_NAMES = {"Camp 1", "Camp 2", "Camp 3"};

dataModel = new DefaultTableModel(new Object[0][0], COLUMN_NAMES) {
	public boolean isCellEditable(int row, int col) { return false; }
};

taula = new JTable(dataModel);
taula.getSelectionModel().addListSelectionListener(this);
taula.addMouseListener(this);
DefaultTableCellRenderer leftRenderer = new DefaultTableCellRenderer();
leftRenderer.setHorizontalAlignment( SwingConstants.LEFT );
taula.getColumnModel().getColumn(0).setPreferredWidth(600);
taula.getColumnModel().getColumn(0).setCellRenderer(leftRenderer);
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment( SwingConstants.CENTER );
taula.getColumnModel().getColumn(1).setPreferredWidth(100);
taula.getColumnModel().getColumn(1).setCellRenderer(centerRenderer);
taula.getColumnModel().getColumn(2).setPreferredWidth(100);
taula.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
taula.setIntercellSpacing(new Dimension(8,8));
taula.setRowHeight(taula.getRowHeight()+10);
taula.setFillsViewportHeight(true);
taula.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane staula = new JScrollPane(taula);
staula.setPreferredSize(new Dimension(800,100));
staula.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
staula.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);


Gestió esdeveniments

public void actionPerformed(ActionEvent e) {
		String textSenseEspais = text.getText().trim();

		if ("Desar".equals(e.getActionCommand())) {
			if ("".equals(textSenseEspais)) {
				JOptionPane.showMessageDialog(pare, "Cal indicar alguna cosa", "Error", JOptionPane.ERROR_MESSAGE);
			} else {
				Object[] rowData = new Object[3];
				rowData[0] = text.getText();
				rowData[1] = 0;
				rowData[2] = dataModel.getRowCount();
				dataModel.addRow(rowData);	
				text.setText("");
			}
			return;
		}

		if ("Esborrar".equals(e.getActionCommand())) {
			int[] row = taula.getSelectedRows();
			if (row.length == 0) {
				JOptionPane.showMessageDialog(pare, "No hi ha cap fila seleccionada", "Error", JOptionPane.ERROR_MESSAGE);
				return;
			}
			for (int i = row.length - 1; i >= 0; i--) {
				JOptionPane.showMessageDialog(pare, "Fila esborrada " + (String) dataModel.getValueAt(row[i], 0), "Correcte", JOptionPane.INFORMATION_MESSAGE);
				dataModel.removeRow(row[i]);
			}
			return;
		}
	}

	public void valueChanged(ListSelectionEvent e) {
		/* Canvia la selecció */
		int viewRow = taula.getSelectedRow();
		if (viewRow >= 0) {
			int modelRow = taula.convertRowIndexToModel(viewRow);
			text.setText((String) dataModel.getValueAt(modelRow, 0)); // Posar el valor de la fila seleccionada al camp de text
		}

	}

	public void mouseClicked(MouseEvent e) {
		/* Doble click */
		if (e.getClickCount() > 1) {
			int row = taula.getSelectedRow();
			int column = taula.getSelectedColumn();
			JOptionPane.showMessageDialog(pare, "Valor " + (String) dataModel.getValueAt(row, column), "Info", JOptionPane.INFORMATION_MESSAGE);
		}
	}

	public void mouseEntered(MouseEvent e) {}

	public void mouseExited(MouseEvent e) {}

	public void mousePressed(MouseEvent e) {}

	public void mouseReleased(MouseEvent e) {}


JDialog

Crida per obrir el diàleg i capturar resposta (Click en un botó "Obrir")

if ("Obrir".equals(e.getActionCommand())) {
      ExempleDialog dialeg = new ExempleDialog(pare, "Titol dialeg exemple", this);
      PanellDialeg content = new PanellDialeg(dialeg);
      dialeg.setContentPane(content);
      dialeg.setVisible(true);
      if (dialeg.getResultat() == true) {
           // Accions si OK ...
      }
}


Codi del diàleg



public class ExempleDialog extends JDialog {
    private boolean resultat;
   
    public ExempleDialog(JFrame pare, String titol, Component rel) {
        super(pare, titol, true);
        resultat = false;
       
        this.setLocationRelativeTo(rel);
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        this.setSize(new Dimension(400,400));
        this.setMinimumSize(new Dimension(350,400));
    }
   
    public boolean getResultat() {
        return resultat;
    }
   
    public void tancarDialeg(boolean correcte) {
        resultat = correcte;
        setVisible(false);
        dispose();
    }
}


Codi del panell del diàleg



public class PanellDialeg extends JPanel implements ActionListener {
    private ExempleDialog dialeg;
    private JButton btnOk;
    private JButton btnKo;
       
    public PanellDialeg(ExempleDialog dialeg) {
        this.dialeg = dialeg;
        initalizePanel();
    }

    private void initalizePanel() {
        this.setLayout(new BorderLayout());
        JLabel ltitol = new JLabel("Exemple");
        this.add(ltitol, BorderLayout.NORTH);

        JPanel sur = new JPanel(new GridLayout(0,2));
        btnOk = new JButton("Desar");
        btnKo = new JButton("Cancelar");
        btnOk.addActionListener(this);
        btnKo.addActionListener(this);
        sur.add(btnOk);
        sur.add(btnKo);

        this.add(sur, BorderLayout.SOUTH);
    }
   
    public void panelInitialFocus() {
        btnOk.requestFocusInWindow();
    }
   
    public void actionPerformed(ActionEvent e) {
        if ("Desar".equals(e.getActionCommand())) dialeg.tancarDialeg(true);
        else dialeg.tancarDialeg(false);
    }

}


JXDatePicker

Llibreria SwingX que inclou components millorats i ampliacions de java Swing (La tendència actual sembla la migració a JavaFX)


https://swingx.java.net/


Per exemple

JXDatePicker dateQualsevol = new JXDatePicker(new Date()); 
dateQualsevol.setName("datePicker"); 
dateQualsevol.setLinkDay(new Date(), "Data {0}");
dateQualsevol.addActionListener(this);

Transformació JFrame a JApplet

Pas 1. Canviar l'herència

Pas 2. Posar el codi d'inicialització al mètode init( ) de l'Applet

Pas 3. Posar el codi de finalització (Si hi ha) al mètode stop( ) de l'Applet

pas 4. Esborrar operacions específiques de Jframe (setVisible per exemple)

pas 5. Esborrar elements específics d'aplicacions d'escriptori (Botó sortir per exemple o menús)