Diferència entre revisions de la pàgina «DAM-M3-UF5. Interfícies Gràfiques d'Usuari (GUI)»
(→Contenidors) |
(→Sistema de delegació d’esdeveniments) |
||
(Hi ha 16 revisions intermèdies del mateix usuari 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> | <html> | ||
Línia 75: | 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 | + | 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()); | ||
− | + | ||
− | JLabel | + | JLabel label = new JLabel("Hola"); // Crem una etiqueta amb text 'Hola' |
− | contentPane.add( | + | contentPane.add(label, BorderLayout.CENTER); // Afegim la etiqueta al centre del panel |
− | + | setContentPane(contentPane); // Afegim el panel al Frame | |
+ | </code> | ||
</pre> | </pre> | ||
+ | </html> | ||
=== Components === | === Components === | ||
Línia 101: | 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 | + | * '''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 139: | 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 150: | Línia 156: | ||
{| border="1" | {| border="1" | ||
| [[File: border.png]] | | [[File: border.png]] | ||
− | | | + | | <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]] | ||
− | | | + | | <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]] | ||
− | | | + | | <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]] | ||
− | | | + | | <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 | ||
− | | | + | | <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 223: | 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 239: | Línia 248: | ||
Per exemple, | Per exemple, | ||
− | < | + | <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 256: | 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 268: | 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 276: | 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: | ||
− | + | <code>java.awt.event</code> | |
− | + | <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 | + | 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: |
− | + | <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 317: | 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 330: | Línia 384: | ||
|- | |- | ||
| Finestres | | Finestres | ||
− | | JFrame | + | | <code>JFrame</code> |
− | | | + | | <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 383: | 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 404: | 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 432: | 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 471: | Línia 530: | ||
} | } | ||
} | } | ||
+ | </code> | ||
</pre> | </pre> | ||
+ | </html> | ||
O també amb una classe anònima | O també amb una classe anònima | ||
+ | <html> | ||
<pre> | <pre> | ||
+ | <code class='java'> | ||
public class Contenidor extends JPanel { | public class Contenidor extends JPanel { | ||
private JButton boto1; | private JButton boto1; | ||
Línia 499: | Línia 562: | ||
} | } | ||
} | } | ||
− | + | </code> | |
</pre> | </pre> | ||
+ | </html> | ||
=== Menús === | === Menús === |
Revisió de 13:38, 10 feb 2021
torna M3 - Programació
Contingut
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.
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 unCheckboxGroup
(classejava.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
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:
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
|
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
|
Ratolí | void addMouseMotionListener(MouseMotionListener l)
|
MouseEvent
|
MouseMotionListener
|
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.
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)
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)