Notepad is a simple application. I am trying to demonstrate how easy creating the logic could be, by using Javafx2. The previous two blogs helped us in creating the layout and styling the notepad.
In this blog we will try to create the logic for our notepad to work. This would deal with adding functionalities that would be triggered for specific needs.
Lets start by adding the methods for File Menu.
This is simple. Open your notepad.fxml and update the File Menu code as under.
<items>
<MenuItem fx:id="newItem" text="New" onAction="#newFile"></MenuItem>
<MenuItem text="Open..." onAction="#openFile"></MenuItem>
<MenuItem text="Save" onAction="#saveFile"></MenuItem>
<MenuItem text="Save As..." onAction="#saveasFile"></MenuItem>
<SeparatorMenuItem></SeparatorMenuItem>
<MenuItem text="Page Setup..."></MenuItem>
<MenuItem text="Print"></MenuItem>
<SeparatorMenuItem></SeparatorMenuItem>
<MenuItem text="Exit" onAction="#exitApp"></MenuItem>
</items>
onAction defines the methods that would be called when you click on the respective Items.
These methods will be defined in the controller of the fxml. Defining a controller is simple. Add this to the place you defined BorderPane.
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="NotepadController">
@FXML
@FXML
In this blog we will try to create the logic for our notepad to work. This would deal with adding functionalities that would be triggered for specific needs.
Lets start by adding the methods for File Menu.
This is simple. Open your notepad.fxml and update the File Menu code as under.
<items>
<MenuItem fx:id="newItem" text="New" onAction="#newFile"></MenuItem>
<MenuItem text="Open..." onAction="#openFile"></MenuItem>
<MenuItem text="Save" onAction="#saveFile"></MenuItem>
<MenuItem text="Save As..." onAction="#saveasFile"></MenuItem>
<SeparatorMenuItem></SeparatorMenuItem>
<MenuItem text="Page Setup..."></MenuItem>
<MenuItem text="Print"></MenuItem>
<SeparatorMenuItem></SeparatorMenuItem>
<MenuItem text="Exit" onAction="#exitApp"></MenuItem>
</items>
onAction defines the methods that would be called when you click on the respective Items.
These methods will be defined in the controller of the fxml. Defining a controller is simple. Add this to the place you defined BorderPane.
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="NotepadController">
Easy, the fully qualified name of the class is defined here. Next, create a controller class with the name and package matching the fully qualified class name you have given above. Now that you have the controller created, add the methods defined above to your class.
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
public class NotepadController{
@FXML
protected void newFile(ActionEvent event) {
System.out.println("new File");
}
@FXML
protected void openFile(ActionEvent event) {
System.out.println("Open file");
}
@FXML
protected void saveFile(ActionEvent event) {
System.out.println("Save File");
}
@FXML
protected void saveasFile(ActionEvent event) {
System.out.println("Save File As");
}
@FXML
protected void exitApp(ActionEvent event) {
System.out.println("Exiting");
}
}
The code above is very simple. It is just a class with methods defined. Observe the signatures of the method. This is the only thing to be noted down. Now your controller is ready. Lets start adding the functionality.
I start by adding the close event.
Add a close Application code in the exit Event. Just update your code as shown below.
@FXML
protected void exitApp(ActionEvent event) {
Platform.exit();
}
Run your App and test exit event. It should close the application as expected.
Now, lets add the new Functionality. When a user clicks on new the TextArea should be refreshed. This should be simple as well. All you need is a reference of the textArea in your controller. This is done in two steps.
1. Add an ID to textarea in your fxml file
<center>
<TextArea fx:id="textpane">
</TextArea>
</center>
2. declare ID in controller
@FXML
@FXML
private TextArea textpane;
Now, that you have the reference of textarea add the desired functionality.
@FXML
protected void newFile(ActionEvent event) {
textpane.clear();
}
This was simple. Now lets start building the notepad.
First we start with the new File functionality.
@FXML
protected void newFile(ActionEvent event) {
textpane.clear();
Stage stage = (Stage) textpane.getScene().getWindow();
stage.setTitle("Untitled - Notepad");
file = null;
}
We have also defined two global parameters.
private FileChooser fileChooser = new FileChooser();
private File file;
The code is extremely simple. we cleared off the textarea. Then we changed the name of the window title. Third the file parameter was changed to null.
The code for Opening a file.
@FXML
protected void openFile(ActionEvent event) {
file = fileChooser.showOpenDialog(null);
if (file != null) {
Stage stage = (Stage) textpane.getScene().getWindow();
stage.setTitle(file.getName() + " - Notepad");
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(file));
while ((sCurrentLine = br.readLine()) != null) {
textpane.appendText(sCurrentLine + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
First we start with the new File functionality.
@FXML
protected void newFile(ActionEvent event) {
textpane.clear();
Stage stage = (Stage) textpane.getScene().getWindow();
stage.setTitle("Untitled - Notepad");
file = null;
}
We have also defined two global parameters.
private FileChooser fileChooser = new FileChooser();
private File file;
The code is extremely simple. we cleared off the textarea. Then we changed the name of the window title. Third the file parameter was changed to null.
The code for Opening a file.
@FXML
protected void openFile(ActionEvent event) {
file = fileChooser.showOpenDialog(null);
if (file != null) {
Stage stage = (Stage) textpane.getScene().getWindow();
stage.setTitle(file.getName() + " - Notepad");
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(file));
while ((sCurrentLine = br.readLine()) != null) {
textpane.appendText(sCurrentLine + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
It is simple, open a file using a jfilechooser. Traverse it and append the same in the textpane.
The code for saving a file
@FXML
protected void saveFile(ActionEvent event) {
String content = textpane.getText();
if (file != null) {
try {
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
// open a file dialog box
file = fileChooser.showSaveDialog(null);
if (file != null) {
Stage stage = (Stage) textpane.getScene().getWindow();
stage.setTitle(file.getName() + " - Notepad");
try {
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@FXML
protected void saveasFile(ActionEvent event) {
file = fileChooser.showSaveDialog(null);
String content = textpane.getText();
if (file != null) {
Stage stage = (Stage) textpane.getScene().getWindow();
stage.setTitle(file.getName() + " - Notepad");
try {
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The code for saving files is redundant and can be further optimized. But that is not the motive here. You can correct the code as you like. There can be many ways of doing the same thing and I don't deny that, but, keeping it simple is easier to understand.
The above code is not complicated as it may look, thanks to the formatting etc. readily available for usage here, all that is relevant here is setting the stage title and extracting the file information from the user. There are two important things for us how we get the stage from any element and the dialog boxes that we have on save and open.
This completes our File menu related functionality for the notepad except for the print related tasks. I tried looking for JavaFX printing support but could not find one. This is still to be released in future editions. Though, we have alternatives for this but that goes beyond scope.
We know now how simple creating logic can be using JavaFX.
Apart from this lets move to other stuffs in the next and the final blog. Let us explore how Accelerators and Mnemonics be used.
We know now how simple creating logic can be using JavaFX.
Apart from this lets move to other stuffs in the next and the final blog. Let us explore how Accelerators and Mnemonics be used.
No comments:
Post a Comment