Visual Editor dla Eclipse

visual_editorSwego czasu do pisania aplikacji okienkowych w Javie (głównie z musu) korzystałem z NetBeans i jego edytora graficznego, jednak w przypadku ostatniego projektu na laboratoria postanowiłem przetestować pewną alternatywę, czyli Visual Editor dla Eclipse.

Visual Editor jest (jak większość dodatków do Eclipse) wtyczką, która ma na celu automatyczne generowanie kodu wykorzystującego bibliotekę okienek Swing. Niestety okazuje się, że mimo wersji 1.5 dla Eclipse Helios jest to raczej prototyp działający trochę na siłę niż poprawna wersja Release.

Jego największą wadą jest dość wysoka niestabilność, co potrafi owocować widokiem okienek jak na obrazku obok niemal co chwila (tak, korzystałem z wersji x64). Drugą rzeczą, która boli jest to, że zagnieżdżone ve_errorokienko zostawia swoja kotwiczkę jako osobny proces, który siedzi sobie jako zupełnie osobna aplikacja w pasku zadań i skutecznie blokuje możliwość użycia skrótu alt+tab, a w przypadku zmiany edytowanych okienek, powoduje wymienione crashe. Kolejną wadą, trochę drobniejszą, jest generowany kod, który, dla większej ilości komponentów i ich właściwości, niestety wygląda jak makaron  (chociaż organizacja na zasadzie statycznych wartości, tudzież singletonów jest dość fajnym rozwiązaniem.

Z zalet Visual Editora mogę wymienić chyba głównie to że jest, a co do samego wyglądu i integracji z Eclipse, to oprócz osobnego procesu dla okienka i crashów, komponuje się to w miarę wygodnie.

Tak przy okazji narzekania na tworzenie okienek w Javie – dlaczego nikt nie wymyślił obliczania minimalnego rozmiaru okna na podstawie minimalnych rozmiarów zawartych w nim komponentów, to naprawdę ułatwiłoby życie.

Swing czyli taniec z Javą

2009-10-26(3)

Tym razem postawiłem napisać o czymś, czym się aktualnie zajmuję na uczelni czyli programowaniem w Javie, a konkretniej programowanie interfejsu graficznego w Swingu. Java Swing jest w pełni obiektową (jak sam język) biblioteką graficzną służącą do majstrowania okienkowego GUI (podobnie jak QT, czy też Windows Forms). Korzystanie z tej biblioteki jest bardzo proste, niestety ma ona jedną podstawową wadę (oprócz bycia w Javie) – domyślnie okienko posiada własny style, więc nie wykorzystuje systemowego, dlatego może się wyróżniać.

Tworzenie okienek w Swingu jest bardzo proste, przykładowo wyświetlenie pustego okienka wygląda następująco:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
 
public class Okienko
{
   public static void main(String[] args)
   {
      SwingUtilities.invokeLater(new Runnable()
      {
         public void run()
         {
            JFrame f = new JFrame();
            f.setTitle("Hello World!");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setSize(290, 250);
            f.setVisible(true);
         }
      });
   }
}

2009-10-26(4)

Ten krótki kod tworzy prostą formatkę JFrame, a następnie ustawia jej tytuł, rozmiar, akcje zamnięcia i na końcu pokazuje okienko. Wszystko to jest wykonywane w funkcji run() anonimowej klasy wewnętrznej po interfejsie Runnable (swoją drogą najpiękniejszy mechanizm w Javie :)), która działa w osobnym wątku biblioteki Swing. Jak widać jest to bardzo proste.

Co jednak gdy chcemy stworzyć coś bardziej wyszukanego? Wtedy najlepiej rozszerzyć (odziedziczyć) klasę JFrame. Mając własną klasę o wiele łatwiej wszystkim zarządzać wszystkimi komponentami, które znajdują się na formatce. Poniższy kod tworzy formatkę i wyświetla na niej przycisk i pole tekstowe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.awt.FlowLayout;
import javax.swing.*;
 
public class Okienko extends JFrame
{
   private JButton bPisz = new JButton("Pisz");
   private JTextArea textArea = new JTextArea(10, 20);
 
   public Okienko()
   {
      setTitle("Hello World!");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(290, 250);
 
      setLayout(new FlowLayout());
      add(new JScrollPane(textArea));
      add(bPisz);
   }
 
   public static void main(String[] args)
   {
      SwingUtilities.invokeLater(new Runnable()
      {
         public void run()
         {
            new Okienko().setVisible(true);
         }
      });
   }
}

Powyższy kod jest już troszkę dłuższy, a jego zadanie polega na wyświetleniu na formatce przycisku oraz pola tekstowego. Pojawiły się tutaj dodatkowe komponenty takie jak: JButton, JTextArea, JScrollPane oraz funkcja setLayout(). Dwa pierwsze są oczywiste, bo jest to wspomniany przycisk i pole tekstowe, natomiast JScrollPane jest dodatkowym komponentem dodającym do JTextArea paski przesuwania (to wszystko przez proste opakowanie go). Funkcja setLayout() ustawia sposób rozmieszczenia kontrolek. Domyślnym układem jest BorderLayout, który kontrolki układa jedna na drugiej, natomiast FlowLayout ustawia je w taki sposób aby wszystkie były widoczne (po szczegóły zapraszam do dokumentacji :)).

2009-10-26(5)

No cóż mamy przycisk, ale teraz co zrobić, aby po jego naciśnięciu coś się stało. Obsługa akcji na kontrolkach opiera się na zdarzeniach, czyli w przypadku naciśnięcia przycisku wywoływana jest odpowiednia funkcja, która to zdarzenie potrafi obsłużyć. W takim razie jak obsłużyć akcję wciśnięcia przycisku? W tym celu należy dodać do przycisku odbiorcę zdarzenia za pomocą funkcji addActionListener(). Funkcja ta przyjmuje referencję do interfejsu ActionListener, z którego należy zaimplementować funkcję actionPerformed(). Właśnie ta funkcja zostanie wywołana w momencie wystąpienia zdarzenia.

Wynikowy kod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.awt.FlowLayout;
import javax.swing.*;
import java.awt.event.*;
 
public class Okienko extends JFrame
{
   private JButton bPisz = new JButton("Pisz");
   private JTextArea textArea = new JTextArea(10, 20);
 
   public Okienko()
   {
      setTitle("Hello World!");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(290, 250); 
 
      bPisz.addActionListener(new ActionListener()
      {
         public void actionPerformed(ActionEvent e)
         {
            textArea.append("Hello World ");
         }
      });
 
      setLayout(new FlowLayout());
      add(new JScrollPane(textArea));
      add(bPisz);
   }
 
   public static void main(String[] args)
   {
      SwingUtilities.invokeLater(new Runnable()
      {
         public void run()
         {
            new Okienko().setVisible(true);
         }
      });
   }
}