Activitats

Estructura d'objectes d'una GUI

L’objectiu d’aquesta activitat és estudiar quina és l’estructura que conformen els objectes associats a una interfície gràfica, a partir de la identificació dels diferents contenidors, controls i layouts existents i les relacions entre ells.

Genereu l’estructura que conformen tots els objectes associats a la interfície gràfica següent:

Figura Interfície pertanyent al programari lliure gISOMount, una aplicació per muntar fitxers amb imatges ISO i poder accedir-hi com si es tractés d’un CD normal

Una possible interpretació de la interfície mostrada, donades les classes existents al paquet Swing, pot ser la següent:

Figura

Barra de menús

L’objectiu d’aquesta activitat és generar una barra de menús completa per a una aplicació gràfica.

Trieu una aplicació qualsevol típica d’escriptori, com pot ser un editor de text, un full de càlcul, un navegador web… Genereu manualment el codi Java per representar una finestra amb una barra de menús completa (amb cadascun dels seus menús i submenús) exactament igual. Això implica la inclusió d’icones davant algunes opcions de menú, o representar-ne l’estat per defecte (habilitat/deshabilitat).

Com a exemple de solució s’ha triat la barra d’eines del navegador Mozilla Firefox. Donada la seva complexitat, només es mostra la creació del menú “Visualitza”, que inclou tots els elements típics (submenús, dreceres, separadors, selectors…). Aquest codi s’ha generat amb l’editor gràfic del Netbeans.

