{"id":"gui-events-launch-parameters","slug":"launch-parameters","title":"Launch parameters","text":"A program started from a terminal can be given **command-line arguments**: words after the class's name, as in `java Main --name=Noor --candles=30`. They arrive in `main`'s parameter, `String[] args`, which every `main` has had since module 1. Here `args` would hold two Strings, `--name=Noor` and `--candles=30`. Programs use them for settings that change from one run to the next: a name, a size, a file to open.\n\n### From main to start\n\nA JavaFX program hands its arguments on to the application: `launch(Main.class, args)`. After the class, `launch` takes any number of Strings (its parameter is written `String... args`): an array of them, as here, Strings written one after another, as in `launch(Main.class, \"--name=Noor\", \"--candles=30\")`, or none at all, as in `launch(Main.class)`.\n\nIn `start`, `getParameters()`, a method that Main inherits from Application, returns them as a `Parameters` object with three methods:\n\n| Method | Returns |\n| --- | --- |\n| `getRaw()` | every argument, in order, as a `List<String>` |\n| `getNamed()` | the arguments written `--key=value`, as a `Map<String, String>` from each key to its value |\n| `getUnnamed()` | the other arguments, in order, as a `List<String>` |\n\nAn argument is named when it starts with two dashes, then a key that begins with a letter (or `_`), then `=`: `--name=Noor` is the key `name` with the value `Noor`. `-name=Noor` (one dash), `--quiet` (no `=`) and `--3d=yes` (the key starts with a digit) are unnamed. A key given twice keeps its last value.\n\nA party has a banner that shows whose birthday it is. To try it without a terminal, this `main` gives `launch` the arguments itself:\n\n```java\nimport java.util.Map;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\nimport javafx.scene.text.Font;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Map<String, String> named = getParameters().getNamed();\n        Label banner = new Label(\"Happy birthday, \" + named.get(\"name\") + \"!\");\n        banner.setFont(Font.font(\"Serif\", 28));\n        Label cake = new Label(\"Candles: \" + named.get(\"candles\"));\n        System.out.println(getParameters().getRaw());\n        System.out.println(getParameters().getUnnamed());\n\n        stage.setScene(new Scene(new VBox(banner, cake)));\n        stage.setTitle(\"Party\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, \"--name=Noor\", \"--candles=30\", \"balloons\");\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Party\",\"scene\":{\"root\":{\"n\":1,\"type\":\"VBox\",\"children\":[{\"n\":2,\"type\":\"Label\",\"text\":\"Happy birthday, Noor!\",\"font\":{\"family\":\"Serif\",\"size\":28}},{\"n\":3,\"type\":\"Label\",\"text\":\"Candles: 30\"}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Party\\\"\\n  VBox\\n    Label \\\"Happy birthday, Noor!\\\", font Serif 28\\n    Label \\\"Candles: 30\\\"\"}\n```\n\n```output\n[--name=Noor, --candles=30, balloons]\n[balloons]\n```\n\n`getNamed()` is a Map, so `get(\"name\")` finds the value by its key (module 31). The values are Strings, even `30`: for a number to calculate with, convert it, as with input, `Integer.valueOf(named.get(\"candles\"))`.\n\n### A default for a missing argument\n\n`get` returns `null` for a key that isn't there. Started without arguments, the banner would say `Happy birthday, null!`. `getOrDefault` (module 31) gives a value of your own instead. This version passes on `main`'s own arguments, as a real program does, and on this page it runs without any:\n\n```java\nimport java.util.Map;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\nimport javafx.scene.text.Font;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Map<String, String> named = getParameters().getNamed();\n        Label banner = new Label(\"Happy birthday, \" + named.getOrDefault(\"name\", \"friend\") + \"!\");\n        banner.setFont(Font.font(\"Serif\", 28));\n        Label cake = new Label(\"Candles: \" + named.getOrDefault(\"candles\", \"plenty\"));\n\n        stage.setScene(new Scene(new VBox(banner, cake)));\n        stage.setTitle(\"Party\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, args);\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Party\",\"scene\":{\"root\":{\"n\":1,\"type\":\"VBox\",\"children\":[{\"n\":2,\"type\":\"Label\",\"text\":\"Happy birthday, friend!\",\"font\":{\"family\":\"Serif\",\"size\":28}},{\"n\":3,\"type\":\"Label\",\"text\":\"Candles: plenty\"}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Party\\\"\\n  VBox\\n    Label \\\"Happy birthday, friend!\\\", font Serif 28\\n    Label \\\"Candles: plenty\\\"\"}\n```\n\n### The application in a class of its own\n\nThe class with `main` doesn't have to be the application. `Main` can stay a plain class whose `main` starts another class, one that extends Application. Here `main` also gives only one of the two arguments:\n\n```java\nimport javafx.application.Application;\n\npublic class Main {\n    public static void main(String[] args) {\n        Application.launch(PartyBanner.class, \"--name=Kai\");\n    }\n}\n// ==== PartyBanner.java ====\nimport java.util.Map;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\nimport javafx.scene.text.Font;\nimport javafx.stage.Stage;\n\npublic class PartyBanner extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Map<String, String> named = getParameters().getNamed();\n        Label banner = new Label(\"Happy birthday, \" + named.getOrDefault(\"name\", \"friend\") + \"!\");\n        banner.setFont(Font.font(\"Serif\", 28));\n        Label cake = new Label(\"Candles: \" + named.getOrDefault(\"candles\", \"plenty\"));\n\n        stage.setScene(new Scene(new VBox(banner, cake)));\n        stage.setTitle(\"Party\");\n        stage.show();\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Party\",\"scene\":{\"root\":{\"n\":1,\"type\":\"VBox\",\"children\":[{\"n\":2,\"type\":\"Label\",\"text\":\"Happy birthday, Kai!\",\"font\":{\"family\":\"Serif\",\"size\":28}},{\"n\":3,\"type\":\"Label\",\"text\":\"Candles: plenty\"}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Party\\\"\\n  VBox\\n    Label \\\"Happy birthday, Kai!\\\", font Serif 28\\n    Label \\\"Candles: plenty\\\"\"}\n```\n\n- `launch` is a static method of Application. Inside a class that extends Application it can be called by its name alone; anywhere else it's called with the class's name, `Application.launch(...)`, as `Math.max(...)` is.\n- JavaFX makes the PartyBanner object itself, so PartyBanner must be `public`, with a constructor that takes no parameters, as module 48 said of Main.\n\n### Arguments here and on your computer\n\n- On your own computer, the arguments go after the class's name in the command that starts the program, or in your editor's settings for running it.\n- In Java Arena, the checks of a challenge give the arguments, and the task card shows them under \"Command-line arguments\". \"Run with my input\" starts your program without arguments, so it shows what your program does when they're missing.\n","task":"A screen at an airport's gate shows a flight and its gate, given as launch parameters such as `--flight=AY123 --gate=12`. When there's no gate yet, the screen says `Gate: not yet known`. Fill in the three blanks. The task card shows the window for the arguments `--flight=AY123 --gate=12`.\n","kind":"fill","seed":"import java.util.Map;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Map<String, String> named = getParameters().[[getNamed]]();\n        Label flight = new Label(\"Flight \" + named.get(\"flight\"));\n        Label gate = new Label(\"Gate: \" + named.[[getOrDefault]](\"gate\", \"not yet known\"));\n\n        stage.setScene(new Scene(new VBox(flight, gate)));\n        stage.setTitle(\"Boarding\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, [[args]]);\n    }\n}\n","solution":"import java.util.Map;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Map<String, String> named = getParameters().getNamed();\n        Label flight = new Label(\"Flight \" + named.get(\"flight\"));\n        Label gate = new Label(\"Gate: \" + named.getOrDefault(\"gate\", \"not yet known\"));\n\n        stage.setScene(new Scene(new VBox(flight, gate)));\n        stage.setTitle(\"Boarding\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, args);\n    }\n}\n","hints":["The `--key=value` arguments come from `getParameters().getNamed()`, a Map. For a key that may be missing, a Map has `getOrDefault(key, fallback)`.","`main` hands its own arguments on to the application: `launch(Main.class, args)`."],"tests":[{"name":"Test 1","stdin":"","args":["--flight=AY123","--gate=12"],"expect":"","hidden":false,"events":[],"window":{"windows":[{"title":"Boarding","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Flight AY123"},{"n":3,"type":"Label","text":"Gate: 12"}]}}}],"problems":[]},"outline":"Window \"Boarding\"\n  VBox\n    Label \"Flight AY123\"\n    Label \"Gate: 12\""},{"name":"Test 2","stdin":"","args":["--gate=3","--flight=SK901"],"expect":"","hidden":true,"events":[],"window":{"windows":[{"title":"Boarding","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Flight SK901"},{"n":3,"type":"Label","text":"Gate: 3"}]}}}],"problems":[]},"outline":"Window \"Boarding\"\n  VBox\n    Label \"Flight SK901\"\n    Label \"Gate: 3\""},{"name":"Test 3","stdin":"","args":["--flight=LH77"],"expect":"","hidden":true,"events":[],"window":{"windows":[{"title":"Boarding","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Flight LH77"},{"n":3,"type":"Label","text":"Gate: not yet known"}]}}}],"problems":[]},"outline":"Window \"Boarding\"\n  VBox\n    Label \"Flight LH77\"\n    Label \"Gate: not yet known\""}],"require":[],"forbid":[],"more":[{"task":"A print shop's program is started with a few arguments, some of them not quite as the shop meant. What does it print?\n","kind":"predict","seed":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        System.out.println(getParameters().getNamed().get(\"copies\"));\n        System.out.println(getParameters().getNamed().size());\n        System.out.println(getParameters().getUnnamed());\n        System.out.println(getParameters().getRaw().size());\n\n        stage.setScene(new Scene(new Label(\"Printing\")));\n        stage.setTitle(\"Print shop\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, \"--copies=3\", \"poster.pdf\", \"--copies=5\", \"-color=red\", \"--draft\");\n    }\n}\n","solution":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        System.out.println(getParameters().getNamed().get(\"copies\"));\n        System.out.println(getParameters().getNamed().size());\n        System.out.println(getParameters().getUnnamed());\n        System.out.println(getParameters().getRaw().size());\n\n        stage.setScene(new Scene(new Label(\"Printing\")));\n        stage.setTitle(\"Print shop\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, \"--copies=3\", \"poster.pdf\", \"--copies=5\", \"-color=red\", \"--draft\");\n    }\n}\n","hints":["An argument is named when it starts with two dashes, then a key that begins with a letter (or `_`), then `=`. `-color=red` has one dash, and `--draft` has no `=`.","`copies` is given twice, and the last value wins, so the Map has one key. `getRaw()` keeps every argument."],"tests":[{"name":"Output","stdin":"","expect":"5\n1\n[poster.pdf, -color=red, --draft]\n5","hidden":false}],"require":[],"forbid":[],"lines":["5","1","[poster.pdf, -color=red, --draft]","5"]},{"task":"A tip calculator's percent is a launch parameter, `--percent=20`, and 15 when it isn't given. The window is built already: the label `Tip percent: 15`, a text field with the prompt text `Bill in euros`, the button `Tip`, and an empty label. Make it work:\n\n- Read the percent in `start`, and show it in the first label, like `Tip percent: 20`.\n- **Tip** reads the bill, a whole number of euros, and sets the last label to the tip, `bill * percent / 100.0`, like `Tip: 9.0 euros` for a bill of 45 at 20 percent.\n- `main` hands its arguments on to the application.\n\nThe task card shows the window for the arguments `--percent=20`, after typing 45 and clicking Tip.\n","kind":"code","seed":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Label rate = new Label(\"Tip percent: 15\");\n        TextField bill = new TextField();\n        bill.setPromptText(\"Bill in euros\");\n        Button tip = new Button(\"Tip\");\n        Label result = new Label(\"\");\n\n        stage.setScene(new Scene(new VBox(rate, bill, tip, result)));\n        stage.setTitle(\"Tip calculator\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        int percent = Integer.valueOf(getParameters().getNamed().getOrDefault(\"percent\", \"15\"));\n        Label rate = new Label(\"Tip percent: \" + percent);\n        TextField bill = new TextField();\n        bill.setPromptText(\"Bill in euros\");\n        Button tip = new Button(\"Tip\");\n        Label result = new Label(\"\");\n        tip.setOnAction(event -> {\n            int amount = Integer.valueOf(bill.getText());\n            result.setText(\"Tip: \" + amount * percent / 100.0 + \" euros\");\n        });\n\n        stage.setScene(new Scene(new VBox(rate, bill, tip, result)));\n        stage.setTitle(\"Tip calculator\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class, args);\n    }\n}\n","hints":["Read the percent from the named parameters at the top of `start`, with `getOrDefault` and \"15\" when it's missing, and make the first label's text from it.","The percent is `Integer.valueOf(getParameters().getNamed().getOrDefault(\"percent\", \"15\"))`. The handler can use `percent`: it's a local variable, but it never changes (step 2). Read the bill with `Integer.valueOf(bill.getText())`, and remember `launch(Main.class, args)` in `main`."],"tests":[{"name":"Test 1","stdin":"","args":["--percent=20"],"expect":"","hidden":false,"events":["type TextField 1 \"45\"","click Button \"Tip\""],"window":{"windows":[{"title":"Tip calculator","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Tip percent: 20"},{"n":3,"type":"TextField","text":"45","promptText":"Bill in euros"},{"n":4,"type":"Button","text":"Tip","onAction":true},{"n":5,"type":"Label","text":"Tip: 9.0 euros"}]}}}],"problems":[]},"outline":"Window \"Tip calculator\"\n  VBox\n    Label \"Tip percent: 20\"\n    TextField \"45\", prompt \"Bill in euros\"\n    Button \"Tip\"\n    Label \"Tip: 9.0 euros\""},{"name":"Test 2","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"40\"","click Button \"Tip\""],"window":{"windows":[{"title":"Tip calculator","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Tip percent: 15"},{"n":3,"type":"TextField","text":"40","promptText":"Bill in euros"},{"n":4,"type":"Button","text":"Tip","onAction":true},{"n":5,"type":"Label","text":"Tip: 6.0 euros"}]}}}],"problems":[]},"outline":"Window \"Tip calculator\"\n  VBox\n    Label \"Tip percent: 15\"\n    TextField \"40\", prompt \"Bill in euros\"\n    Button \"Tip\"\n    Label \"Tip: 6.0 euros\""},{"name":"Test 3","stdin":"","args":["--percent=12","--currency=EUR"],"expect":"","hidden":true,"events":["type TextField 1 \"50\"","click Button \"Tip\""],"window":{"windows":[{"title":"Tip calculator","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Tip percent: 12"},{"n":3,"type":"TextField","text":"50","promptText":"Bill in euros"},{"n":4,"type":"Button","text":"Tip","onAction":true},{"n":5,"type":"Label","text":"Tip: 6.0 euros"}]}}}],"problems":[]},"outline":"Window \"Tip calculator\"\n  VBox\n    Label \"Tip percent: 12\"\n    TextField \"50\", prompt \"Bill in euros\"\n    Button \"Tip\"\n    Label \"Tip: 6.0 euros\""},{"name":"Test 4","stdin":"","args":["--percent=10"],"expect":"","hidden":true,"events":["type TextField 1 \"37\"","click Button \"Tip\"","set TextField 1 \"120\"","click Button \"Tip\""],"window":{"windows":[{"title":"Tip calculator","scene":{"root":{"n":1,"type":"VBox","children":[{"n":2,"type":"Label","text":"Tip percent: 10"},{"n":3,"type":"TextField","text":"120","promptText":"Bill in euros"},{"n":4,"type":"Button","text":"Tip","onAction":true},{"n":5,"type":"Label","text":"Tip: 12.0 euros"}]}}}],"problems":[]},"outline":"Window \"Tip calculator\"\n  VBox\n    Label \"Tip percent: 10\"\n    TextField \"120\", prompt \"Bill in euros\"\n    Button \"Tip\"\n    Label \"Tip: 12.0 euros\""}],"require":[],"forbid":[]}]}