Interfete grafice

Interfeţele grafice (Graphical User Interfaces) reprezintă ferestre ce conţin elemente grafice ce permit interacţiunea dintre aplicaţie şi utilizator. Limbajul java pune la dispoziţia programatorului două biblioteci pentru realizarea interfeţelor grafice: java.awt şi java.swing.

Diagrama din figura 1 prezintă cele mai importante clase din cadrul pachetelor java.awt şi java.swing.

Construire fereastra principala aplicatie

Pentru a construi o fereastră grafică principală în java trebuie extinsă clasa JFrame. Programul următor exemplifică o aplicaţie ce construieşte o fereastră grafică şi o afişează pe ecran.

import javax.swing.JFrame;
 
public class SimpleApp extends JFrame{
 
      SimpleApp(){
            setTitle("Titlul ferestrei");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(400,500);
            setVisible(true);
      }
 
      public static void main(String[] args) {
            SimpleApp a = new SimpleApp();
      }
 
}

Butoane si casute de text

Butoanele sunt elemente de control care, prin apăsare, pot genera o acţiune. Despre modul cum se asociază la un buton o acţiune se va vorbi în sectiunea „Captarea evenimentelor”. Pentru a construi un buton se foloseşte clasa JButton.

Căsuţele de text sunt zone pe unu sau mai multe rânduri în care utilizatorul poate adăuga un text. Pentru a construi o căsuţă de text se poate folosi clasa JTextField (ce pemrite construirea unei căsuţe de text cu un singur rând) sau clasa JTextArea (ce permite construirea unei căsuţe de text pe mai multe rânduri.

Pentru a construi un text static ce nu poate fi modificat se foloseşte clasa JLabel.

import java.awt.FlowLayout;
 
import javax.swing.*;
import java.util.*;
 
public class ButtonAndTextField extends JFrame{
 
      HashMap accounts = new HashMap();
 
      JLabel user,pwd;
      JTextField tUser,tPwd;
      JButton bLoghin;
 
      ButtonAndTextField(){
 
            accounts.put("user1", "pwd1");
            accounts.put("user2", "pwd2");
            accounts.put("user3", "pwd3");
 
            setTitle("Test login");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            init();
            setSize(200,250);
            setVisible(true);
      }
 
      public void init(){
 
            this.setLayout(null);
            int width=80;int height = 20;
 
            user = new JLabel("User ");
            user.setBounds(10, 50, width, height);
 
            pwd = new JLabel("Pasword ");
            pwd.setBounds(10, 100,width, height);
 
            tUser = new JTextField();
            tUser.setBounds(70,50,width, height);
 
            tPwd = new JTextField();
            tPwd.setBounds(70,100,width, height);
 
            bLoghin = new JButton("Loghin");
            bLoghin.setBounds(10,150,width, height);
 
            add(user);add(pwd);add(tUser);add(tPwd);add(bLoghin);
 
      }
 
      public static void main(String[] args) {
            new ButtonAndTextField();
      }
}

Componentele pot fi aşezate în cadrul unei ferestre folosind clase speciale responsabile cu poziţionarea componentelor pe ecran numite clase de tip layout manager sau relativ la colţul din stânga sus al ferestrei. Modul de folosire a claselor de tip layout manager este acoperit în cadrul capitolului „Capturarea evenimentelor”.

În programul anterior elementele grafice (butoane, căsuţe de text, etichete) sunt poziţionate pe ecran folosind metoda setBounds(x,y,width,hight). Pentru ca acest mod de poziţionare a componentelor să poată fi realizat trebuie ca componenta layout manager să fie dezactivată folosind metoda setLayout(null) .

Capturarea evenimentelor

Comunicarea dintre utilizator şi aplicaţie prin intermediul interfeţei grafice se realizează printr-un mecanism bazat pe evenimente. Orice acţiune a utilizatorului în cadrul interfeţei grafice (apăsarea unui buton, mişcarea mouse-ului, selectarea unui buton de selecţie) determină generarea unui eveniment de către componentă. Evenimentele generate de componente ca urmare a acţiunii utilizatorului pot fi captate de către aplicaţie şi gestionate corespunzător.

Aşadar, pentru a scrie cod care sa se execute în momentul în care utilizatorul interacţionează cu o componenta grafica trebuiesc realizaţi următorii paşi:

  • sa scriem o clasa de tip listener care sa “asculte” evenimentele produse de acea componenta si în cadrul acestei clase sa implementam metode specifice pentru tratarea lor;
  • sa comunicam componentei sursa clasa care “asculta” evenimentele pe care le generează, cu alte cuvinte sa înregistram acea clasa drept “consumator” al evenimentelor produse de componenta respectiva.

Evenimentele sunt modelate şi ele prin intermediul claselor. Pentru fiecare tip de eveniment există o clasă care descrie acest eveniment. Clasele ce descriu evenimente sunt definite în cadrul pachetului java.awt.event.

ActionListener class listener methods:

  • actionPerformed()

Componentele generatoare de evenimente: AbstractButton, Button, ButtonModel, ComboBoxEditor, JComboBox, JFileChooser, JTextField, List, MenuItem, TextField, Timer

AdjustmentListener class listener methods:

  • adjustementValueChanged()

Componentele generatoare de evenimente: Adjustable, JScrollBar, Scrollbar

ComponentListener class listener methods:

  • componentHidden(), componentMoved(), componentResized(), componentShown()

Componentele generatoare de evenimente: Component

ContainerListener class listener methods:

  • componentAdded(), componentRemoved()

Componentele generatoare de evenimente: Container

FocusListener class listener methods:

  • focusGained(), focusLost()

Componentele generatoare de evenimente: Component

ItemListener class listener methods:

  • itemStateChanged()

Componentele generatoare de evenimente: AbstractButton, ButtonModel, Checkbox, CheckboxMenuItem, Choice, ItemSelectable, JComboBox, List

KeyListener class listener methods:

  • keyPressed(), keyReleased(), keyTyped()

Componentele generatoare de evenimente: Component

MouseListener class listener methods:

  • mouseClicked(), mouseEntered(), mouseExited(), mousePressed(), mouseReleased()

Componentele generatoare de evenimente: Component

MouseMotionListener class listener methods:

  • mouseDragged(), mouseMoved()

Componentele generatoare de evenimente: Component

TextListener class listener methods:

  • textValueChanged()

Componentele generatoare de evenimente: TextListener

WindowListener class listener methods:

  • windowActivated(), windowClosed(), windowClosing(), windowDeactivated(), windowDeiconified(), windowIconified(), windowOpened()

Componentele generatoare de evenimente: Window

Exemplu aplicatie captare evenimente

În continuare este prezentată aplicaţia din capitolul anterior modificată astfel încât să capteze şi să trateze evenimentele generate de componenta de tip buton în momentul apăsării acestuia.

package isp.grafic.fereastra;
 
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.*;
import java.util.*;
 
public class ButtonAndTextField2 extends JFrame{
 
      HashMap accounts = new HashMap();
 
      JLabel user,pwd;
      JTextField tUser,tPwd;
      JTextArea tArea;
      JButton bLoghin;
 
      ButtonAndTextField2(){
 
            accounts.put("user1", "pwd1");
            accounts.put("user2", "pwd2");
            accounts.put("user3", "pwd3");
 
            setTitle("Test login");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            init();
            setSize(200,300);
            setVisible(true);
      }
 
      public void init(){
 
            this.setLayout(null);
            int width=80;int height = 20;
 
            user = new JLabel("User ");
            user.setBounds(10, 50, width, height);
 
            pwd = new JLabel("Pasword ");
            pwd.setBounds(10, 100,width, height);
 
            tUser = new JTextField();
            tUser.setBounds(70,50,width, height);
 
            tPwd = new JTextField();
            tPwd.setBounds(70,100,width, height);
 
            bLoghin = new JButton("Loghin");
            bLoghin.setBounds(10,150,width, height);
 
            bLoghin.addActionListener(new TratareButonLoghin());
 
            tArea = new JTextArea();
            tArea.setBounds(10,180,150,80);
 
            add(user);add(pwd);add(tUser);add(tPwd);add(bLoghin);
            add(tArea);
 
      }
 
      public static void main(String[] args) {
            new ButtonAndTextField2();
      }
 
      class TratareButonLoghin implements ActionListener{
 
            public void actionPerformed(ActionEvent e) {
 
                  String usr = ButtonAndTextField2.this.tUser.getText();
                  String pwd = ButtonAndTextField2.this.tPwd.getText();
 
                  if(ButtonAndTextField2.this.accounts.containsKey(usr)){
                        String correctPwd = (String)ButtonAndTextField2.this.accounts.get(usr);
                        if(correctPwd.equals(pwd)){
                              //user and password correct
                              ButtonAndTextField2.this.tArea.append("Valid loghin\n");
                        }
                        else{
                              //invalid password
                              ButtonAndTextField2.this.tArea.append("Invalid password\n");
                        }
                  }else{
                        //user not found
                        ButtonAndTextField2.this.tArea.append("User not found\n");
                  }
 
            }    
      }
}

Meniuri

Spre deosebire de celelalte obiecte grafice, care deriva din clasa Component, componentele unui meniu reprezintă instanţe ale unor clase derivate din superclasa abstracta MenuComponent.

Ierarhia de clase folosită în lucrul cu meniuri este prezentată mai jos.

Aplicaţia următoare exemplifică modul în care meniurile pot fi integrate în cadrul unei aplicaţii.

package isp.grafic.menu;
 
import java.awt.*;
import java.awt.event.*;
import java.io.*;
 
import javax.swing.*;
 
 
public class Editor extends JFrame
{
      JMenuBar mb;
      JMenu f;
      JMenu t;
      JMenuItem s,o,e;
      JTextArea ta;
 
      Editor()
      {
            mb = new JMenuBar();
            f = new JMenu("File");
 
            s = new JMenuItem("Save");
            o = new JMenuItem("Open");
            e = new JMenuItem("Exit");
 
            s.addActionListener(new A());
            o.addActionListener(new A());
            e.addActionListener(new A());
 
            mb.add(f);
            f.add(s);
            f.add(o);
            f.add(e);
 
            setJMenuBar(mb);
 
            ta = new JTextArea();
            add(ta);
 
            setSize(500,400);
            setVisible(true);
      }
 
      void save(String f)
      {
            try
            {
            PrintWriter pw = new PrintWriter(
                  new FileWriter(new File(f)));
            pw.println(ta.getText());
            pw.close();
            }catch(Exception e)
            {
 
            }
 
      }
 
      void open(String f)
      {
            try
            {
            ta.setText("");
            BufferedReader bf =
                  new BufferedReader(
                        new FileReader(new File(f)));
            String l = "";
            l = bf.readLine();
            while (l!=null)
            {
                  ta.append(l+"\n");
                  l = bf.readLine();
            }
            }catch(Exception e){}
      }
 
      class A implements ActionListener
      {
            public void actionPerformed(ActionEvent e)
            {
                  String t = ((JMenuItem)e.getSource()).getLabel();           
                  if(t.equals("Save")){
                  FileDialog d = new FileDialog(Editor.this,"Incarca f",FileDialog.SAVE);
                  d.setVisible(true);
                  save(d.getDirectory()+d.getFile());
                  }
 
                  if (t.equals("Open"))
                  {
                   FileDialog d = new FileDialog(Editor.this,"Incarca f",FileDialog.LOAD);
                   d.setVisible(true);
                   open(d.getDirectory()+d.getFile());
                  }
 
            }
      }
 
      public static void main(String args[])
      {
            new Editor();
      }
}

Casute de selectie Checkbox

package isp.grafic.componente;
 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
class CheckboxTest extends JFrame implements ItemListener {
 
    private JLabel label1, label2;
    private JCheckBox cbx1, cbx2, cbx3;
 
    public CheckboxTest(String titlu) {
        super(titlu);
        initializare();
        setVisible(true);
 
    }
 
    public void initializare() {
        setLayout(new GridLayout(5, 1));
        label1 = new JLabel("Componente :");
        label2 = new JLabel("");
        cbx1 = new JCheckBox("componenta 1");
        cbx2 = new JCheckBox("componenta 2");
        cbx3 = new JCheckBox("componenta 3");
 
        add(label1);
        add(label2);
        add(cbx1);
        add(cbx2);
        add(cbx3);
        pack();
        setSize(200, 200);
 
        cbx1.addItemListener(this);
        cbx2.addItemListener(this);
        cbx3.addItemListener(this);
    }
 
    //metoda interfetei ItemListener
    public void itemStateChanged(ItemEvent e) {
        StringBuffer ingrediente = new StringBuffer();
        if (cbx1.isSelected() == true) {
            ingrediente.append(" componenta 1");
        }
        if (cbx2.isSelected() == true) {
            ingrediente.append(" componenta 2 ");
        }
        if (cbx3.isSelected() == true) {
            ingrediente.append(" componenta 3 ");
        }
        label2.setText(ingrediente.toString());
    }
 
    public static void main(String[] args) {
        new CheckboxTest("titlu");
    }
}

Casute de selectie JComboBox

package isp.grafic.componente;
 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
class ChoiceTest extends JFrame implements ItemListener {
      private JLabel label;
      private JComboBox culori;
 
      public ChoiceTest(String titlu) {
            super(titlu);
            initializare();
            setVisible(true);
      }
 
      public void initializare() {
            setLayout(new GridLayout(4, 1));
 
            label = new JLabel("Alegeti culoarea");
            label.setOpaque(true);
            label.setBackground(Color.red);
 
            culori = new JComboBox();
            culori.addItem("Rosu");
            culori.addItem("Verde");
            culori.addItem("Albastru");
            culori.setSelectedIndex(0);
 
            add(label);
            add(culori);
            pack();
            setSize(200, 100);
 
            culori.addItemListener(this);
      }    
 
      //metoda interfetei ItemListener
      public void itemStateChanged(ItemEvent e) {
            switch (culori.getSelectedIndex()) {
                  case 0:
                        label.setBackground(Color.red);
                        break;
                  case 1:
                        label.setBackground(Color.green);
                        break;
                  case 2:
                        label.setBackground(Color.blue);
            }
      }
 
      public static void main(String[] args) {
            new ChoiceTest("test");
      }
}

Componentele List si JSCrollPane

Componenta List conţine o listă de opţiuni dintre care utilizatorul poate selecta una sau mai multe. Toate opţiunile listei sunt vizibile. Componenta ScrollPane permite ataşarea unor bare de defilare orizontale şi / sau verticale componentelor grafice care nu au implementată funcţionalitatea de defilare automată.

package isp.grafic.componente;
 
 
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.PrintWriter;
import java.io.StringWriter;
 
import javax.swing.*;
import javax.swing.event.*;
 
public class ListTest extends JFrame implements ListSelectionListener{
 
      //JFrame frame = new JFrame("Selecting JList");
 
      String labels[] = { "Chardonnay", "Sauvignon", "Riesling", "Cabernet",
              "Zinfandel", "Merlot", "Pinot Noir", "Sauvignon Blanc",
              "Syrah", "Gewurztraminer" };
 
    JList jlist = new JList(labels);
 
    final JTextArea textArea = new JTextArea();
 
 
      ListTest(){
             setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
 
             JScrollPane scrollPane1 = new JScrollPane(jlist);
             add(scrollPane1, BorderLayout.WEST);
 
 
             textArea.setEditable(false);
             JScrollPane scrollPane2 = new JScrollPane(textArea);
             add(scrollPane2, BorderLayout.CENTER);
 
             jlist.addListSelectionListener(this);
 
             jlist.addMouseListener(new MyMouseListener());
 
             setSize(350, 200);
             setVisible(true);
 
 
 
      }
 
      public void valueChanged(ListSelectionEvent listSelectionEvent) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        pw.print("First index: " + listSelectionEvent.getFirstIndex());
        pw.print(", Last index: " + listSelectionEvent.getLastIndex());
        boolean adjust = listSelectionEvent.getValueIsAdjusting();
        pw.println(", Adjusting? " + adjust);
        if (!adjust) {
          JList list = (JList) listSelectionEvent.getSource();
          int selections[] = list.getSelectedIndices();
          Object selectionValues[] = list.getSelectedValues();
          for (int i = 0, n = selections.length; i < n; i++) {
            if (i == 0) {
              pw.print("  Selections: ");
            }
            pw
                .print(selections[i] + "/" + selectionValues[i]
                    + " ");
          }
          pw.println();
        }
        textArea.append(sw.toString());
      }
 
      class MyMouseListener extends MouseAdapter{
            public void mouseClicked(MouseEvent mouseEvent) {
              JList theList = (JList) mouseEvent.getSource();
              if (mouseEvent.getClickCount() == 2) {
                int index = theList.locationToIndex(mouseEvent.getPoint());
                if (index >= 0) {
                  Object o = theList.getModel().getElementAt(index);
                  textArea.append("Double-clicked on: " + o.toString());
                  textArea.append(System.getProperty("line.separator"));
                }
              }
            }
      }
 
  public static void main(String args[]) {
        new ListTest();
 
   }
}