Classe MenuFirefox.java

  1. public class BarraFirefox extends javax.swing.JFrame {
  2.  
  3. public BarraFirefox() {
  4. initComponents();
  5. }
  6.  
  7. private void initComponents() {
  8.  
  9. jMenuBar1 = new javax.swing.JMenuBar();
  10. jMenu1 = new javax.swing.JMenu();
  11. jMenu2 = new javax.swing.JMenu();
  12. jMenu7 = new javax.swing.JMenu();
  13. jMenu8 = new javax.swing.JMenu();
  14. jCheckBoxMenuItem1 = new javax.swing.JCheckBoxMenuItem();
  15. jCheckBoxMenuItem2 = new javax.swing.JCheckBoxMenuItem();
  16. jCheckBoxMenuItem3 = new javax.swing.JCheckBoxMenuItem();
  17. jCheckBoxMenuItem4 = new javax.swing.JCheckBoxMenuItem();
  18. jSeparator3 = new javax.swing.JPopupMenu.Separator();
  19. jCheckBoxMenuItem5 = new javax.swing.JCheckBoxMenuItem();
  20. jSeparator4 = new javax.swing.JPopupMenu.Separator();
  21. jMenuItem2 = new javax.swing.JMenuItem();
  22. jMenu9 = new javax.swing.JMenu();
  23. jMenuItem3 = new javax.swing.JMenuItem();
  24. jMenuItem4 = new javax.swing.JMenuItem();
  25. jSeparator1 = new javax.swing.JPopupMenu.Separator();
  26. jMenu10 = new javax.swing.JMenu();
  27. jMenuItem5 = new javax.swing.JMenuItem();
  28. jMenuItem6 = new javax.swing.JMenuItem();
  29. jSeparator5 = new javax.swing.JPopupMenu.Separator();
  30. jMenuItem7 = new javax.swing.JMenuItem();
  31. jSeparator6 = new javax.swing.JPopupMenu.Separator();
  32. jMenuItem8 = new javax.swing.JMenuItem();
  33. jMenu11 = new javax.swing.JMenu();
  34. jRadioButtonMenuItem1 = new javax.swing.JRadioButtonMenuItem();
  35. jRadioButtonMenuItem2 = new javax.swing.JRadioButtonMenuItem();
  36. jMenu12 = new javax.swing.JMenu();
  37. jSeparator2 = new javax.swing.JPopupMenu.Separator();
  38. jMenuItem1 = new javax.swing.JMenuItem();
  39. jMenu3 = new javax.swing.JMenu();
  40. jMenu4 = new javax.swing.JMenu();
  41. jMenu5 = new javax.swing.JMenu();
  42. jMenu6 = new javax.swing.JMenu();
  43.  
  44. setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
  45.  
  46. jMenu1.setText("Fitxer");
  47. jMenuBar1.add(jMenu1);
  48.  
  49. jMenu2.setText("Edita");
  50. jMenuBar1.add(jMenu2);
  51.  
  52. jMenu7.setText("Visualitza");
  53.  
  54. jMenu8.setText("Barra d'eines");
  55.  
  56. jCheckBoxMenuItem1.setSelected(true);
  57. jCheckBoxMenuItem1.setText("Barra del menú");
  58. jMenu8.add(jCheckBoxMenuItem1);
  59.  
  60. jCheckBoxMenuItem2.setSelected(true);
  61. jCheckBoxMenuItem2.setText("Barra de navegació");
  62. jMenu8.add(jCheckBoxMenuItem2);
  63.  
  64. jCheckBoxMenuItem3.setSelected(true);
  65. jCheckBoxMenuItem3.setText("Barra de les adreces d'interés");
  66. jMenu8.add(jCheckBoxMenuItem3);
  67.  
  68. jCheckBoxMenuItem4.setText("Barra de complements");
  69. jMenu8.add(jCheckBoxMenuItem4);
  70. jMenu8.add(jSeparator3);
  71.  
  72. jCheckBoxMenuItem5.setSelected(true);
  73. jCheckBoxMenuItem5.setText("Les pestanyes a dalt");
  74. jMenu8.add(jCheckBoxMenuItem5);
  75. jMenu8.add(jSeparator4);
  76.  
  77. jMenuItem2.setText("Personalitza...");
  78. jMenu8.add(jMenuItem2);
  79.  
  80. jMenu7.add(jMenu8);
  81.  
  82. jMenu9.setText("Barra lateral");
  83.  
  84. jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_B, java.awt.event.InputEvent.CTRL_MASK));
  85. jMenuItem3.setText("Adreçes d'interès");
  86. jMenu9.add(jMenuItem3);
  87.  
  88. jMenuItem4.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_H, java.awt.event.InputEvent.CTRL_MASK));
  89. jMenuItem4.setText("Historial");
  90. jMenu9.add(jMenuItem4);
  91.  
  92. jMenu7.add(jMenu9);
  93. jMenu7.add(jSeparator1);
  94.  
  95. jMenu10.setText("Mida de la pàgina");
  96.  
  97. jMenuItem5.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_PLUS, java.awt.event.InputEvent.CTRL_MASK));
  98. jMenuItem5.setText("Augmenta");
  99. jMenu10.add(jMenuItem5);
  100.  
  101. jMenuItem6.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_MINUS, java.awt.event.InputEvent.CTRL_MASK));
  102. jMenuItem6.setText("Redueix");
  103. jMenu10.add(jMenuItem6);
  104. jMenu10.add(jSeparator5);
  105.  
  106. jMenuItem7.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_0, java.awt.event.InputEvent.CTRL_MASK));
  107. jMenuItem7.setText("Reinicia");
  108. jMenu10.add(jMenuItem7);
  109. jMenu10.add(jSeparator6);
  110.  
  111. jMenuItem8.setText("Augmenta el text només");
  112. jMenu10.add(jMenuItem8);
  113.  
  114. jMenu7.add(jMenu10);
  115.  
  116. jMenu11.setText("Estil de la pàgina");
  117.  
  118. jRadioButtonMenuItem1.setSelected(true);
  119. jRadioButtonMenuItem1.setText("Sense estil");
  120. jMenu11.add(jRadioButtonMenuItem1);
  121.  
  122. jRadioButtonMenuItem2.setText("Estil de pàgina bàsic");
  123. jMenu11.add(jRadioButtonMenuItem2);
  124.  
  125. jMenu7.add(jMenu11);
  126.  
  127. jMenu12.setText("Codificació de caràcters");
  128. jMenu7.add(jMenu12);
  129. jMenu7.add(jSeparator2);
  130.  
  131. jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F11, 0));
  132. jMenuItem1.setText("Pantalla completa");
  133. jMenu7.add(jMenuItem1);
  134.  
  135. jMenuBar1.add(jMenu7);
  136.  
  137. jMenu3.setText("Historial");
  138. jMenuBar1.add(jMenu3);
  139.  
  140. jMenu4.setText("Adreces d'Interés");
  141. jMenuBar1.add(jMenu4);
  142.  
  143. jMenu5.setText("Eines");
  144. jMenuBar1.add(jMenu5);
  145.  
  146. jMenu6.setText("Ajuda");
  147. jMenuBar1.add(jMenu6);
  148.  
  149. setJMenuBar(jMenuBar1);
  150.  
  151. javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
  152. getContentPane().setLayout(layout);
  153. layout.setHorizontalGroup(
  154. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  155. .addGap(0, 400, Short.MAX_VALUE)
  156. );
  157. layout.setVerticalGroup(
  158. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  159. .addGap(0, 279, Short.MAX_VALUE)
  160. );
  161.  
  162. pack();
  163. }
  164.  
  165. public static void main(String args[]) {
  166. java.awt.EventQueue.invokeLater(new Runnable() {
  167. public void run() {
  168. new BarraFirefox().setVisible(true);
  169. }
  170. });
  171. }
  172.  
  173. private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem1;
  174. private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem2;
  175. private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem3;
  176. private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem4;
  177. private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem5;
  178. private javax.swing.JMenu jMenu1;
  179. private javax.swing.JMenu jMenu10;
  180. private javax.swing.JMenu jMenu11;
  181. private javax.swing.JMenu jMenu12;
  182. private javax.swing.JMenu jMenu2;
  183. private javax.swing.JMenu jMenu3;
  184. private javax.swing.JMenu jMenu4;
  185. private javax.swing.JMenu jMenu5;
  186. private javax.swing.JMenu jMenu6;
  187. private javax.swing.JMenu jMenu7;
  188. private javax.swing.JMenu jMenu8;
  189. private javax.swing.JMenu jMenu9;
  190. private javax.swing.JMenuBar jMenuBar1;
  191. private javax.swing.JMenuItem jMenuItem1;
  192. private javax.swing.JMenuItem jMenuItem2;
  193. private javax.swing.JMenuItem jMenuItem3;
  194. private javax.swing.JMenuItem jMenuItem4;
  195. private javax.swing.JMenuItem jMenuItem5;
  196. private javax.swing.JMenuItem jMenuItem6;
  197. private javax.swing.JMenuItem jMenuItem7;
  198. private javax.swing.JMenuItem jMenuItem8;
  199. private javax.swing.JRadioButtonMenuItem jRadioButtonMenuItem1;
  200. private javax.swing.JRadioButtonMenuItem jRadioButtonMenuItem2;
  201. private javax.swing.JPopupMenu.Separator jSeparator1;
  202. private javax.swing.JPopupMenu.Separator jSeparator2;
  203. private javax.swing.JPopupMenu.Separator jSeparator3;
  204. private javax.swing.JPopupMenu.Separator jSeparator4;
  205. private javax.swing.JPopupMenu.Separator jSeparator5;
  206. private javax.swing.JPopupMenu.Separator jSeparator6;
  207.  
  208. }

