devstory

Programmation de l'application Java Desktop à l'aide de SWT

1- Introduction

Ce document est basé sur:
  • Eclipse 4.6, 47 (NEON, OXYGEN)

Dans ce document, je vais vous présenter la programmation de l'application Desktop avec SWT.

La question de savoir est que dans Java quel choix de technologie peuvent programmer l'application Desktop, ou quelles technogies ont capable de programmer une application web qui possède l'interface similaire de celle de l'application Desktop.

Voir plus à:

2- RCP (Rich Client Platform)

RCP (Rich Client Platform) - est une plate-forme (Platform) basée sur SWT, sert à programmer des applications Desktop et plus loin elle a contruit une plate- forme qui vous permet de développer des applications de style Desktop comme Workbench, comme Eclipse IDE, ou ou les programmeurs peuvent intégrer le plugin à Eclipse IDE.

Mais même si vous voulez utiliser SWT pour programmer, et ne voulez pas utiliser ce qui sont fournit par RCP vous pouvez également créer une application RCP.

SWT:

Workbench Application:

Afin de créer une application Desktop en utilisant SWT. Sur Eclipse nous pouvons créer un projet RCP Plugin. Vous avez deux choix.
  • N'utilisez que les fonctions de SWT
  • L'utilisation la plate-forme fournite par l'application RCP afin de programmer RCP Workbench.
Dans ce document, je vais vous guider pour vous familiariser avec la programmation de base SWT, en utilisant WindowBuilder pour faire glisser et déposer des composants dans l'interface.

3- Les réglages requis avant le démarrage

Certains réglages requis avant de commencer:

Vous avez besoin de la dernière version d'Eclipse. Il existe actuellement Eclipse 4.7 (Codes OXYGEN).
À mon avis, vous devez télécharger le progiciel: "Eclipse IDE for Java EE Developers". Le seul nombre différent est le nombre de plugins, dans le but de différentes programmations. Vous pouvez installer des plugins supplémentaires à d'autres fins si vous le souhaitez.
L'installation du plugin Win. Il s'agit d'un plugin qui vous permet de concevoir des applications GUI SWT en utilisant la commodité de glisser-déposer.
Voir les instructions d'installation à l'adresse suivante:

4- Quelques concepts de SWT.

4.1- Display & Shell

La classe Display et la classe Shell sont des composants clés de l'application SWT.

- org.eclipse.swt.widgets.Shell représet une fenêtre (Window)

- org.eclipse.swt.widgets.Display est responsable de gérer des boucles d'événements( event loops), des polices, des couleurs et pour contrôler la communication entre processus dans l'interface utilisateur (UI Thread) et d'autres processus (other Thread). Display est la base de toutes les capacités SWT.

Chaque application SWT exige au moinss un Display et un/ plusieurs objects Sell​​​​​​​.
Exemple:
Display display = new Display();
Shell shell = new Shell(display);
shell.open();

// run the event loop as long as the window is open
while (!shell.isDisposed()) {
   // read the next OS event queue and transfer it to a SWT event
 if (!display.readAndDispatch())
  {
 // if there are currently no other OS event to process
 // sleep until the next OS event is available
   display.sleep();
  }
}

// disposes all associated windows and their components
display.dispose();

4.2- SWT Widgets

Les SWT widget sont installés dans des progiciels org.eclipse.swt.widgets et org.eclipse.swt.custom. Ces widget s'étendent de la classe Widget ou Control. Certains widget sont décrits dans le shéma ci- dessous.
Ce shéma est la capture de l'écran de SWT widget homepage.

5- Créer le projet RCP Plugin Project

Dans Eclipse, sélectionnez:
  • File/New/Other...
  • Donc, il n'est pas nécessaire de créer une application Workbench, donc nous ne pouvons pas vous enregistrer (1) comme indiqué ci-dessous
  • ​​​​​​​Sélectionnez Yes dans la région (2) pour qu' Eclipse crée RCP Application (Exécuter sur Desktop), sinon elle créera une RAP application (Exécution sur le Web).
Le projet est créé:
Ajoutez la bibliothèque swt:  org.eclipse.swt

Si vous développez l'application RAP, la bibliothèque correspondante est org.eclipse.rap.rwt

6- Le premier exemple

