TDDE10 Objektorienterad programmering i Java
JavaFX - Referens för projekt och Lab4
Installera JavaFX på egen dator
Linux
Ladda hem zip-filen.
- Skapa en lämplig mapp, exempelvis Libs på lämplig
plats. Vårt förslag är något i stil
med:
/home/dinanvändare/Libs
. Du kan göra detta genom att i terminalen köra:mkdir ~/Libs
- Flytta zip-filen du nyss laddade hem till denna
mapp:
mv ~/Downloads/openjfx-21.0.2*.zip ~/Libs
Beroende på din installation kan du behöva ersätta Downloads med Hämtningar. - Gå till mappen och extrahera filerna:
cd ~/Libs && unzip openjfx-21.0.2*.zip
Detta bör skapa en mapp som heter javafx-sdk-21.0.2, och installationen är klar. Du kan nu ta bort zip-filen.
MacOS
Ladda hem zip-filen för x64 (mest sannolikt) eller aarch64 beroende på vilken arkitektur du har. Du kan avgöra arkitektur genom att öppna en terminal och köra:
uname -m
Om du får svar med något arm eller aarch väljer du aarch64, annars x64 ovan.
- Skapa en lämplig mapp, exempelvis Libs på lämplig
plats. Vårt förslag är något i stil
med:
/Users/dinanvändare/Libs
. Du kan göra detta genom att i terminalen köra:mkdir ~/Libs
- Flytta zip-filen du nyss laddade hem till denna
mapp:
mv ~/Downloads/openjfx-21.0.2*.zip ~/Libs
Beroende på din installation kan du behöva ersätta Downloads med Hämtningar. - Gå till mappen och extrahera filerna:
cd ~/Libs && unzip openjfx-21.0.2*.zip
Detta bör skapa en mapp som heter javafx-sdk-21.0.2, och installationen är klar. Du kan nu ta bort zip-filen.
Windows
Ladda hem zip-filen.
- Skapa en lämplig mapp, exempelvis Libs på lämplig
plats. Vårt förslag är något i stil
med:
C:\användare\dinUser\Libs
. Du kan göra detta genom att i gå in i filhanteraren, navigera fram till Den här datorn -> C:\ -> användare (eller users) -> din användare, högerklicka och skapa mapp: Libs - Flytta zip-filen du nyss laddade hem till denna mapp
(klipp ut eller kopiera och klistra in).
- Gå till mappen och extrahera filerna:
Dubbeklicka på filen, och klicka på "Extrahera alla".
Detta bör skapa en mapp som heter javafx-sdk-21.0.2, och installationen är klar. Du kan nu ta bort zip-filen.
Förbered ditt JavaFX-projekt
ThinLinc eller SU-sal
-
I Eclipse: högerklicka ditt projekt (exempelvis TDDE10-Lab4)
och välj "Properties". Du får upp ett fönster med menyer och
val. I menyn till vänster väljer du "Java Build Path". Du
får nu upp ett delfönster med flikar. Välj fliken
"Libraries". Klicka på "Modulepath", och sedan på knappen
"Add External JARs...". Detta borde ge en
filsystemsdialog. Navigera till mappen:
/courses/TDDE10/Libs/javafx-sdk-19
Markera (shift eller ctrl-klicka) samtliga filer som slutar på .jar och klicka på "Open". Klicka på "Apply and Close". Du har nu lagt till så att Eclipse kan hitta JavaFX för detta projekt.
Om du inte kan se den angivna mappen i ditt Eclipsefönster, öppna en terminal och skriv:
cd /courses/TDDE10/
Kursmapparna laddas dynamiskt så ibland kan det se ut som att de inte finns. Laddar du den i terminal bör den synas, både för dig och andra, tills den anses vara inaktiv igen. - Vi måste nu berätta för JVM var den ska hitta JavaFX. Vi
måste alltså skapa en "Run Configuration" för ditt
program. Klicka på "Run"-menyn högst upp i Eclipse, och välj
"Run Configurations". Du får upp ett fönster med eventuella
gamla konfigurationer, samt lite templates och annat smått
och gott. Högst upp till vänster har du en knapp: "New
launch configuration". Klicka på den. Du bör få upp ett
fönster som ser ut ungefär så här:
Under project klickar du på "Browse" och väljer ditt projekt. Döp konfigurationen till något lämpligt, ex. Lab4Main. Under Main klickar du också på "Browse" och väljer din main-klass. Klicka på "Arguments". Under VM-arguments, kopiera och klistra in följande två rader:
--module-path /courses/TDDE10/Libs/javafx-sdk-19/lib
--add-modules=javafx.controls
Efteråt bör det se ut ungefär så här:
(namnen kan skilja beroende på vad du kallar ditt projekt och din "main-fil", samt version av javafx).
Linux
-
I Eclipse: högerklicka på ditt projekt, exempelvis
TDDE10-lab3, och välj "Properties". Du får upp ett fönster
med menyer och val. I menyn till vänster väljer du "Java
Build Path". Du får nu upp ett delfönster med flikar. Välj
fliken "Libraries". Klicka på "Modulepath", och sedan på
knappen "Add External JARs...". Detta borde ge en
filsystemsdialog. Navigera till där du installerade JavaFX
(ex:
/home/dinanvändare/Libs/javafx-sdk-21.0.2
. Markera (shift eller ctrl-klicka) samtliga filer som slutar på .jar och klicka på "Open". Klicka på "Apply and Close". Du har nu lagt till så att Eclipse kan hitta JavaFX för detta projekt. -
Vi måste nu berätta för JVM var den ska hitta JavaFX. Vi
måste alltså skapa en "Run Configuration" för ditt
program. Klicka på "Run"-menyn högst upp i Eclipse, och välj
"Run Configurations". Du får upp ett fönster med eventuella
gamla konfigurationer, samt lite templates och annat smått
och gott. Högst upp till vänster har du en knapp: "New
launch configuration". Klicka på den. Du bör få upp ett
fönster som ser ut ungefär så
här:
Under project klickar du på "Browse" och väljer ditt projekt. Döp konfigurationen till något lämpligt, ex. Lab4Main. Under Main klickar du också på "Browse" och väljer din main-klass. . Klicka på "Arguments". Under VM-arguments, kopiera och klistra in följande två rader, men ersätt dinanvändare med ditt användarnamn, eller ersätt sökvägen med den du valde om du inte följde förslagen vid installation:
--module-path /home/dinanvändare/Libs/javafx-sdk-21.0.2/lib
--add-modules=javafx.controls
Efteråt bör det se ut ungefär så här:
(namnen kan skilja beroende på vad du kallar ditt projekt och din "main-fil", samt version av javafx).Eventuellt behöver du även, på denna sida, avmarkera: Use the -XstartOnFirstThread argument when launching with SWT. Låt detta vara från start, men skulle det inte fungera när du försöker köra (inget händer) avmarkerar du denna checkbox.
MacOS
/courses/TDDE10/Libs/javafx-sdk-21.0.2
Markera (shift eller ctrl-klicka) samtliga filer som slutar på .jar och klicka på "Open". Klicka på "Apply and Close". Du har nu lagt till så att Eclipse kan hitta JavaFX för detta projekt.
Under project klickar du på "Browse" och väljer ditt projekt. Döp konfigurationen till något lämpligt, ex. Lab4Main. Under Main klickar du också på "Browse" och väljer din main-klass. Klicka på "Arguments". Under VM-arguments, kopiera och klistra in följande två rader men ersätt dinanvändare med ditt användarnamn, eller ersätt sökvägen med den du valde om du inte följde förslagen vid installation:
--module-path /Users/dinanvändare/Libs/javafx-sdk-21.0.2/lib
--add-modules=javafx.controls
Efteråt bör det se ut ungefär så här:
(namnen kan skilja beroende på vad du kallar ditt projekt och din "main-fil", samt version av javafx).
Eventuellt behöver du även, på denna sida, avmarkera: Use the -XstartOnFirstThread argument when launching with SWT. Låt detta vara från start, men skulle det inte fungera när du försöker köra (inget händer) avmarkerar du denna checkbox.
Fel: Graphics Device initialization failed for : es2, sw
- Öppna inställningarna för din dator och gå till "Security & Privacy" (förmodligen Säkerhet & Sekretess eller liknande på svenska). Gå till "General"-tabben (Allmänt, troligtvis, på svenska).
- Öppna din motsvarighet till utforskaren där du kan navigera dina filer. Gå till mappen där du har installerat javafx, och en i taget försöker du köra (dubbelklicka) alla .jar- och .dylib-filer i lib-mappen. När du klickar på dem väljer du öppna. Vid körning kommer .jar-filen att säga att den inte hittar en runtime, det är helt ok, medan .dylib öppnar en terminal som du kan stänga direkt igen. När du kört en fil kommer det sannolikt (inte garanterat) läggas till en dialog att du kan ge rättigheter åt filen i "säkerhetsfönstret" du öppnade i föregående punkt. Ge filerna de rättigheter som behövs. Repetera för samtliga av dessa filer (bara dessa två filtyper behöver rättigheter satta). Testa sedan att köra projektet igen.
Windows
/courses/TDDE10/Libs/javafx-sdk-21.0.2
Markera (shift eller ctrl-klicka) samtliga filer som slutar på .jar och klicka på "Open". Klicka på "Apply and Close". Du har nu lagt till så att Eclipse kan hitta JavaFX för detta projekt.
Under project klickar du på "Browse" och väljer ditt projekt. Döp konfigurationen till något lämpligt, ex. Lab4Main. Under Main klickar du också på "Browse" och väljer din main-klass. Klicka på "Arguments". Under VM-arguments, kopiera och klistra in följande två rader men ersätt dinanvändare med ditt användarnamn, eller ersätt sökvägen med den du valde om du inte följde förslagen vid installation (beroende på din installation kan du behöva ersätta "Användare" med "Users" också, kolla vad mappen heter på just din maskin).:
--module-path
"C:\Användare\dinanvändare\Libs\javafx-sdk-21.0.2\lib"
--add-modules=javafx.controls
Efteråt bör det se ut ungefär så här:
(namnen kan skilja beroende på vad du kallar ditt projekt och din "main-fil", samt version av javafx).
Eventuellt behöver du även, på denna sida, avmarkera: Use the -XstartOnFirstThread argument when launching with SWT. Låt detta vara från start, men skulle det inte fungera när du försöker köra (inget händer) avmarkerar du denna checkbox.
Layout och fönster
Fönstret / Stage
I JavaFX är vår Stage själva fönstret. Den får vi gratis
från start-metoden:
Vi kan ändra storleken på fönstret och titeln, på följande vis inuti start-metoden:
public void start(Stage primaryStage) throws Exception {
// jag har valt att kalla min stage för primaryStage, du kan kalla den vad du vill
}
primaryStage.setTitle("My fancy JavaFX window!");
primaryStage.setWidth(1000); // Vi sätter bredden till 1000 pixlar
primaryStage.setHeight(600); // Vi sätter höjden till 600 pixlar
Skapa en layout / organisera innehåll (HBox/VBox)
Vi kan välja att skapa alla våra komponenter i start-metoden, detta blir dock snabbt kladdigt, rörigt, och svårt att felsöka. Därför rekommenderar vi att ni skapar egna klasser för de olika delar av fönstret. Vi kanske, exempelvis, vill ha en "rityta" som vi kan rita i (inte nödvändigtvis rita i tradidionell bemärkelse, det kan handla om bilder, "spelyta", vad vi nu vill kalla det. Mer om den i Rityta / Canvas nedan.
Utöver vår "rityta" vill vi förmodliga ha paneler. Om vi vill ha en vertikal panel (trava på höjden) skapar vi en klass som ärver från VBox, om vi vill ha en horisontell panel (stoppa in innehåll från vänster till höger) skapar vi en klass som ärver from HBox. I exemplet väljer vi att illustrera hur den kan fungera med en HBox, men de fungerar likadant frånsett hur de organiserar innehållet vi stoppar in.
Vi skapar en panelklass som är ärver från HBox:
public class HorizontalPanel extends XBox {
public HorizontalPanel() {
// Vi sätter en bakgrundsfärg, #d4d6d5 är hexkoden för en
// färg. Googla efter colorpicker och välj en färg ni gillar.
setStyle("-fx-background-color: #d4d6d5;");
setHeight(100); // Sätter höjden på panelen till 100 pixlar
setWidth(1000); // Sätter bredden till 1000 pixlar
}
}
När vi sedan lägger till saker i panelen är det ordningen vi
lägger till dem som avgör vilken ordning de visas. Använder vi
VBox kommer de att läggas till på höjden, använder vi HBox läggs
de till på bredden, men i övrigt fungerar det likadant:
public class HorizontalPanel extends XBox {
private Button rightButton, leftButton;
public HorizontalPanel() {
// Vi sätter en bakgrundsfärg, #d4d6d5 är hexkoden för en
// färg. Googla efter colorpicker och välj en färg ni gillar.
setStyle("-fx-background-color: #d4d6d5;");
setHeight(100); // Sätter höjden på panelen till 100 pixlar
setWidth(1000); // Sätter bredden till 1000 pixlar
// Vi initerar knapparna. Mer under Knappar / Buttons om hur de fungerar.
rightButton = new Button("Right");
leftButton = new Button("Left");
// Vi lägger till leftButton först då vi vill ha den vänster.
getChildren().add(leftButton);
getChildren().add(rightButton);
}
}
Om vi vill kan vi lägga till HBoxar i VBoxar och vice versa för att få innehållet precis som vi vill.
Visa upp layouten i fönstret (Scene)
För att visa upp innehåll i vårt fönster (Stage) behöver vi en scen (Scene). Vi sätter in vår layout i scenen, och stoppar in scenen i fönstret. Sedan säger vi till fönstret att rita ut sig.
Ponera att vi har gjort tre olika paneler (eventuellt som
ovan, någon kanske är ett Canvas, etc. men approachen är
densamma) som vi vill stoppa in på höjden i vårt fönster. Vi
kan då nyttja en VBox som vi stoppar in våra paneler i, och
skapar sedan en scen åt VBoxen:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("My fancy JavaFX window!");
primaryStage.setWidth(1000); // Vi sätter bredden till 1000 pixlar
primaryStage.setHeight(600); // Vi sätter höjden till 600 pixlar
TopBar top = new TopBar();
MiddleStuff middle = new MiddleStuff();
BottomBar bot = new BottomBar();
HBox mainLayout = new HBox();
mainLayout.getChildren().add(top); // top först, vi vill ha den högst upp
mainLayout.getChildren().add(middle); // sedan middle
mainLayout.getChildren().add(bot); // sist botten
Scene theScene = new Scene(mainLayout); // Vi skapar en scen åt vår layout
primaryStage.setScene(theScene); // Vi sätter scenen i fönstret
primaryStage.show(); // Vi säger till fönstret att rita ut sig.
}
}
De viktigaste komponenterna (Canvas, Button, ...)
Ritytan, eller canvaset
Vi vill ibland ha ytor där vi kan rita ut egna bilder, eller
rita med hjälp av de inbyggda verktygen. Till vår hjälp har vi
klassen Canvas. Den kommer med stöd för att rita olika
geometriska figurer, text, bilder, etc. Den är inte en
behållare, som VBox och HBox, utan har egen
funktionalitet. Sannolikt vill vi göra en egen Canvas-klass så
att vi smidigat kan kapsla in den funktionalitet vi vill ha i
vårt eget Canvas.
public class MyCanvas extends Canvas {
public MyCanvas() {
// Precis som andra "paneler" kan vi sätta bredd och höjd på vårt canvas
setHeight(400);
setWidth(1000);
// Vi kan även sätta bakgrundsfärg om vi vill
setStyle("-fx-background-color: #00f241;");
// Vi kan säga vad som ska hända när vi klickar i vårt canvas.
setOnMouseClicked(event -> {
System.out.println("Ojojoj, vi klicka i Canvas. Tvärtufft!");
});
}
}
Vår "pensel", GraphicsContext2D
Var som helst i vår Canvas kan vi plocka fram vår "pensel"
och arbeta med den, eller skicka den till andra klasser och
låta dem rita ut sig i vårt Canvas genom att använder vårt
GraphicsContext2D-objekt. Vi kan även byta färg på "penseln".
GraphicsContext context = getGraphicsContext2D();
// Vi sätter "fill"-färgen till djup rosa.
context.setFill(Color.DEEPPINK);
// Vi ritar ut en 100 gånger 100 pixlar stor kvadrat som startar
// i övre vänstra hörnet (koordinat 0,0).
context.fillRect(0, 0, 100, 100);
// Det finns mängder av utritningsmetoder. Testa att, i Eclipse,
// köra context.fill och titta på listan av metoder.
// Vi kan även rita ut former utan att fylla dem med en färg:
g.setStroke(Color.GREEN); // Vi kan sätta färg på "pennan", alltså strecken som ritas
g.setLineWidth(5); // Vi sätter tjockleken på "pennan"
g.strokeRect(0, 0, getWidth(), getHeight()); // och ritar ut en kvadrat
// Vi kan även rita ut bilder med vårt GraphicsContext2D:
String imagePath = "/home/username/bildnamn.png"; // format på filnamn / path i Linux,
// i macOS ersätt home med Users.
// String imagePath = "C:\\Användare\\username\\bildnamn.png"; // format för Windows.
// Ersätt med platsen där din bild finns, samt namnet på bilden.
Image image = new Image((new FileInputStream(imagePath)); // Ladda in bilden.
// ritar ut bilden med start i koordinat 10,10 med bredd och höjd 200.
getGraphicsContext2D().drawImage(image, 10, 10, 200, 200);
// ritar ut bilden på koordinat 250,250 med sin egen bredd och höjd
getGraphicsContext2D().drawImage(image, 250, 250, image.getWidth(), image.getHeight());
// Vi har en "bil-klass" som själv vet hur den ritar ut sig, men behöver låna vårt
// GraphicsContext2D-objekt för att kunna rita ut sig i vårt Canvas:
Car myCar = new Car();
// Vi skickar vårt context-objekt till bilens drawYourself-metod och den kan
// då jobba med contextobjektet precis som vi gjort ovan.
myCar.drawYourself(context);
// Sist men inte minst kanske vi vill sudda fönstret, eller delar av det.
// Vi rensar från koordinat 0,0 lika brett och högt som vår canvas.
context.clearRect(0, 0, getWidth(), getHeight());
Den inbyggda knappklassen (Button)
Det kan i många fall vara användbart att snabbt kunna skapa
knappar efter en färdig mall. Speciellt om vi bara vill ha en
generisk knapp, utan speciellt utseende:
Button clear = new Button("MinKnapp"); // Vi skapar en knapp med texten MinKnapp
clear.setOnAction(value -> { // Vi säger till knappen vilken funktionalitet den ska ha
// Vi kan göra vad som helst här, behöver inte vara utskrifter.
System.out.println("Vi tryckte på knappen! Det går bra nu!");
});
Sidansvarig: Magnus Nielsen
Senast uppdaterad: 2024-02-02