Interfícies complexes amb un IDE

L’objectiu d’aquesta activitat és aprendre a generar interfícies complexes mitjançant el vostre entorn integrat d’edició de programes.

Trieu una aplicació qualsevol típica d’escriptori, amb una interfície no gaire complexa, com pot ser un editor de textos, un editor d’imatges, un reproductor d’àudio… Genereu una interfície semblant mitjançant el vostre IDE. La interfície generada no cal que respongui a les ordres de l’usuari; simplement ha de tenir un aspecte semblant a l’aplicació triada.

Com a exemple de solució, s’ha triat la interfície del gISOMount (que heu vist a l’activitat 1). La interfície s’ha fet amb l’editor gràfic del Netbeans i usa recursos addicionals, com ara imatges. Per aquest motiu, la trobareu en el fitxer següent, com un projecte Netbeans autocontingut. Tot i que el codi s’ha generat automàticament, fixeu-vos en la creació dels diferents elements gràfics (new…) i com es van afegint uns dintre els altres (add…).

Figura 3. ( 22.8 KB )

Modificació de propietats

L’objectiu d’aquesta activitat és entendre quins són els mètodes existents en les diferents classes del Java Swing per modificar l’aspecte o el comportament dels diversos components.

Indiqueu quin és el codi Java que cal usar per assolir les fites següents:

  • Establir a vermell el color del text i a blanc el fons d’un JLabel.
  • Incloure una imatge des d’un fitxer, en lloc de text, dins un JButton.
  • Habilitar o deshabilitar un JMenuItem.
  • Seleccionar o deseleccionar un JRadioButton.
  • Generar un conjunt de tres JRadioButton de manera que en un moment determinat només un pugui estar seleccionat. Quan se’n selecciona un, els altres automàticament deixen d’estar seleccionats.
  • Obtenir el text d’una JTextArea.

  1. 1.
  2. jlabel.setForeground(Color.RED);
  3. jlabel.setBackground(Color.WHITE);
  4.  
  5. 2.
  6. jbutton.setIcon(new ImageIcon("NomFitxer"));
  7.  
  8. 3.
  9. jmenuItem.enabled(true);
  10. jmenuItem.enabled(false);
  11.  
  12. 4.
  13. jradioButton.setSelected(true);
  14. jradioButton.setSelected(false);
  15.  
  16. 5.
  17. bg.add(jradioButton1);
  18. bg.add(jradioButton2);
  19. bg.add(jradioButton3);
  20. ...
  21.  
  22. 6.
  23. jtextArea.getText();