C'est un exemple simple qui n'utilise pas les outils glisser- déplacer WindowBuilder.
HelloSWT.java
package org.o7planning.tutorial.swt.helloswt;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class HelloSWT {

  public static void main(String[] args) {
      // Create Display
      Display display = new Display();
      // Create Shell (Window) from diplay
      Shell shell = new Shell(display);

      shell.open();

      while (!shell.isDisposed()) {
          if (!display.readAndDispatch())
              display.sleep();
      }
      display.dispose();
  }
}
Cliquez sur le bouton droit de la classe HelloSWT.java et sélectionnez Run As/Java Application.
Résutat de l'exécution de l'exemple:

7- L'utilisation WindowBuilder

Ensuite, nous allons créer un exemple de glisser et déplacer sur WindowBuilder.
  • File/New/Other ..
C'est la fenêtre de la conception de WindowBuilder. Il vous permet de glisser et de déposer les Widgets facilement.
You can watch the video below:

8- SWT Widget

8.1- Vue ensemble

C'est la hiérarchie des Widget disponibles dans SWT.
Vous pouvez voir le démo (demo) des Control dans le lien suivant, c'est RWT Control,  mais ils sont essentiellement les mêmes que le SWT control.

Demo:

8.2- Des Widget peuvent contenir d'autres Widget (Container)

8.3- Des Controls

9- SWT Layout

9.1- Qu'est ce que Layout?

Pour simplifier, Layout est la manière d'arranger les composants sur l'interface.
Les Layout standard de la bibliothèque SWT sont:
  • FillLayout – Définit des Widgets de même taille dans une seule ligne ou colonne
  • RowLayout – Présente des Widgets dans une ligne ou des lignes, avec des options de remplissage (Fill), enveloppement (Wrap) et espacement (Espace).
  • GridLayout – Présente des Widgets dans une grille

9.2- Exemple en ligne

Ceci est un exemple en ligne, vous permettant de voir comment l'exercice de Layout.
  • TODO Link?

9.3- FillLayout

FillLayout est une classe layout simple. Il met des widgets dans une seule ligne ou une seule colonne, ce qui les oblige à avoir la même taille. Initialement, les widgets seront tous aussi grands que les widget les plus hauts, et aussi large que les plus larges. FillLayout ne s'enveloppe (wrap) pas, et vous ne pouvez pas spécifier de marges (margin) ou d'espacement (space).

FillLayout fillLayout = new FillLayout();
fillLayout.type = SWT.VERTICAL;
shell.setLayout(fillLayout);
                                                                                                                      Initial                                                             Après le redimensionnement                                   
fillLayout.type = SWT.HORIZONTAL
(par défaut)
fillLayout.type = SWT.VERTICAL
Video:
 
 
FillLayoutExample.java
package org.o7planning.tutorial.swt.layout;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class FillLayoutExample {

  public static void main(String[] args) {
      Display display = new Display();
      final Shell shell = new Shell(display);
      shell.setLayout(new FillLayout());

      //
      Composite parent = new Composite(shell, SWT.NONE);
     
      FillLayout fillLayout= new FillLayout();
      fillLayout.type= SWT.VERTICAL;
     
      parent.setLayout(fillLayout);

      Button b1 = new Button(parent, SWT.NONE);
      b1.setText("B1");

      Button b2 = new Button(parent, SWT.NONE);
      b2.setText("B2");

      Button button3 = new Button(parent, SWT.NONE);
      button3.setText("Button 3");
     
      // Windows back to natural size.
      shell.pack();
      //
      shell.open();
      while (!shell.isDisposed()) {
          if (!display.readAndDispatch())
              display.sleep();
      }
      // tear down the SWT window
      display.dispose();
  }
}
Résultat de l'exécution:

9.4- RowLayout

RowLayout est plus couramment utilisé que FillLayout en raison de sa capacité à envelopper( wrap), et parce qu'il fournit des margin et des spacing. RowLayout possède plusieurs champs (field) de configuration. En outre, la hauteur et la largeur de chaque widget dans un RowLayout peuvent être spécifiées en définissant un objet RowData dans le widget en utilisant setLayoutData.

The field configuration:

Wrap, Pack, Justify:

InitialAprès le redimensionnement
wrap = true
pack = true
justify = false
 
(Par défaut)
wrap = false
 
