Uppgift Konstruktion av användargränssnitt Uppgift Syfte Under fjärde uppgiften kommer ni att få känna på lite mer om trådning, avbrottsstyrning. Efter denna uppgift ska ni veta varför/hur Swing är enkeltrådat, samt hur man gör avbrottsstyrda funktioner. Dvs t.ex. hur man skapar gränssnitt som inte hänger sig vid tunga operationer. Deadline / kl. IT Informationsteknologi # Uppgift Utritning av grafik i Swing är "enkeltrådat", vilket har vissa konsekvenser. Absolut viktigast i denna uppgift är att swingtråden inte "hänger sig" när jobbiga operationer utförs. Man måste också se till att Swinganrop alltid görs från Swings event-tråd. Uppgift Ni ska bygga ut er applikation med möjligheten att välja att lägga till hela kataloger och alla dess underkataloger till playlisten. Katalogerna ska sökas igenom och samtliga MP-filer som hittas ska efterhand läggas till i playlisten. Denna operation kan ta lång tid och för att hela gränssnittet då inte ska "hänga" sig är det viktigt att man sköter trådningen på rätt sätt. Informationsteknologi # Informationsteknologi # Uppgift Det ska finnas nån form av progressbar för genomsökningen som ger en uppfattning av vad som sker och hur mycket det är kvar att göra. Genomsökningen ska kunna ska även kunna pausas, återupptas och avbrytas. Det ska fortfarande gå att använda spelaren som vanligt under tiden som en genomsökning pågår. Uppgift Man ska kunna ladda och spara en playlist. Det räcker med att den playlist man senast hade laddas när man öppnar programmet, men det är fritt fram att göra mer sofistikerad playlisthantering. Man ska kunna markera flera låtar i en spellista och på något sätt kunna välja att ta bort samtliga markerade (tex popup-meny och/eller snabbtangent) Man ska kunna klicka på en låt och på något sätt välja att hoppa dit i spellistan. Informationsteknologi # Informationsteknologi #
Uppgift Spelaren ska vara språkoberoende, enligt samma princip som Uppgift och. Spelaren ska även fortsättningsvis använda themes för all färg- och fonthantering, enligt samma princip som Uppgift och. Ni ska även fortsättningsvis använda er av Actions där det är vettigt. Skapa en ant-regel player som startar klassen player.ui.player (som är den klass som ska köras). (Uppgift ) Extra för de som vill: lägg till möjligheten att välja slumpmässig uppspelning av spellistan och möjligheten att repetera den i all oändlighet. Extra för de som vill: gör det möjligt att släppa filer från filsystemet på spellistan (drag-anddrop). Informationsteknologi #7 Informationsteknologi # (Uppgift ) Om man vill: Eftersom det är sista uppgiften så är det självklart positivt för helhetsintrycket att visa vad man lärt sig under kursens gång. Det är med andra ord helt okej att göra en förbättrad tabellmodell, snyggare actions, bättre hantering av resize etc etc, om man tycker sig ha kommit på bättre lösningar under kursens gång. En stor del av programvarutvecklingen handlar om att lära sig av sina tidigare erfarenheter. Trådar Definition: A thread is a single sequential flow of control within a program. Informationsteknologi #9 Informationsteknologi # Swing är enkeltrådat Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread. Undantag: repaint(), revalidate(), invalidate() Samt metoder som enligt javadoc är thread safe Kör vi på event-tråden nu? Om osäker, enkel koll genom: if (EventQueue.isDispatchThread()) { Insikt: public void actionperformed(actionevent e) // klart att vi är event-tråd här! Informationsteknologi # Informationsteknologi #
Varför enkeltrådat? Komplicerat göra ett toolkit tråd-säkert Få utvecklare kan hantera UI med flera trådar Händelser kommer i garanterad ordning (slipper icke-determinism) Snabbare UI (slipper synkronisering) Lösningar: SwingUtilities.invokeLater SwingUtilities.invokeAndWait SwingWorker Thread Timer SwingUtilities.invokeLater Mekanism som används för att lägga en referens till ett kodblock på event-kön. När event-tråden kommer till kodblocket så körs den. GUI t kan på det viset uppdateras av kodblocket eftersom det körs på event-tråden. invokelater() metoden returnerar direkt utan att invänta att event-dispatch tråden exekverar koden. Runnable dowork = new Runnable() { public void run() { drawsome(); ; SwingUtilities.invokeLater(doWork); Informationsteknologi # Informationsteknologi # SwingUtilities.invokeAndWait invokeandwait() metoden fungerar som invokelater(), utom att invokeandwait() inte returnerar innan event-dispatching tråden har exekverat kodblocket. void showhellotheredialog() throws Exception { Runnable showmodaldialog = new Runnable() { public void run() { JOptionPane.showMessageDialog(frame, "Hi"); ; SwingUtilities.invokeAndWait(showModalDialog); SwingWorker SwingWorker ingår inte i Java-distributionen utan är en egen klass/fil Finns på uppgift -sidan att ladda hem om man vill final SwingWorker worker = new SwingWorker() { public Object construct() { // do long operation here // NOTE: runs on a background thread public void finished() { // called when construct is done // NOTE: runs on the event dispatching thread ; worker.start(); Informationsteknologi # Informationsteknologi # SwingWorker construct() metoden används till att utföra något som kan vara tidsödande. Exempelvis: Blockera i väntan på disk I/O eller nätverk Utföra omfattande beräkningar Exekvera kod som kan resultera i att många klasser laddas. Vänta på nån annan resurs Timer Om ens program måste utföra en viss sak om och om igen med nåt intervall kan det vara bra att överväga java.util.timer eller javax.swing.timer klassen. Timer klassen är också bra om man vill ha något gjort efter en viss delay. Dvs Task-Scheduling. Informationsteknologi #7 Informationsteknologi #
x Timer java.util.timer javax.swing.timer The important difference between using the Swing Timer class and creating your own Thread is that the Swing Timer class uses just one thread for all timers. The other important feature of this timer class is that the actionperformed method runs on the event-dispatching thread. As a result, you don't have to bother with an explicit invokelater call. Trådar och CPU Ej bra att slösa bort processorkraft i onödan Trådar bör ge tillbaka tid till OS:et // fel, tar massor med resurser while (b) { checkfordata(); // bättre while (b) { checkfordata(); Thread.sleep(); try/catch runt sleep behövs Informationsteknologi #9 Informationsteknologi # Uppgift till torsdagen den / Var beredd att kunna beskriva hur invokelater() resp invokeandwait() fungerar och förhåller sig till varandra. Var beredd att kunna förklara hur Java:s keyword synchronized fungerar och hur man kan dra nytta av det. Titta på klasserna java.util.timer och java.util.timertask och fundera över vilken nytta man kan dra av dessa i gränssnittssammanhang. Uppgift till torsdagen den / Kommentera gränssnittet (uppgift ) från annan grupp. Projektor och jar-filer kommer att finnas under gruppträffen. Vid det här laget har ni kanske börjat laborera med att göra saker i separata trådar; vad får det för konsekvenser att Swing är enkeltrådat? Informationsteknologi # Informationsteknologi # Antal svar:, frånvarande:. Vad tycker du om föreläsningarna? [=mycket dåliga, =mycket bra] (.) Series. Vad tycker du om gruppträffarna? [=mycket dåliga, =mycket bra] (.7) Series Informationsteknologi # Informationsteknologi #
. Vad tycker du om kursmaterialet (TiJ + länkar + webben) [=mycket dåligt, =mycket bra] (.). Hur bedömer du din arbetsinsats? [=mycket liten, =mycket stor] (.) 7 Series Series Informationsteknologi # Informationsteknologi #. Har du tillräckliga förkunskaper? [=inte alls, =mer än nog] (.). Vad tycker du om kursens svårighetsgrad? [=mycket lätt, =mycket svår] (.) Series Series Informationsteknologi #7 Informationsteknologi # Ni tycker att det är kul att arbeta praktiskt i grupper En del tycker att uppgifterna är svåra att dela upp på fyra personer Inget krav att man delar upp arbetet! Agile utvecklingsmetoder som tex. XP förespråkar att man ska arbeta i par (parprogrammering), detta kan vara effektivare än att jobba som fyra individer. Dagboken strular SunRay:arna har någon form av bugg som dyker upp med just dagboken. Buggar kring inmatning av dagboksposter, några av dessa är nu fixade. Ny dagboks-jar kommer finnas tillgänglig. Föreläsningar En del vill ha längre föreläsningar/mer innehåll. Kursen bygger dock mer på att man ska lära sig genom att göra än att höra. Detta passar inte alla, men på denna kurs frångår vi den vedertagna standarden med föreläsningar/labbar/tenta, därför att vi tror att man bättre lär sig den arbetsmetodik som man måste ha vid gränssnittsutveckling genom praktiskt arbete och egen informationshämtning. Se inte timmarna då ni försöker få något att fungera som bortslösad tid. Det är så man lär sig! Var dock inte allt för envisa, ibland kan det vara betydligt mer produktivt att fråga - det är lätt att bli kodblind! Java. tips Med Java. kom Generics som gör att man bla kan använda sig av typade containers. Detta gör att man slipper den jobbiga konstruktionen med downcasting. Gamla sättet (<.) att göra en typisk iterering över en Collection på: // Otypad lista List songs = new ArrayList(); // Iterera genom listan Iterator it = songs.iterator(); while (it.hasnext()) { // Här måste vi typkonvertera eftersom it.next() // returnerar Object Song s = (Song) it.next(); s.sing(); Informationsteknologi #9 Informationsteknologi #
Java. - ny for-loop Med. kan man istället göra så här: // Lista som enbart kan innehålla objekt av typen Song List<Song> songs = new ArrayList<Song>(); // Iterera genom listan med den nya for-loopen: for (Song s : songs) { // För alla Song s i songs s.sing(); Det blir inte bara mindre att skriva, utan man får också compile-time typcheck istället för run-time. Man kan använda den nya for-loop:en även för arrayer. Java. Mer om generics Om man är intresserad av att lära sig mer om generics så rekomenderas länken på hemsidan som behandlar nyheterna i Java.. Vill man skriva egna klasser som använder generics är det ett tips att titta på implementationen av klasserna i java.util. Informationsteknologi # Informationsteknologi # Exempel på filsökningsfunktion private int addfiles(file[] files, double progress, double totalprogress, int pos) { double partprogress = totalprogress / (double) files.length; for (File f : files) { if (f.isdirectory()) { // Add directory content recursively pos = addfiles(f.listfiles(), progress, partprogress, pos); else if (f.isfile()) { // Add the file to the playlist if it is an mp file String filename = f.getname().tolowercase(); int i = filename.lastindexof(".mp"); if (i >= ) { Song s = Song.createSong(f); if (s!= null) { if (pos >= ) { playlistmodel.addsong(pos, s); pos++; else playlistmodel.addsong(s); progress += partprogress; log.debug("p: " + progress); return pos; // Exempel som lägger till filerna först i spellistan: addfiles(filechooser.getselectedfiles(),.,., ); Olika approacher för fil-letandet Föregående funktion lägger till låtar samtidigt som den scannar igenom. Man kan då inte på förhand veta exakt vad varje steg i progressbaren ska motsvara, utan man får istället göra gissningar. Detta gör att progressbaren kommer stega fram olika fort beroende på antalet filer i en katalog. Alternativet är att man gör det som en tvåstegsoperation där man först scannar genom alla kataloger (då kan progress-baren vara indeterminate) för att sen (när man vet hur många filer man har) visa helt korrekt progress. Båda varianterna har sina för- och nackdelar. Använd vilken ni vill. Informationsteknologi # Informationsteknologi # Drag and drop Frivilligt på uppgiften Lite klurigt Men man kan med enkla medel få relativt schysst beteende. Exempel: Vi vill kunna släppa filer från vår filhanterare på vår playlist. Detta är egentligen bara en drop-operation, vilket gör det lite enklare för oss. Exempel: Släppa filer på playlist Först vill vi skapa en DropTargetListener: DropTargetListener tabledtl = new DropTargetAdapter() { public void drop(droptargetdropevent e) { try { Transferable tr = e.gettransferable(); if (tr.isdataflavorsupported(dataflavor.javafilelistflavor)) { e.acceptdrop(dndconstants.action_copy_or_move); Point point = e.getlocation(); java.util.list<file> filelist = (java.util.list) tr.gettransferdata(dataflavor.javafilelistflavor); if (playlisttable!= null) { int row = playlisttable.rowatpoint(point); addfiles(filelist, row); else addfiles(filelist, -); else { log.debug("rejecting: " + e.getcurrentdataflavorsaslist()); e.rejectdrop(); catch (Exception ex) { e.rejectdrop(); ; Informationsteknologi # Informationsteknologi #
Skapa DropTarget Därefter skapar vi en DropTarget och sätter den på tabellen. DropTarget tabledroptarget = new DropTarget(playlistTable, tabledtl); playlisttable.setdroptarget(tabledroptarget); Detta är allt som behövs för att det ska fungera att släppa på tabellen. Det finns dock ett problem: innan tabellen har några rader så träffar man istället den omgivande JScrollPane:en med sina drops Lösningen är att skapa en nästan likadan DropTarget och sätta denna på själva JScrollPane:n: Tips: Sätta kolumnbredder Självklart vill man att sin playlist har rätt bredd på respektive kolumn. Problemet är att rätt bredd kan ändras under körning. Hur ska vi få reda på när bredden måste sättas om? DropTarget scrolldroptarget = new DropTarget(scrollPane, scrolldtl); scrollpane.setdroptarget(scrolldroptarget); Informationsteknologi #7 Informationsteknologi # Tips: Sätta kolumnbredder Vi kan registrera en lyssnare på modellen och se till att göra något smart när modellen ändras: playlistmodel.addtablemodellistener(new TableModelListener() { public void tablechanged(tablemodelevent e) { if (playlistmodel!= null && playlisttable!= null) { int rows = playlistmodel.getrowcount(); FontMetrics fm = playlisttable.getfontmetrics(playlisttable.getfont()); int w = fm.stringwidth(integer.tostring(rows) + ""); TableColumn col = playlisttable.getcolumn(lang.get("player.playlist.index")); if (col!= null) { col.setminwidth(w); col.setmaxwidth(w + ); ); Tips: Sätta kolumnbredd Självklart bör man kolla vilket sorts event som kommer och enbart ändra kolumnbredden om eventet är av en sån typ att bredden kan ha ändrats. Informationsteknologi #9 Informationsteknologi # 7