It's now time to write some code. I'll do what I usually do when I have to develop an application with a GUI: I design the UI before anything else.
So, firstly, let's list the functions the UI has to provide:
Now that we know what we want to do, let's implement it! After some additional reading and tests, I end up with following architecture and code:
Contents of each source file is below:
UserInterface.xml
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.paint.*?> <?import javafx.scene.text.*?> <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.monblocnotes.devicecontroller.UserInterfaceController"> <children> <GridPane> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> </columnConstraints> <rowConstraints> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> </rowConstraints> <children> <Label text="Enter serial port device:" /> <TextField fx:id="serialPortTF" GridPane.columnIndex="1" /> <Button fx:id="sendReadCommandBtn" mnemonicParsing="false" text="Send READ command" GridPane.rowIndex="1" /> </children> </GridPane> <ListView fx:id="recFramesLV" prefHeight="319.0" prefWidth="600.0" /> </children> </VBox>
UserInterfaceController.java
package com.monblocnotes.devicecontroller; import java.net.URL; import java.util.ResourceBundle; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.control.TextField; public class UserInterfaceController implements Initializable { @FXML private TextField serialPortTF; @FXML private Button sendReadCommandBtn; @FXML private ListView<String> recFramesLV; private ObservableList<String> lines; private RecFrames recFrames; private int num; /** * */ @Override public void initialize(URL location, ResourceBundle resources) { sendReadCommandBtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { addFrame(); } }); lines = FXCollections.observableArrayList(); recFramesLV.setItems(lines); recFrames = new RecFrames(lines); num = 0; } /** * */ public void addFrame() { num++; String str = "frame " + num; recFrames.addFrame(str); } }
RecFrames.java
package com.monblocnotes.devicecontroller; import javafx.collections.ObservableList; public class RecFrames { // Maximum number of displayed frames. private final static int MAX_NB_FRAMES = 3; private ObservableList<String> frameList; /** * * @param frameList */ public RecFrames(ObservableList<String> frameList) { this.frameList = frameList; } /** * * @param frame */ public void addFrame(String frame) { int s = frameList.size(); if (s >= MAX_NB_FRAMES) { // Remove oldest element. frameList.remove(s - 1); } // Add new element. frameList.add(0, frame); } }
Main.java
package com.monblocnotes.devicecontroller; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.stage.Stage; import javafx.scene.Parent; import javafx.scene.Scene; public class Main extends Application { /** * */ @Override public void start(Stage primaryStage) { try { Parent root = FXMLLoader.load(getClass().getResource("UserInterface.fxml")); Scene scene = new Scene(root,400,400); scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); primaryStage.setScene(scene); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } /** * * @param args */ public static void main(String[] args) { launch(args); } }
What happens when you run this program? The window below is displayed:
Quite ugly, isn't it? But it does what I want with this first version, i.e. intercepting clicks on button, and displaying most recent strings in list view. More precisely, every time you click on the Send READ command button, a new string is generated and displayed. Most recent string is displayed at top, and only latest three strings are displayed:
Why this name for the button? Well, you'll discover later.