GridBagLayout

L’objectiu d’aquesta activitat és entendre com funciona el GridBagLayout, un dels layouts més complexos dins la biblioteca Swing.

Genereu manualment, sense usar l’editor gràfic del vostre IDE, el codi que mostraria la interfície gràfica següent. Per fer-ho, utilitzeu únicament el GridBagLayout.

Figura Interfície a assolir

  1. JFrame frame = new JFrame();
  2. frame.setSize(300,200);
  3.  
  4. JPanel panel = (JPanel)frame.getContentPane();
  5. panel.setLayout(new GridBagLayout());
  6.  
  7. cts1.fill = GridBagConstraints.BOTH;
  8. cts1.gridheight = 2;
  9. panel.add(new JButton("Botó 1"), cts1);
  10.  
  11. cts2.fill = GridBagConstraints.BOTH;
  12. cts2.gridwidth = GridBagConstraints.REMAINDER;
  13. panel.add(new JButton("Botó 2"), cts2);
  14.  
  15. cts3.fill = GridBagConstraints.BOTH;
  16. panel.add(new JButton("Botó 3"), cts3);
  17.  
  18. cts4.fill = GridBagConstraints.BOTH;
  19. cts4.gridwidth = GridBagConstraints.REMAINDER;
  20. panel.add(new JButton("Botó 4"), cts4);
  21.  
  22. cts5.fill = GridBagConstraints.BOTH;
  23. cts5.insets = new Insets(10,10,10,10);
  24. panel.add(new JButton("Botó 5"), cts5);
  25.  
  26. cts6.fill = GridBagConstraints.BOTH;
  27. cts6.insets = new Insets(10,10,10,10);
  28. cts6.gridwidth = GridBagConstraints.REMAINDER;
  29. panel.add(new JButton("Botó 6"), cts6);
  30.  
  31. cts7.fill = GridBagConstraints.BOTH;
  32. cts7.gridwidth = GridBagConstraints.REMAINDER;
  33. panel.add(new JButton("Botó 7"), cts7);
  34.  
  35. frame.setVisible(true);

Control del display

L’objectiu d’aquest exercici és generar una interfície gràfica senzilla que permeti veure com es registren els Listeners per executar un fragment de codi concret davant les accions de l’usuari. Addicionalment, es treballa amb la classe JColorChooser.

Creeu una aplicació en què es mostri en la zona superior de la pantalla una zona clarament diferenciada, inicialment buida (de manera semblant a la pantalla de “display” d’una calculadora). D’aquesta zona, l’usuari ha de poder controlar, com a mínim, el següent:

  • Triar quin text es visualitza. El text s’ha d’anar actualitzant en temps real, a mesura que es va escrivint sobre el control escollit per fer-ho.
  • Triar el color del text que es mostra. Si el color triat és el que ja hi havia en aquell moment, ha de sorgir un tauler de diàleg que avisi d’aquest fet i fer que l’usuari en triï un de diferent.
  • Generar text a l’atzar (una cadena de text de deu caràcters).
  • Esborrar totalment el text.

La tria dels diferents controls a usar per efectuar cada acció i la seva ubicació són totalment lliures. L’única restricció que s’imposa és que en la tria del color de la casella ha d’estar implicada la classe JColorChooser.

La classe ControlText s’ha creat amb l’editor gràfic del Netbeans. Per tant, una part del seu codi està generat automàticament i és una mica complex. La part rellevant d’aquest exercici, i que val la pena revisar, recau en el mètode “initComponents” i les seves instruccions, on s’afegeixen components i Listeners, i els mètodes “ActionPerformed” dels diferents botons.

  1. import java.awt.Color;
  2. import java.util.Random;
  3. import javax.swing.JColorChooser;
  4. import javax.swing.JOptionPane;
  5.  
  6. public class ControlText extends javax.swing.JFrame {
  7.  
  8. public ControlText() {
  9. initComponents();
  10. }
  11.  
  12. private void initComponents() {
  13.  
  14. jTextField1 = new javax.swing.JTextField();
  15. jLabel1 = new javax.swing.JLabel();
  16. jButton1 = new javax.swing.JButton();
  17. jButton2 = new javax.swing.JButton();
  18. jButton3 = new javax.swing.JButton();
  19.  
  20. setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
  21.  
  22. jTextField1.addActionListener(new java.awt.event.ActionListener() {
  23. public void actionPerformed(java.awt.event.ActionEvent evt) {
  24. jTextField1ActionPerformed(evt);
  25. }
  26. });
  27.  
  28. jLabel1.setText("Escriu aquí el teu text...");
  29.  
  30. jButton1.setText("Esborra text");
  31. jButton1.addActionListener(new java.awt.event.ActionListener() {
  32. public void actionPerformed(java.awt.event.ActionEvent evt) {
  33. jButton1ActionPerformed(evt);
  34. }
  35. });
  36.  
  37. jButton2.setText("Canvia color");
  38. jButton2.addActionListener(new java.awt.event.ActionListener() {
  39. public void actionPerformed(java.awt.event.ActionEvent evt) {
  40. jButton2ActionPerformed(evt);
  41. }
  42. });
  43.  
  44. jButton3.setText("Genera text a l'atzar");
  45. jButton3.addActionListener(new java.awt.event.ActionListener() {
  46. public void actionPerformed(java.awt.event.ActionEvent evt) {
  47. jButton3ActionPerformed(evt);
  48. }
  49. });
  50.  
  51. javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
  52. getContentPane().setLayout(layout);
  53. layout.setHorizontalGroup(
  54. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  55. .addGroup(layout.createSequentialGroup()
  56. .addContainerGap()
  57. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  58. .addComponent(jLabel1)
  59. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
  60. .addComponent(jButton3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  61. .addComponent(jButton2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  62. .addComponent(jButton1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  63. .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE))
  64. .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  65. );
  66. layout.setVerticalGroup(
  67. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  68. .addGroup(layout.createSequentialGroup()
  69. .addContainerGap()
  70. .addComponent(jLabel1)
  71. .addGap(5, 5, 5)
  72. .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  73. .addGap(18, 18, 18)
  74. .addComponent(jButton1)
  75. .addGap(18, 18, 18)
  76. .addComponent(jButton2)
  77. .addGap(18, 18, 18)
  78. .addComponent(jButton3)
  79. .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  80. );
  81.  
  82. pack();
  83. }
  84.  
  85. private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
  86. this.jTextField1.setText("");
  87. }
  88.  
  89. private static final char[] lletres = {'a','b','c','d','e','f','g','h',
  90. 'i','j','k','l','m','n','o','p',
  91. 'q','r','s','t','u','v','w','x',
  92. 'y','z'};
  93.  
  94. private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
  95. Random rnd = new Random();
  96. String s = "";
  97. for (int i = 0; i < 30; i++) {
  98. s = s + lletres[rnd.nextInt(lletres.length)];
  99. }
  100. this.jTextField1.setText(s);
  101. }
  102.  
  103. private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
  104. Color c = this.jTextField1.getForeground();
  105. JColorChooser chooser = new JColorChooser();
  106. Color nouColor = chooser.showDialog(this, "Tria el color", Color.WHITE);
  107. if (nouColor.equals(c)) {
  108. JOptionPane.showMessageDialog(this,"Aquest ja és el color actual!");
  109. } else {
  110. this.jTextField1.setForeground(nouColor);
  111. }
  112. }
  113.  
  114. public static void main(String args[]) {
  115. java.awt.EventQueue.invokeLater(new Runnable() {
  116. public void run() {
  117. new ControlText().setVisible(true);
  118. }
  119. });
  120. }
  121.  
  122. private javax.swing.JButton jButton1;
  123. private javax.swing.JButton jButton2;
  124. private javax.swing.JButton jButton3;
  125. private javax.swing.JLabel jLabel1;
  126. private javax.swing.JTextField jTextField1;
  127.  
  128. }

Esdeveniments del ratolí

L’objectiu d’aquest exercici és veure quina mena d’esdeveniments pot generar el ratolí sobre una interfície gràfica.

Genereu una interfície gràfica senzilla composta per un panell blanc que ocupi pràcticament tota la finestra principal. Sota aquest tauler, ubiqueu un seguit d’etiquetes (JLabel) amb el comportament següent quan el ratolí es troba sobre el panell blanc:

  • La primera de totes mostra en tot moment quines són les coordenades del punter del ratolí sobre el tauler. Els valors s’actualitzen en temps real a mesura que el punter es mou.
  • La segona canvia a color verd quan es pitja el botó esquerre, i es torna gris quan es deixa de prémer.
  • La tercera canvia a color vermell quan es pitja el botó dret, i es torna gris quan es deixa de prémer.
  • Si es disposa d’un ratolí amb roda, una quarta etiqueta va comptant el nombre d’increments que s’han fet amb la roda des de l’inici de l’aplicació.

La classe ControlRatoli s’ha creat amb l’editor gràfic del Netbeans. Per tant, una part del seu codi està generat automàticament i és una mica complex. La part rellevant d’aquest exercici, i que val la pena revisar, recau en el mètode “initComponents” i les seves instruccions, on s’afegeixen components i Listeners, i en els mètodes “jPanel2MouseMoved”, “jPanel2MousePressed”, “jPanel2MouseReleased” i “jPanel2MouseWheelMoved”, que controlen les accions del ratolí sobre el panell blanc.

  1. import java.awt.Color;
  2. import java.awt.event.MouseEvent;
  3.  
  4. public class ControlRatoli extends javax.swing.JFrame {
  5.  
  6. public ControlRatoli() {
  7. initComponents();
  8. }
  9.  
  10. private void initComponents() {
  11.  
  12. jPanel1 = new javax.swing.JPanel();
  13. jLabel1 = new javax.swing.JLabel();
  14. jLabel2 = new javax.swing.JLabel();
  15. jLabel3 = new javax.swing.JLabel();
  16. jLabel4 = new javax.swing.JLabel();
  17. jPanel2 = new javax.swing.JPanel();
  18.  
  19. setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
  20.  
  21. jLabel1.setBackground(new java.awt.Color(204, 204, 204));
  22. jLabel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
  23. jLabel1.setOpaque(true);
  24.  
  25. jLabel2.setBackground(new java.awt.Color(204, 204, 204));
  26. jLabel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
  27. jLabel2.setOpaque(true);
  28.  
  29. jLabel3.setBackground(new java.awt.Color(204, 204, 204));
  30. jLabel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
  31. jLabel3.setOpaque(true);
  32.  
  33. jLabel4.setBackground(new java.awt.Color(204, 204, 204));
  34. jLabel4.setText("0");
  35. jLabel4.setBorder(javax.swing.BorderFactory.createEtchedBorder());
  36. jLabel4.setOpaque(true);
  37.  
  38. javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
  39. jPanel1.setLayout(jPanel1Layout);
  40. jPanel1Layout.setHorizontalGroup(
  41. jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  42. .addGroup(jPanel1Layout.createSequentialGroup()
  43. .addContainerGap()
  44. .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 76, javax.swing.GroupLayout.PREFERRED_SIZE)
  45. .addGap(18, 18, 18)
  46. .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
  47. .addGap(18, 18, 18)
  48. .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE)
  49. .addGap(18, 18, 18)
  50. .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE)
  51. .addContainerGap(21, Short.MAX_VALUE))
  52. );
  53. jPanel1Layout.setVerticalGroup(
  54. jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  55. .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
  56. .addContainerGap()
  57. .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
  58. .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 34, Short.MAX_VALUE)
  59. .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 34, Short.MAX_VALUE)
  60. .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 34, Short.MAX_VALUE)
  61. .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 34, Short.MAX_VALUE))
  62. .addGap(55, 55, 55))
  63. );
  64.  
  65. getContentPane().add(jPanel1, java.awt.BorderLayout.PAGE_END);
  66.  
  67. jPanel2.setBackground(new java.awt.Color(255, 255, 255));
  68. jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
  69. jPanel2.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
  70. public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
  71. jPanel2MouseWheelMoved(evt);
  72. }
  73. });
  74. jPanel2.addMouseListener(new java.awt.event.MouseAdapter() {
  75. public void mousePressed(java.awt.event.MouseEvent evt) {
  76. jPanel2MousePressed(evt);
  77. }
  78. public void mouseReleased(java.awt.event.MouseEvent evt) {
  79. jPanel2MouseReleased(evt);
  80. }
  81. });
  82. jPanel2.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
  83. public void mouseMoved(java.awt.event.MouseEvent evt) {
  84. jPanel2MouseMoved(evt);
  85. }
  86. });
  87.  
  88. javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
  89. jPanel2.setLayout(jPanel2Layout);
  90. jPanel2Layout.setHorizontalGroup(
  91. jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  92. .addGap(0, 398, Short.MAX_VALUE)
  93. );
  94. jPanel2Layout.setVerticalGroup(
  95. jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  96. .addGap(0, 198, Short.MAX_VALUE)
  97. );
  98.  
  99. getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);
  100.  
  101. pack();
  102. }
  103.  
  104. private void jPanel2MouseMoved(java.awt.event.MouseEvent evt) {
  105. int x = evt.getX();
  106. int y = evt.getY();
  107. this.jLabel1.setText(x + ", " + y);
  108. }
  109.  
  110. private void jPanel2MousePressed(java.awt.event.MouseEvent evt) {
  111. int b = evt.getButton();
  112. if (MouseEvent.BUTTON1 == b) {
  113. this.jLabel2.setBackground(Color.green);
  114. } else if (MouseEvent.BUTTON3 == b) {
  115. this.jLabel3.setBackground(Color.red);
  116. }
  117. }
  118.  
  119. private void jPanel2MouseReleased(java.awt.event.MouseEvent evt) {
  120. int b = evt.getButton();
  121. if (MouseEvent.BUTTON1 == b) {
  122. this.jLabel2.setBackground(new Color(204,204,204));
  123. } else if (MouseEvent.BUTTON3 == b) {
  124. this.jLabel3.setBackground(new Color(204,204,204));
  125. }
  126. }
  127.  
  128. private void jPanel2MouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
  129. voltes++;
  130. this.jLabel4.setText(voltes + " voltes");
  131. }
  132.  
  133. public static void main(String args[]) {
  134. java.awt.EventQueue.invokeLater(new Runnable() {
  135. public void run() {
  136. new ControlRatoli().setVisible(true);
  137. }
  138. });
  139. }
  140.  
  141. private int voltes = 0;
  142.  
  143. private javax.swing.JLabel jLabel1;
  144. private javax.swing.JLabel jLabel2;
  145. private javax.swing.JLabel jLabel3;
  146. private javax.swing.JLabel jLabel4;
  147. private javax.swing.JPanel jPanel1;
  148. private javax.swing.JPanel jPanel2;
  149.  
  150. }