(Découpe si pas assez d'espace)
pack = false
 
(Tous les widgets ont la même taille)
justify = true
 
(Les widgets sont répartis sur l'espace disponible)

MarginLeft, MarginTop, MarginRight, MarginBottom, Spacing:

Ces champs (field) contrôlent le nombre de pixels (Pixel) entre les widgets (space - espacement) et le nombre de pixels entre un widget et le côté de la Composite principale (margin - marge). Par défaut, RowLayouts laisse 3 pixels pour la marge (margin) et l'espacement (space). Les champs de marge et d'espacement sont affichés dans le diagramme suivant.
Video:
 

9.5- GridLayout

GridLayout est le plus utile et le plus puissant des Layout standard, mais c'est aussi le plus compliqué. Avec un GridLayout, les widgets d'un Composite sont disposés dans une grille. GridLayout possède un certain nombre de champs de configuration et, comme RowLayout, les widgets que RowLayout contient peuvent avoir un objet de données de mise en page associé, appelé GridData. Le pouvoir de GridLayout réside dans la capacité de configurer GridData pour chaque widget contrôlé par GridLayout.

Les configurations de GridLayout:

  • NumColumns
  • MakeColumnsEqualWidth

Video GridLayout:

9.6- StackLayout

Ce Layout empile tous les Widgets l'un sur l'autre et les redimensionne pour avoir la même taille et du même emplacement. Le contrôle spécifié dans topControl est visible et tous les autres contrôles ne sont pas visibles. Les utilisateurs doivent définir la valeur topControl puis appeller la méthode layout() sur le composite qui contient StackLayout.

Video StackLayout:

 

9.7- Combiner des Layout

Au-dessus, nous nous sommes familiarisés avec des Layout standard. La combinaison entre des Layout différents et l'autres conteneurs (Composite, TabFolder, SashForm, ...) créera l'interface souhaitée.
  • TODO

10- Écrire la classe étendue à partir du widget de SWT

Parfois, vous devez écrire une classe à partir de la classe de widgets disponibles de SWT. Il est parfaitement normal, mais il y a une petite remarque, il faut passer outre à la méthode checkSubclass() sans avoir à faire quoi que ce soit dans cette méthode.
MyButton.java
package org.o7planning.tutorial.swt.swtsubclass;

import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;

public class MyButton extends Button {

   public MyButton(Composite parent, int style) {
       super(parent, style);
   }

   // You have to override this method.
   @Override
   protected void checkSubclass() {
       // No need to do anything.
   }

   
}

11- Des interfaces de composants modulaires

Dans le cas où vous avez conçu une interface complexe. Le fractionnement des conceptions est nécessaire et ensuite de metre ensemble, ce sera plus facile si vous concevez sur WindowBuilder.

Consultez l'interface suivante, et nous essaierons de la diviser.
Supposons que vous souhaitez concevoir une interface comme l'illustration ci-dessous. (Il n'est pas compliqué de diviser la conception, mais c'est un exemple pour illustrer comment diviser la conception de l'interface)
Nous pouvons concevoir deux composites séparés et le greffer sur MainComposite.

TopComposite

  • File/New/Other...
Concevoir l'interface pour TopComposite.
TopComposite.java
package org.o7planning.tutorial.swt.module;

import org.eclipse.swt.widgets.Composite;

public class TopComposite extends Composite {
  private Text text;

  /**
   * Create the composite.
   * @param parent
   * @param style
   */
  public TopComposite(Composite parent, int style) {
      super(parent, style);
      setLayout(new FillLayout(SWT.HORIZONTAL));
     
      Composite composite = new Composite(this, SWT.NONE);
      composite.setLayout(new GridLayout(1, false));
     
      Button btnPreferredSite = new Button(composite, SWT.CHECK);
      btnPreferredSite.setText("Preferred Site");
     
      Label lblColumnWidth = new Label(composite, SWT.NONE);
      lblColumnWidth.setText("Column width");
     
      text = new Text(composite, SWT.BORDER);
      text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

  }

  @Override
  protected void checkSubclass() {
  }
}

BottomComposite

De la même manière, créez la classe BottomComposite:
Concevoir l'interface pour BottomComposite:
BottomComposite.java
package org.o7planning.tutorial.swt.module;

import org.eclipse.swt.SWT;

public class BottomComposite extends Composite {
  private Text text;

  /**
   * Create the composite.
   * @param parent
   * @param style
   */
  public BottomComposite(Composite parent, int style) {
      super(parent, style);
      setLayout(new FillLayout(SWT.HORIZONTAL));
     
      Composite composite = new Composite(this, SWT.NONE);
      composite.setLayout(new GridLayout(1, false));
     
      Composite composite_1 = new Composite(composite, SWT.NONE);
      GridLayout gl_composite_1 = new GridLayout(3, false);
      gl_composite_1.marginHeight = 0;
      gl_composite_1.marginWidth = 0;
      composite_1.setLayout(gl_composite_1);
      composite_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
     
      Button btnNewButton = new Button(composite_1, SWT.NONE);
      btnNewButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
      btnNewButton.setText("Add");
     
      Button btnNewButton_1 = new Button(composite_1, SWT.NONE);
      btnNewButton_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
      btnNewButton_1.setText("Delete");
     
      Button btnNewButton_2 = new Button(composite_1, SWT.NONE);
      btnNewButton_2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
      btnNewButton_2.setText("Clear");
     
      text = new Text(composite, SWT.BORDER | SWT.MULTI);
      text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

  }

  @Override
  protected void checkSubclass() {
      // Disable the check that prevents subclassing of SWT components
  }

}

MainComposite

Similairement, créez la classe MainComposite:

Enregistrez-vous TopComposite & BottomComposite sur Palette

Cliquez sur le bouton droit de Palette et sélectionnez Add category...
Baptisé Pallete Category:
  • My Composite
Cliquez sur le bouton droit de Pallette Category "My Composite" pour ajouter TopComposite & BottomComposite.
De la même facon, ajoutez BottomComposite au catalogue My Composite.
Maintenant TopComposite & BottomComposite sont facilement glissés et déplacés dans des autres Composite.
MainComposite.java
package org.o7planning.tutorial.swt.module;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;

public class MainComposite extends Composite {

  /**
   * Create the composite.
   * @param parent
   * @param style
   */
  public MainComposite(Composite parent, int style) {
      super(parent, style);
      setLayout(new FillLayout(SWT.HORIZONTAL));
     
      Composite composite = new Composite(this, SWT.NONE);
      composite.setLayout(new GridLayout(1, false));
     
      TopComposite topComposite = new TopComposite(composite, SWT.BORDER);
      topComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
     
      BottomComposite bottomComposite = new BottomComposite(composite, SWT.BORDER);
      bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

  }

  @Override
  protected void checkSubclass() {
  }

}

12- L'utilisation des gestionnaires d'événements

La gestion des événements SWT est très simple avec le support de WindowBuilder.

Des exemples:

  • File/New/Other...
  • Package: org.o7planning.tutorial.swt.event1
  • Name: ButtonEventDemo
Cliquez sur le bouton droit du Button, sélectionnez "Add event handler", une série des événementss de Button sera affichée.
WindowBuilder va automatiquement générer le code pour vous:
btnClickToMe.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {
        // Sử lý sự kiện Button được chọn tại đây.
        System.out.println("Button selected!");
    }
});
ButtonEventDemo.java
package org.o7planning.tutorial.swt.event1;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class ButtonEventDemo {

  protected Shell shlButtonEventDemo;

  public static void main(String[] args) {
      try {
          ButtonEventDemo window = new ButtonEventDemo();
          window.open();
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  public void open() {
      Display display = Display.getDefault();
      createContents();
      shlButtonEventDemo.open();
      shlButtonEventDemo.layout();
      while (!shlButtonEventDemo.isDisposed()) {
          if (!display.readAndDispatch()) {
              display.sleep();
          }
      }
  }

  protected void createContents() {
      shlButtonEventDemo = new Shell();
      shlButtonEventDemo.setSize(296, 205);
      shlButtonEventDemo.setText("Button Event Demo");
      shlButtonEventDemo.setLayout(new RowLayout(SWT.HORIZONTAL));

      Button btnClickToMe = new Button(shlButtonEventDemo, SWT.NONE);
      btnClickToMe.addSelectionListener(new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
              // Handle Button selected here!
              System.out.println("Button selected!");
          }
      });
      btnClickToMe.setText("Click to me");

  }

}

13- JFace

Vous pouvez voir plus de JFace, une API supplémentaire pour SWT: