GUI programmering i Java SWT och Lab 1 DVGA11 Översikt JAVA SWT/JFace Lab 1 Översikt till SWT Hemsida − http://www.eclipse.org/swt Tutorials online − http://www.cs.umanitoba.ca/~eclipse/ http://www.cs.umanitoba.ca/~eclipse/2-Basic.pdf Javadoc − http://help.eclipse.org/stable/nftopic/org.eclipse.platform. doc.isv/reference/api/overview-summary.html Översikt till SWT Standard Widget Toolkit (SWT) − Använder native widgets via JNI − Emulerar widgets som inte finns på host plattformen − Tillhandahåller MVC genom JFace. − Flexibilitet (traditionell eller MVC programmering) − Open source − kompilerar till native körbar fil med gcj SWT Hello World 1. import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; 2. import org.eclipse.swt.widgets.Shell; org.eclipse.swt.widgets.Shell; 3. public class HelloWorld { 4. public static void main(String[] args) args) { 5. Display display = new Display(); 6. Shell shell = new Shell(display); 7. shell.setText("Hello World"); 8. shell.setSize(250, 100); 9. 10. shell.open(); 11. 12. while (!shell.isDisposed ()) { (!shell.isDisposed()) 13. if (!display.readAndDispatch ()) { (!display.readAndDispatch()) 14. display.sleep(); 15. } 16. } 17. display.dispose(); 18. 19. } } SWT Hello World (fortsätt.) shell och display Shell objekt (rad 6) kan sägas motsvara JFrame i Swing, dvs topp nivå container som innehåller alla andra widgets (knappar, labels etc.) − Shell måste hållas öppet genom att lyssna efter event med en while loop (rad 12-16). Till skillnad mot swing − − Så måste man skapa ett Display objekt (rad 5), som representerar det underliggand fönsterhanteringssystemet. Eftersom man hanterar operativssystems objekt så fungerar inte heller garabage collectorn utan man måste själv se till att rensa upp (rad 17). Tar man bort föräldern tas dock alla barnen bort så vanligtvis är detta allt som krävs SWT Hello World (fortsätt.) SWTUtil • Känns det obekant att inte kunna använda garbage collectorn kan man skapa en SWTUtil klass (se höger) •SWTUtil.java import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; public class SWTUtil { private static Display display = new Display(); public static Shell getShell() getShell() { Hellow World som använder SWTUtil class Shell shell = new Shell(display); return shell; } import org.eclipse.swt.widgets.*; public static void openShell(Shell shell) { public class HelloWorld { shell.open(); public static void main(String[] args) { Shell shell = SWTUtil.getShell(); // This loop keeps the shell open constantly listening for events events while (!shell.isDisposed ()) { (!shell.isDisposed()) shell.setText(“Still Hello World"); if (!display.readAndDispatch ()) { (!display.readAndDispatch()) display.sleep(); shell.setSize(250, 100); } } SWTUtil.openShell(shell); display.dispose(); } } } } SWT Display org.eclipse.swt.widgets.Display Instanser av den här klassen sköter koppling mellan SWT och det underliggande operativsystemet. Den tillhandahåller även olika metoder för att komma åt information om operativsystemet och de resurser som allokeras av SWT I SWT så är det den tråd som skapar en instans av Display som anses vara UI tråden (för den displayen). SWT Shell org.eclipse.swt.widgets.Shell Shell klassen representerar “fönstret" som hanteras av fönsterhanteraren. Typer: − − “Top level shell” är ett shell som inte har någon förälder (de är skapade av konstruktorn som tar en Display som argument) Shell som har föräldrar anges som sekundära (secondary) eller dialog shells. Tillstånd: − − − Maximerad (Maximized) Minimerad (Minimized) Normal SWT Shell org.eclipse.swt.widgets.Shell Styles (specifika för varje klass): − BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL − Om man vill använda mer än en style kan man använde dem genom bitvis or operator “|” (ex. CLOSE | TITLE | MIN). − Vill man inte ha någon specifik style använd SWT.NONE. − Style är bara ett förslag, kan inte det underliggande operativsystemet visa en style så använder den en default Fördefinerade konstanter: − SHELL_TRIM − En sammanslagning av styles (CLOSE | TITLE | MIN | MAX | RESIZE) för att skapa ett typiskt applikations fönster. DIALOG_TRIM En sammanslagning av styles (TITLE | CLOSE | BORDER) för att skapa ett typiskt dialog ruta. SWT Widget org.eclipse.swt.widgets.Widget Widget klassen är den abstrakta superklassen för alla interface objekt En widget skapas genom att både specificera en förälder och en style En förälder är den container som widgeten är skapade inuti (ex. Shell). Style beror på vilken widget det är se − http://www.eclipse.org/swt/widge ts/ org.eclipse.swt.widgets.Label SWT Label Ej editerbar och ej valbar text SWT.VERTICAL eller SWT.HORIZONTAL kan användas tillsammans med SWT.SEPARATOR för att skapa horisontella/vertikala separatorer LabelWorld.java 1.import org.eclipse.swt.SWT; org.eclipse.swt.SWT; 2.import org.eclipse.swt.layout.GridLayout; org.eclipse.swt.layout.GridLayout; 3.import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; 4.public class LabelWorld { 5. public static void main(String[] args) args) { 6. Shell shell = SWTUtil.getShell(); SWTUtil.getShell(); 7. shell.setText("Label World"); 8. shell.setLayout(new GridLayout()); GridLayout()); 9. // Create labels 10. new Label(shell, SWT.NONE).setText("Regular label"); 11. new Label(shell, SWT.SEPARATOR); new Label(shell, SWT.SEPARATOR|SWT.HORIZONTAL); 12. 13. 14. // pack and show 15. shell.pack(); 16. SWTUtil.openShell(shell); SWTUtil.openShell(shell); 17. 18.} } SWT Button org.eclipse.swt.widgets.Button Alla typer av knappar skapas genom att använda Button klassen. − Klickbar widget, skickar en notifikation när den är klickad på. − Styles: ARROW, CHECK, PUSH, RADIO, TOGGLE, FLAT, UP, DOWN, LEFT, RIGHT, CENTER 9. ButtonWorld.java 10. new Button(shell, SWT.PUSH | SWT.FLAT).setText("Flat Push Button"); 11. new Button(shell, SWT.CHECK).setText("Check Button"); 12. new Button(shell, SWT.TOGGLE).setText("Toggle Button"); 13. new Button(shell, SWT.RADIO).setText("Radio Button"); 1.import org.eclipse.swt.SWT; org.eclipse.swt.SWT; 2.import org.eclipse.swt.layout.GridLayout; org.eclipse.swt.layout.GridLayout; 14. 3.import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; 4.public 5. class ButtonWorld { public static void main(String[] args) args) { 6. Shell shell = SWTUtil.getShell(); SWTUtil.getShell(); 7. shell.setText("Button World"); shell.setLayout(new GridLayout(2, true)); 8. 15. // pack and show 16. shell.pack(); 17. SWTUtil.openShell(shell); SWTUtil.openShell(shell); } 18. 19. } SWT Text org.eclipse.swt.widgets.Text Textruta där användaren kan skriva in text och ändra text − Styles: CENTER, LEFT, MULTI, PASSWORD, SINGLE, RIGHT, READ_ONLY, WRAP TextWorld.java 10. new Text(shell, SWT.NONE).setText("Missing something ..."); 1. import org.eclipse.swt.SWT; org.eclipse.swt.SWT; 11. new Text(shell, SWT.BORDER); // regular textfield 2. import org.eclipse.swt.layout.GridLayout; org.eclipse.swt.layout.GridLayout; 12. new Text(shell, SWT.PASSWORD | SWT.BORDER).setText("password"); SWT.BORDER).setText("password"); 3. import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; 13. new Text(shell, SWT.READ_ONLY | SWT.BORDER).setText("Can't type inside"); 14. new Text(shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP 4. 5. public class TextWorld { public static void main(String[] args) args) { | SWT.BORDER).setText("\ SWT.BORDER).setText("\n\n\n"); 15. 16. 6. Shell shell = SWTUtil.getShell(); SWTUtil.getShell(); 17. // pack and show 7. shell.setText("Text World"); 18. shell.pack(); 8. shell.setLayout(new GridLayout()); GridLayout()); 19. SWTUtil.openShell(shell); SWTUtil.openShell(shell); 9. 20. 21. } } SWT Combo org.eclipse.swt.widgets.Combo Välj ifrån en lista/meny – enkel eller multival möjligt − Styles: DROP_DOWN, READ_ONLY, SIMPLE ComboWorld.java 1. import org.eclipse.swt.SWT; org.eclipse.swt.SWT; 2. import org.eclipse.swt.layout.GridLayout; org.eclipse.swt.layout.GridLayout; 3. import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; 4. 5. public class ComboWorld { public static void main(String[] args) args) { 14. two.setItems(items); two.setItems(items); 15. Combo three = new Combo(shell, SWT.SIMPLE); 16. three.setItems(items); three.setItems(items); 17. 18. // pack and show 19. shell.pack(); 20. SWTUtil.openShell(shell); SWTUtil.openShell(shell); } 21. 6. Shell shell = SWTUtil.getShell(); SWTUtil.getShell(); 7. shell.setText("Combo World"); 8. shell.setLayout(new GridLayout(3, true)); 9. String[] items = "One Two Three Four Five Six".split(" "); 10. Combo one = new Combo(shell, SWT.DROP_DOWN); 11. one.setItems(items); one.setItems(items); 12. 13. 22. Combo two = new Combo(shell, SWT.DROP_DOWN | SWT.READ_ONLY); } SWT Composites org.eclipse.swt.widgets.Composite Instanser av den här klassen är en widget som kan innehålla andra widgets (knappar etc). Widget w = new Widget(composite, SWT.NONE); ... public class CompositeExample { ... public CompositeExample() { ... // Build the components Composite c1 = new Composite( shell, SWT.NULL ); c1.setLayout( new FillLayout() ); Button b1 = new Button( c1, SWT.PUSH ); b1.setText( "Button on Composite 1" ); Composite c2 = new Composite( shell, SWT.NULL ); c2.setLayout( new FillLayout() ); Button b2 = new Button( c2, SWT.PUSH ); b2.setText( "Button on Composite 2" ); ... } ... } SWT Layouts org.eclipse.swt.widgets.Layout En layout bestämmer position och storlek på en composite widget SWT har 5 layouter: − FillLayout − RowLayout − StackLayout − GridLayout − FormLayout Man applicerar en layout genom att anropa setLayout() http://www.eclipse.org/articles/Article-Understanding-Layouts/Understanding-Layouts.htm SWT Layouts (forts.) org.eclipse.swt.layout.FillLayout Placerar alla widgets in en kolumn eller rad − FillLayout SWT.VERTICAL eller SWT.HORIZONTAL Alla widgets får samma storlek SWT Layouts (forts.) RowLayout org.eclipse.swt.layout.RowLayout Liknar Filllayout men tvingar inte alla widgets att vara lika stora Byter rad om inte alla widgets får plats SWT Layouts (forts.) GridLayout org.eclipse.swt.layout.GridLayout Som namnet antyder läggs widgets ut i en grid. 6 attributes (defaults är definerade): − boolean makeColumnsEqualWidth – alla kolumner får samma vidd − int numColumns – antal kolumner − int marginWidth, int marginHeight, int horizontalSpacing, int verticalSpacing Bestämmer avstånd till andra objekt och avstånd mellan celler GridLayout(int numColumns, boolean makeColumnsEqualWidth) För ytterliggare kontroll använd GridData objekts − OBS ett gridData objekt skall inte återanvändas för flera layouter. SWT Layouts (forts.) GridData org.eclipse.swt.layout.GridData GridData är det layout data objekt som man assoscierar med GridLayout. För att aktivera ett GridData objekt för en widget så använder man widget.setLayoutData(Object) metoden. Det finns 2 sätt att skapa specifika GridData objekt. Första sättet är att sätta attributen: − GridData gridData = new GridData(); − gridData.horizontalAlignment = GridData.FILL; − gridData.grabExcessHorizontalSpace = true; − button1.setLayoutData(gridData); Det andra är att använda fördefinerade “style bits”: − button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); SWT Layouts (forts.) GridLayout exempel org.eclipse.swt.layout.GridLayout 17. 1. import org.eclipse.swt.SWT; org.eclipse.swt.SWT; 18. 2. import org.eclipse.swt.layout.*; org.eclipse.swt.layout.*; 19. 3. import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; // Password new Label(shell, SWT.RIGHT).setText("Password:"); SWT.RIGHT).setText("Password:"); new Text(shell,SWT.BORDER| SWT.PASSWORD) 20. .GridData(GridData.FILL_HORIZONTAL)); GridData(GridData.FILL_HORIZONTAL)); 4. 5. public class GridLayoutExample { public static void main(String[] args) args) { 21. // Login Button 22. 6. Shell shell = SWTUtil.getShell(); SWTUtil.getShell(); 23. Button loginButton = new Button(shell, SWT.PUSH | SWT.FLAT); shell.setText("GridLayoutExample"); shell.setText("GridLayoutExample"); 24. 7. loginButton.setText("Proceed to your account"); 25. GridData data = new GridData(GridData.FILL_HORIZONTAL); GridData(GridData.FILL_HORIZONTAL); 8. shell.setLayout(new GridLayout(2, false)); // 2 columns, same width 26. data.horizontalSpan = 2; // span 2 columns 27. loginButton.setLayoutData(data); 9. 10. // Username 11. new Label(shell, SWT.RIGHT).setText("Username:"); SWT.RIGHT).setText("Username:"); 12. Combo cmbUsername = new Combo(shell, SWT.DROP_DOWN); 13. cmbUsername.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); GridData(GridData.FILL_HORIZONTAL)); 14. cmbUsername.setItems(new String[]{"Howard", "Admin", "Kalman "}); "Kalman"}); 15. cmbUsername.setText("Admin"); cmbUsername.setText("Admin"); 16. 28. shell.pack(); 29. SWTUtil.openShell(shell); SWTUtil.openShell(shell); } 30. 31. } Events org.eclipse.swt.events SWT widgets kan lyssna efter events − − För att kunna lyssna på ett event så måste en lyssnare (listener) läggas till widgeten Ibland så kan en lyssnare lyssna på för många olika saker Då använder man en adapter. Några popolära lyssnare/adaptrar − − − − − − FocusListener/FocusAdapter – fokus event KeyListener/KeyAdapter – tangenttryckningar ModifyListener(1 method) – textändringar VerifyListener – lyssnare efter och fångar upp textändringar MouseListener/MouseAdapter – mustryck/klick SelectionListener/SelectionAdapter – selection events (liknande ActionListener i Swing) Events (EventHandling.java) 1. import org.eclipse.swt.SWT; org.eclipse.swt.SWT; import org.eclipse.swt.events.*; org.eclipse.swt.events.*; 29. 2. Button btnAllow = new Button(shell, SWT.CHECK); 3. import org.eclipse.swt.layout.*; org.eclipse.swt.layout.*; 30. btnAllow.setText("Allow numbers only"); 4. import org.eclipse.swt.widgets.*; org.eclipse.swt.widgets.*; 31. 5. public class EventHandling { 32. data.horizontalSpan = 2; 33. btnAllow.setLayoutData(data); btnAllow.setLayoutData(data); 6. private static boolean numbersOnly; numbersOnly; 7. public static void main(String[] args) args) { 8. Shell shell = SWTUtil.getShell(); SWTUtil.getShell(); 9. shell.setText("EventHandling"); shell.setText("EventHandling"); 10. shell.setLayout(new GridLayout(2, false)); 11. 12. // input 13. Label lblInput = new Label(shell, SWT.RIGHT); 14. lblInput.setText("Type in here:"); 15. GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END); GridData(GridData.HORIZONTAL_ALIGN_END); 16. 34. data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); GridData(GridData.HORIZONTAL_ALIGN_CENTER); btnAllow.addSelectionListener(new SelectionAdapter() SelectionAdapter() { 35. public void widgetSelected(SelectionEvent selectionEvent) selectionEvent) { 36. numbersOnly = ((Button)(selectionEvent.widget)).getSelection (); ((Button)(selectionEvent.widget)).getSelection(); } 37. 38. }); lblInput.setLayoutData(data); lblInput.setLayoutData(data); 39. shell.pack(); 17. Text input = new Text(shell, SWT.BORDER); 40. SWTUtil.openShell(shell); SWTUtil.openShell(shell); 18. input.addVerifyListener(new VerifyListener() VerifyListener() { 19. 20. vEvent.doit = false; // don't allow anything but numbers 21. if(!numbersOnly || vEvent.character == '\ '\b') { vEvent.doit = true; 22. 23. } 24. else if(Character.isDigit(vEvent.character) if(Character.isDigit(vEvent.character) && numbersOnly) numbersOnly) { vEvent.doit = true; 25. } 26. } 27. 28. }); } 41. public void verifyText(VerifyEvent vEvent) vEvent) { 42. } syncExec() / asyncExec() org.eclipse.swt.events Man skall endast uppdatera UIet ifrån UI tråden − För att uppdatera en Label i UI (huvud) tråden ifrån en annan tråd så kan man INTE anropa label.setText(Värde) ifrån den andra tråden. För att uppdatera så anropar man (på Displayen): − syncExec(Runnable) om den anropande tråden kräver svar eller måste veta att UI tråden är klar innan den fortsätter. − asyncExec(Runnable) om man skall göra en UI operation som inte kräver nått svar eller är oavhängigt av den anropande trådens exekvering syncExec() / asyncExec() Exempel kod för att uppdater en Label ungefär 1 gång i sekunden ifrån en annan tråd 1. new Thread(new Runnable() Runnable() { 2. public void run() { 3. Display display = shell.getDisplay(); shell.getDisplay(); 4. while(!shell.isDisposed()) while(!shell.isDisposed()) { //kontrollera //kontrollera så att shellet inte har kastats 5. try { display.asyncExec(new Runnable() Runnable() { 6. public void run() { 7. clock.setText((new Date()).toString()); Date()).toString()); 8. } 9. }); //slut parantes ifrå ifrån 6 10. Thread.sleep(1000); 11. 12. } 13. catch (InterruptedException (InterruptedException e) { e.printStackTrace(); e.printStackTrace(); 14. } 15. } 16. 17. 18. } }).start(); //slut parantes ifrå ifrån 1 JFace org.eclipse.jface.* Bild och font register för att hantera OS resurser Dialoger och wizards Progress bars Action mekanism − Action mekanismen separerar användarkommandon från var de hände i UI. En action representerar ett användarkommando (event). − Viewers och editors Model-baserade adapters för några SWT widgets som JFace tillhandahåller hög-nivå semantik för. http://download.eclipse.org/eclipse/downloads/documentation/2.0/html/plugins/org.eclipse.platform.doc.isv/reference/a pi/overview-summary.html JFace exempel 1/3 1. /** 2. * Represents a category of items. items. 3. * 4. */ 5. class Category { 6. private String name; name; 7. private Vector subCategories; subCategories; 8. private Category parent; parent; 9. public Category(String name, name, Category parent) parent) { 10. 11. this.name = name; name; 12. this.parent = parent; parent; 13. if(parent != null) null) parent.addSubCategory(this); parent.addSubCategory(this); 14. 15. } 16. public Vector getSubCategories() getSubCategories() { return subCategories; subCategories; 17. 18. } 19. private void addSubCategory(Category subcategory) subcategory) { if(subCategories == null) null) 20. Vector categories = new Vector(); 2. Category category = new Category(“ Category(“Java libraries” libraries”, null); 3. categories.add(category); categories.add(category); 4. category = new Category(“ Category(“UI Toolkits” Toolkits”, category); 5. new Category(“ Category(“AWT” AWT”, category); 6. new Category(“ Category(“Swing” Swing”, category); 7. new Category(“ Category(“SWT/JFace” SWT/JFace”, category); 8. category = new Category(“ Category(“Java IDEs” IDEs”, null); 9. categories.add(category); categories.add(category); 10. new Category(“ Category(“Eclipse” Eclipse”, category); 11. new Category(“ Category(“JBuilder” JBuilder”, category); subCategories = new Vector(); Vector(); 21. if(! if(! subCategories.contains(subcategory)) subCategories.contains(subcategory)) 22. subCategories.add(subcategory); subCategories.add(subcategory); 23. 24. } 25. public String getName() getName() { return name; name; 26. 27. } 28. public Category getParent() getParent() { return parent; parent; 29. } 30. 31. 1. } http://media.wiley.com/product_data/excerpt/91/04700945/0470094591.pdf JFace exempel 2/3 På ”traditionellt sätt” utan MVC final Tree tree = new Tree(shell, Tree(shell, SWT.BORDER); 12. 1. /** /** 13. 2. * Adds a category to the tree (recursively). recursively). * Builds up the tree with traditional approach. 14. 3. * @param @param parentItem * 15. 4. * @param @param category */ 16. 5. */ public void traditional() traditional() { 17. private void addCategory(TreeItem parentItem, parentItem, Category category) category) { 6. for(int i=0; categories != null && i < categories.size(); categories.size(); i++) { 7. Category category = (Category)categories.elementAt(i ); (Category)categories.elementAt(i); 19. 8. addCategory(null, addCategory(null, category); category); 20. 9. } 10. 11. } TreeItem item = null; null; 18. if(parentItem == null) null) item = new TreeItem(tree, TreeItem(tree, SWT.NONE); else 21. item = new TreeItem(parentItem, TreeItem(parentItem, SWT.NONE); 22. 23. item.setText(category.getName()); item.setText(category.getName()); 24. Vector subs = category.getSubCategories(); category.getSubCategories(); 25. for(int i=0; subs != null && i < subs.size(); subs.size(); i++) addCategory(item, )); addCategory(item, (Category)subs.elementAt(i (Category)subs.elementAt(i)); 26. 27. } http://media.wiley.com/product_data/excerpt/91/04700945/0470094591.pdf JFace exempel 3/3 Med MVC 1. final Tree tree = new Tree(shell, Tree(shell, SWT.BORDER); 20. public Object[] Object[] getElements(Object inputElement) inputElement) { if(inputElement != null && inputElement instanceof Vector) Vector) { 21. 2. /** 3. * Builds up the tree with the MVC approach. 4. return ((Vector)inputElement).toArray (); ((Vector)inputElement).toArray(); 22. } 23. return new Object[0]; 24. * } 25. 5. */ 6. public void MVC() { public void dispose() dispose() { 26. 7. 8. 9. TreeViewer treeViewer = new TreeViewer(tree); TreeViewer(tree); 28. } 29. public void inputChanged(Viewer viewer, viewer, Object oldInput, oldInput, Object newInput) newInput) { treeViewer.setContentProvider(new ITreeContentProvider() ITreeContentProvider() { public Object[] Object[] getChildren(Object parentElement) parentElement) { Vector subcats = ((Category)parentElement).getSubCategories (); ((Category)parentElement).getSubCategories(); 10. return subcats == null ? new Object[0] : subcats.toArray(); subcats.toArray(); 11. 12. // 27. } // 30. } 31. 32. }); 33. treeViewer.setLabelProvider(new LabelProvider() LabelProvider() { 13. public Object getParent(Object element) { 14. return ((Category)element).getParent (); ((Category)element).getParent(); 15. 16. public String getText(Object element) { 34. return ((Category)element).getName (); ((Category)element).getName(); 35. } } 36. 17. public boolean hasChildren(Object element) { return ((Category)element).getSubCategories () != null; ((Category)element).getSubCategories() null; 18. 19. }); 37. } treeViewer.setInput(categories); treeViewer.setInput(categories); 38. 39. } http://media.wiley.com/product_data/excerpt/91/04700945/0470094591.pdf Lab 1 Luffarschak (Tic-Tac-Toe) Uppgift: Skriv ett luffarschack spel som går att spela (ingen AI). − Krav (grundläggande) − − Språk : Java SWT Programmet skall kunna köras utan eclipse med kommandot java -jar programnamn.jar Programmet skall använda SWT (ev. JFace) Frivillig Extra uppgift − Lösningen skall vara implementerad med MVC mönstret Lab 1 Arbetsgång Indentifiera problem − Vad är Luffaschack − Ett spel bestående av 3x3 rutor där varje spelare (X och O) försöker få 3 i rad (horisontellt vertikalt eller diagonalt (de turas om att spela). Hur representerar jag detta Som ett rutnät på 3x3 med en knapp i varje ruta. Varje knapp skriver in X el O beroende på vilkens drag det var när man klickade på den − − ”sätter sig” sedan i disabled läge så man inte kan trycka på den igen. Problem Hur kan man veta vilkens tur det är? Hur veta när någon vunnit? Hur vet när spelet är slut (om ingen vunnit före detta)? Lab 1 Lab 1 Arbetsgång Layout problem − Nyckelord : Knapp problem (storlek) − Nyckelord : shell setLayout GridLayout setLayoutData GridData GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL Event problem − Nyckelord : addSelectionListener SelectionAdapter widgetSelected Lab 1 Arbetsgång Hur kan man få reda på vems tur det är − − Man kan ha en variabel som alternerar mellan 2 värden Modulo 2 på en räknare som räknar antal drag (resten blir 0 varannan gång) Hur kan man veta att spelet är slut (om ingen vunnit) − − Alla knapparna är “disabled” Räkna hur många drag som gjorts (9 rutor, ett klick per ruta) Lab 1 Arbetsgång Hur veta om någon har vunnit − Finns bara ett fixt antal sätt att vinna på − Kolla alla möjliga vinstkombinationer med if satser Lab 1 Arbetsgång Hur veta om någon har vunnit − Skapa en matris med “vinstkombinationer” − Loopa över knapparna och kolla mot matrisen http://forum.codecall.net/java-tutorials/2141-java-tutorial-tic-tac-toe.html