560 likes | 664 Vues
Standard Widget Toolkit. ECESIS Eclipse Community Education Project An Eclipse Technology Research Subproject. Jak budować interfejs użytkownika?. Topics. SWT czy Swing? Terminologia Prosty program w SWT Wzorzec Observer Widgets Menus Layouts Graphics Drag and Drop. Swing.
E N D
Standard Widget Toolkit ECESISEclipse Community Education ProjectAn Eclipse Technology Research Subproject Jak budować interfejs użytkownika?
Topics • SWT czy Swing? • Terminologia • Prosty program w SWT • Wzorzec Observer • Widgets • Menus • Layouts • Graphics • Drag and Drop
Swing • Biblioteka GUI w javie (javax.swing.*) • Była mało wydajna (poprawionow Java 1.4) • Napisana w Javie (korzysta AWT – Java / C) • Niezależna platformowo (daleko od OS) Swing java.awt sun.awt Operating system
SWT • Zależna od platformy (dostępne implementacje dla większości popularnych platform) • Wykorzystuje komponenty OS (JNI) – dispose! • Tylko kontrolki nie obsługiwane przez dany system zostały stworzone • Posiada wsparcie w postaci JFace JFace SWT JNI Windowing system Operating system
SWT vs. Swing • Zależny od platformy • Wydajny (Komponenty z systemu operacyjnego) • Wykorzystuje wzorzec observer • Menadżery rozmieszczenia • Niezależny od platformy • Niewydajny • Look and Feel • Wykorzystuje wzorze observer • Menadżery rozmieszczenia JFace SWT Swing java.awt JNI sun.awt Windowing system Operating system Operating system
org.eclipse.swt.SWT • Klasa z polami static public • Dostarcza stałe dla SWT • Bez instancji (eg. SWT.BOLD) • Stałe w SWT można sumować bitowo (eg. SWT.BOLD | SWT.ITALIC) SWT
Terminy • Display • Połączenie między SWT i systemem GUI danej platformy • Wykorzystywana do zarządzania pętlą komunikatów i wątkami UI • Shell • Okno zarządzane przez Window menadżer danego OS • Composite • Widget, który może zawierać inne widgety • Layout manager • Klasa odpowiedzialna za zarządzanie rozkładem
Jak uruchomić program w SWT? • classpath SWT.jar library (eclipse/plugins) • Add to the JVM arguments • Djava.library.path=<katalog z dll> • albo wybrać Run as ... SWT Application • JFace wymaga bibliotek: • org.eclipse.jface_x.jar, org.eclipse.core.commands_x.jar, org.eclipse.equinox.common_x.jar, (org.eclipse.osgi) • Podczas pisania pluginów nie trzeba się tym martwić!
Basic SWT application publicstaticvoidmain(String[]args){ Displaydisplay=newDisplay(); Shellshell=newShell(display); Labellabel=newLabel(shell,SWT.CENTER); label.setText(”Witaj świecie"); label.pack(); shell.pack(); shell.open(); while(!shell.isDisposed()){ if(!display.readAndDispatch()) display.sleep(); } display.dispose(); } Snippet
Wzorzec Observer Następny proszę! Lalaaaalalaa! Dziękujemy. Proszę nie dzwonić, to my zadzwonimy… Broadway
SWT&Observer Object publicvoid addListener (int eventType, Listener listener) Widget publicinterface Listener { void handleEvent (Event event); } Control Button publicvoid addSelectionListener (SelectionListener listener) Scrollable publicinterface SelectionListener extends SWTEventListener { publicvoid widgetSelected(SelectionEvent e); publicvoid widgetDefaultSelected(SelectionEvent e); } Composite
SWT&Composite Object public Control (Composite parent, int style) Widget Button button = new Button(shell,SWT.PUSH); * Control Button Scrollable Composite
Label Label label = new Label(shell, SWT.CENTER); label.setText("Hello World"); label.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE)); Snippet
Button Snippet Button button = new Button(shell, SWT.PUSH); button.setText("Click me!"); Button button = new Button(shell, SWT.CHECK); button.setText("Click me!"); Button button = new Button(shell, SWT.ARROW|SWT.RIGHT); Button button = new Button(shell, SWT.RADIO); button.setText("Click me!"); Button button = new Button(shell, SWT.TOGGLE); button.setText("Click me!");
Button Usage Button button = new Button(shell, SWT.PUSH); button.setText("Click me!"); button.addSelectionListener(new SelectionListener(){ publicvoid widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } publicvoid widgetSelected(SelectionEvent e) { System.out.println(e.getSource().toString()+" was clicked!"); } }); Button {Click me!} was clicked! Snippet
Text Text text = new Text(shell, SWT.SINGLE | SWT.BORDER); text.setText("Text"); Text text = new Text(shell, SWT.MULTI | SWT.BORDER | SWT.VERTICAL); text.setText("Text\nText"); Text text = new Text(shell, SWT.PASSWORD | SWT.SINGLE | SWT.BORDER); text.setText("Text"); Snippet
Text Usage Text text = new Text(shell, SWT.SINGLE | SWT.BORDER); text.addVerifyListener(new VerifyListener(){ publicvoid verifyText(VerifyEvent e) { if (e.text.matches("[0-9]*")){ e.doit = true; }else{ e.doit = false; } } }); text.addModifyListener(new ModifyListener(){ publicvoid modifyText(ModifyEvent e) { System.out.println(((Text)(e.widget)).getText()+ " - text after modification"); } }); 2 - text after modification 23 - text after modification 232 - text after modification 2321 - text after modification 23212 - text after modification 232123 - text after modification 2321231 - text after modification Snippet
ProgressBar Snippet ProgressBar pb = new ProgressBar(shell, SWT.SMOOTH); pb.setMinimum(0); pb.setMaximum(100); pb.setSelection(34); ProgressBar pb = new ProgressBar(shell, SWT.SMOOTH | SWT.INDETERMINATE); pb.setMinimum(0); pb.setMaximum(100);
Slider and Scale Slider slider = new Slider(shell, SWT.HORIZONTAL); slider.setMinimum(0); slider.setMaximum(100); slider.setSelection(30); Snippet Scale scale = new Scale(shell, SWT.HORIZONTAL); scale.setMinimum(0); scale.setMaximum(100); scale.setSelection(30);
List Snippet List list = new List(shell, SWT.MULTI); list.add("First"); list.add("Second"); list.add("Third"); list.addSelectionListener(new SelectionListener(){ publicvoid widgetDefaultSelected(SelectionEvent e) { System.out.println("Default action - double click(Windows)"); widgetSelected(e); } publicvoid widgetSelected(SelectionEvent e) { System.out.println("Selected items:"); String[] selection = ((List)(e.widget)).getSelection(); for (int i = 0; i < selection.length; i++) { System.out.println(" - "+selection[i]+""); } } });
Combo Snippet Combo combo = new Combo(shell, SWT.DROP_DOWN); combo.add("First"); combo.add("Second"); combo.add("Third"); combo.addSelectionListener(new SelectionListener(){ publicvoid widgetDefaultSelected(SelectionEvent e) { System.out.println("Default action - Enter (Windows)"); widgetSelected(e); } publicvoid widgetSelected(SelectionEvent e) { System.out.println("Selected "+((Combo)(e.widget)).getText()); } });
Tree Tree tree = new Tree(shell, SWT.SINGLE); TreeItem node1 = new TreeItem(tree, SWT.NULL); node1.setText("1. Main node"); TreeItem node11 = new TreeItem(node1, SWT.NULL); node11.setText("1.1 First sub node"); TreeItem node12 = new TreeItem(node1, SWT.NULL); node12.setText("1.2 First sub node"); tree.addTreeListener(new TreeListener(){ publicvoid treeCollapsed(TreeEvent e) { System.out.println(((TreeItem)e.item).getText()+ " was collapsed"); } publicvoid treeExpanded(TreeEvent e) { System.out.println(((TreeItem)e.item).getText()+ " was expanded"); } }); Snippet
Menu Menu menuBar = new Menu(shell, SWT.BAR); shell.setMenuBar(menuBar); MenuItem fileTitle = new MenuItem(menuBar, SWT.CASCADE); fileTitle.setText("File"); Menu fileMenu = new Menu(shell, SWT.DROP_DOWN); fileTitle.setMenu(fileMenu); MenuItem exitItem = new MenuItem(fileMenu, SWT.PUSH); exitItem.setText("Exit"); exitItem.addSelectionListener(new SelectionListener(){ publicvoid widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } publicvoid widgetSelected(SelectionEvent e) { ((MenuItem)(e.widget)).getParent().getShell().close(); } }); SWT.BAR SWT.DROP_DOWN SWT.POP_UP setManuBar – SWT.BAR setMenu – SWT.POP_UP SWT.CHECK SWT.CASCADE SWT.PUSH SWT.RADIO SWT.SEPARATOR Snippet
Layouts • Kontroluje rozmiar i rozmieszczenie komponentów • Klasy menadżerów, są podklasami abstrakcyjnej klasy Layout • SWT udostępnia kilka podstawowych layout’ów • FillLayout, rozmieszcza komponenty w rzędzie lub w kolumnie, równych rozmiarów, wypełniając dostępne miejsce • RowLayout, ustawia komponenty w rzędzie lub kolumnie • GridLayout, wpisuje komponenty w siatkę • FormLayout, ustawia komponenty doczepiając je między sobą
Praca z Layout’ami • Importujemy odpowiedni pakiet SWT: • import org.eclipse.swt.layout.*; • Aby przypisać Layout obiektowi klasy Composite użyjsetLayout(Layout) Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FillLayout());
Layout Data • Klasy layout’ów często wykorzystują pomocnicze klasy nazywane ogólnie LayoutData • RowLayout -> RowData • GridLayout -> GridData • FormLayout -> FormData • Przypisanie danych układu Button button = new Button(shell, SWT.PUSH); button.setLayoutData(new RowData(10, 20));
FillLayout • Ustawia komponenty w rzędzie lub kolumnie • Wszystkie tego samego rozmiaru • Bez zawijania wierszy • Nie można zdefiniować marginesów i odstępów • Wykorzystywany do: • Umieszczanie przycisków na paskach zadań • Umieszczania checkbox’ów w grupy
FillLayout Example Displaydisplay=newDisplay(); Shellshell=newShell(display); FillLayoutfillLayout=newFillLayout(); fillLayout.type=SWT.VERTICAL; shell.setLayout(fillLayout); newButton(shell,SWT.PUSH).setText("1'st Button"); newButton(shell,SWT.PUSH).setText("Big Button"); newButton(shell,SWT.PUSH).setText("Button 3"); newButton(shell,SWT.PUSH).setText("Last Button"); shell.pack(); shell.open();
FillLayout Example fillLayout.type = SWT.VERTICAL; fillLayout.type = SWT.HORIZONTAL; Snippet
RowLayout • RowLayout ma możliwość zawijania wierszy • Można ustawiać marginesy i odległości • Różne właściwości mogą zostać ustawione • Wysokość i szerokość widget’ów • Użyjobiektu klasy RowData
RowLayout Example RowLayoutrowLayout=newRowLayout(); rowLayout.wrap=true; rowLayout.pack=true; rowLayout.justify=true; rowLayout.type=SWT.HORIZONTAL; rowLayout.marginLeft=4; rowLayout.marginTop=4; rowLayout.marginRight=4; rowLayout.marginBottom=4; rowLayout.spacing=0; shell.setLayout(rowLayout);
RowLayout Example rowLayout.wrap=false; rowLayout.pack=false; rowLayout.justify=false;
RowData Example RowLayoutrowLayout=newRowLayout(); shell.setLayout(rowLayout); Buttonbutton1=newButton(shell,SWT.PUSH); button1.setText("First"); button1.setLayoutData(newRowData(50,100)); Buttonbutton2=newButton(shell,SWT.PUSH); button2.setText("Second"); button2.setLayoutData(newRowData(200,400));
GridLayout • Chyba najczęściej wykorzystywany • Najbardziej rozbudowany • Komponenty wpisane w siatkę • Kolumny i rzędy dostowują się do wielkości zawartości • Różne wartości mogą zostać ustawione • Do komponentów można dodawać GridData
GridLayout Example GridLayoutgridLayout=newGridLayout(); gridLayout.numColumns=2; shell.setLayout(gridLayout); newButton(shell,SWT.PUSH).setText("B1"); newButton(shell,SWT.PUSH).setText("Second Button"); newButton(shell,SWT.PUSH).setText("Third Button"); newButton(shell,SWT.PUSH).setText("B4"); newButton(shell,SWT.PUSH).setText("B5"); newButton(shell,SWT.PUSH).setText("Button Number 6");
GridLayout Fields • Pola • makeColumnsEqualWidthnarzuca kolumną równą szerokość • marginWidthustala lewy i prawy margines • marginHeightustala górny i dolny margines • horizontalSpacingiverticalSpacingodległości między komponentami
GridData • Zawiera wskazówki dla GridLayout • Dodaje się za pomocą metodysetLayoutData ButtonaButton=newButton(shell,SWT.PUSH); aButton.setText("FirstButton"); aButton.setLayoutData(newGridData());
GridData Fields • horizontalAlignment: specyfikuje gdzie umiścić widget horyzontalnie lub wertykalnie w komórce siatki • BEGINNING, CENTER, END, FILL • horizontalIndent: umożliwia przesunięcie kontrolki w prawo o wybraną liczbę pixeli • Użyteczne kiedyhorizontalAlignmentjestBEGINNING • horizontalSpaniverticalSpan: jedna kontrolka może zajmować kilka komórek
GridData Fields • grabExcessHorizontalSpaceigrabExcessVerticalSpace: pozwala kontrolkom zwiększać rozmiar jeśli ich rodzic zmienia rozmiar • widthHintiheightHint: zalecany rozmiar kontrolki Snippet
Ćwiczenie - rozwiązanie GridLayoutgridLayout=newGridLayout(); gridLayout.numColumns=3; shell.setLayout(gridLayout); newLabel(shell,SWT.NONE).setText(„Name:"); TextuserName=newText(shell,SWT.SINGLE|SWT.BORDER); GridDatagridData=newGridData(GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan=2; userName.setLayoutData(gridData); … Każdy widget musi mieć własną instancję GridData
Ćwiczenie - rozwiązanie newLabel(shell,SWT.NONE).setText(”Sex:"); Combosex=newCombo(shell,SWT.NONE); sex.setItems(newString[]{"Male","Female"}); gridData=newGridData(GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan=2; sex.setLayoutData(gridData); newLabel(shell,SWT.NONE).setText("Photo:"); Canvasphoto=newCanvas(shell,SWT.BORDER); gridData=newGridData(GridData.FILL_BOTH); gridData.widthHint=80; gridData.heightHint=80; gridData.verticalSpan=3; photo.setLayoutData(gridData);
FormLayout • TworzyFormAttachmentsdla krawędzi widget’a • Przechowuje attachments jako layout data • Przyłącza krawędź relatywnie do Composite’a rodzicainnego widget’a w ramach layout’u • Pozwala w pełni wyspecyfikować położenie widgetu http://www.eclipse.org/articles/Article-Understanding-Layouts/Understanding-Layouts.htm
Graphics • GC – Graphics Context (można rysować po wszystkich klasach które implementują interfejs Drawable (np. Image, Control, Canvas itd.) • Jeśli używasz konstruktora GC(), nie zapomnij dispose! • Rysowania dokonujemy wewnątrz metody paintControl(PaintEvent) należącej do PaintListener Composite.addPaintListener(new PaintListener(){ public void paintControl(PaintEvent event){ Display display = event.display; GC gc = event.gc gc.drawRectangle(0,0,10,10); } });