El buscamines

L’objectiu d’aquesta activitat és utilitzar tots i cadascun dels coneixements adquirits fins ara per generar una aplicació de certa complexitat basada en una interfície gràfica. L’objectiu més important de tots és comprendre com es garanteix la modularitat d’una aplicació mitjançant el patró Model-Vista-Controlador.

El joc del buscamines consisteix en una graella de caselles en blanc que es poden obrir prement-hi a sobre. L’objectiu del jugador és esbrinar sota quines caselles hi ha una mina oculta, però sense obrir-les. Per ajudar-lo en aquesta tasca, cada cop que s’obre una casella, si no conté una mina, mostra quantes caselles del voltant en contenen una (que sempre és un valor de 0 a 8). El jugador també té l’opció de marcar qualsevol casella en blanc en què sospita que hi ha una mina amb una bandera, de manera que queda bloquejada i no es pot obrir accidentalment.

El joc acaba quan en totes les caselles pendents d’obrir només hi ha mines. El joc perfecte és aquell en què el jugador no ha descobert cap mina. Aconseguir-ho requereix una combinació de sort i lògica.

Genereu un joc del buscamines mitjançant la biblioteca Swing. No cal usar gràfics o icones, és suficient usar caràcters per a cada element (per exemple, un asterisc vermell per representar una mina, una exclamació blava per a una bandera…). La manera de desenvolupar el joc és totalment lliure, no cal que la interfície sigui gaire complexa. De totes maneres, algunes de les funcionalitats bàsiques que es demanen són:

  • Amb el botó de l’esquerra del ratolí s’obre una casella.
  • Amb el botó dret del ratolí es marca una casella amb una bandera, o s’esborra si ja n’hi ha una.
  • Abans de començar, el jugador indica les dimensions del tauler i quantes mines hi haurà (controlant que els valors siguin coherents).
  • En acabar el joc, es mostra la puntuació obtinguda (es pot calcular com es vulgui), i es comença una nova partida.
  • Cal complir estrictament el patró MVC. Sota cap concepte s’ha d’analitzar l’estat del joc a partir de l’estat de la GUI. Únicament s’ha de fer mitjançant consultes al Model.

Els fitxers amb la solució els podeu trobar aquí:

Solució ( 4.9 KB )

Sobre aquesta solució, us proposem fer dues activitats addicionals:

  1. Un cop vista i compresa la solució proposada, modifiqueu radicalment la GUI. Atès que s’ha aplicat el patró MVC, vegeu quins fitxers JAVA cal modificar realment per efectuar els canvis.
  1. Genereu una interfície totalment textual, basada en consola. Torneu a veure quins fitxers JAVA cal modificar i quins són els canvis necessaris per aconseguir-ho.

Menús emergents (o pop-up menu)

L’objectiu d’aquesta activitat és estudiar el funcionament dels menús emergents.

Un dels elements típics dins una interfície gràfica són els menús emergents, que sorgeixen en pitjar amb el botó dret sobre certs components.

Genereu el codi Java necessari per mostrar un menú emergent en pitjar amb el botó dret del ratolí sobre un JPanel definit mitjançant la variable jpanel. El menú ha de tenir tres elements anomenats “La primera opció”, “La segona opció” i “La tercera opció”.

  1. private class MyPopupListener extends MouseAdapter {
  2. JPopupMenu popupMenu;
  3.  
  4. PopupListener(JPopupMenu pm) {
  5. popupMenu = pm;
  6. }
  7.  
  8. public void mousePressed(MouseEvent e) {
  9. if (e.isPopupTrigger()) {
  10. popup.show(e.getComponent(),
  11. e.getX(), e.getY());
  12. }
  13. }
  14. }
  15. ...
  16. JPopupMenu popupMenu = new JPopupMenu();
  17. popupMenu.add(new JMenuItem("La primera opció"));
  18. popupMenu.add(new JMenuItem("La segona opció"));
  19. popupMenu.add(new JMenuItem("La tercera opció"));
  20.  
  21. MouseListener popupListener = new MyPopupListener(popupMenu);
  22. jpanel.addMouseListener(popupListener);
  23. ...

Taules

L’objectiu d’aquesta activitat és repassar com es vincula un model a un objecte JTable de manera que en tot moment la representació en pantalla sigui fidel al seu estat.

Completeu el fragment de codi següent per poder visualitzar correctament una taula. El codi que falta està ubicat en els llocs marcats amb ???, si bé a cadascun d’aquests llocs pot correspondre més d’una línia de codi:

  1. private class MyTableModel extends AbstractTableModel {
  2. private String[] nomsColumma = ...
  3. private Object[][] dades = ...
  4.  
  5. public int getColumnCount() {
  6. ???
  7. }
  8.  
  9. public int getRowCount() {
  10. ???
  11. }
  12.  
  13. public String getColumnName(int col) {
  14. ???
  15. }
  16.  
  17. public Object getValueAt(int row, int col) {
  18. ???
  19. }
  20.  
  21. public void setValueAt(Object value, int row, int col) {
  22. ???
  23. data[row][col] = value;
  24. ???
  25. }
  26.  
  27. //Afegeix una fila amb caselles buides al final de la taula
  28. public void afegirFila() {
  29. ???
  30. }
  31.  
  32. }

  1. private class MyTableModel extends AbstractTableModel {
  2. private String[] nomsColumna = ...
  3. private Object[][] dades = ...
  4.  
  5. public int getColumnCount() {
  6. return nomsColumna.length;
  7. }
  8.  
  9. public int getRowCount() {
  10. return dades.length;
  11. }
  12.  
  13. public String getColumnName(int col) {
  14. return nomsColumna [col];
  15. }
  16.  
  17. public Object getValueAt(int row, int col) {
  18. return dades [row][col];
  19. }
  20.  
  21. public void setValueAt(Object value, int row, int col) {
  22. if ((row < getRowCount())&&(col < getColumnCount()))
  23. dades[row][col] = value;
  24. fireTableCellUpdated(row, col);
  25. }
  26. }
  27.  
  28. //Afegeix una fila amb caselles buides al final de la taula
  29. public void afegirFila() {
  30. Object[][] novesDades =
  31. new Object[getRowCount() + 1][getColumnCount()];
  32. for(int i = 0; i < getRowCount(); i++) {
  33. for(int j = 0; j < getColumnCount(); j++) {
  34. novesDades[i][j] = dades[i][j];
  35. }
  36. }
  37. dades = novesDades;
  38. fireTableDataChanged();
  39. }
  40. }

Traducció a applet

Els objectius d’aquesta activitat són veure com és possible traduir una aplicació simple d’escriptori a un applet Java sense gaire esforç i veure els beneficis de separar el Model de la Vista i el Controlador, en permetre variar aspectes de la interfície gràfica sense haver de modificar en absolut el codi de les classes del Model.

Modifiqueu el d’exemple “Calculadora”, disponible al final d’aquest enunciat, de manera que s’executi en un navegador web com a applet. Per fer aquesta tasca, no es pot modificar la classe associada al Model (la classe Calculadora.java).

Aplicació ( 2.1 KB )

Els fitxers amb la solució estan tot seguit. Recordeu que, al tractar-se d’un applet, per eexecutar-lo el que cal és obrir el fitxer html.

Solució ( 2.2 KB )

Anar a la pàgina anterior:
Interfícies gràfiques d'usuari
Anar a la pàgina següent:
Exercicis