I am currently working on a project in Java, and I use JavaFX for the GUI of the System. Currently, I am in the designing phase of the system, where I am designing the look of the system as well as setting up the basic functionality like navigation. I would highly appreciate it if someone can review my simple navigation system and the code I have written so far. I would like to know:
- Any bad practices I am following, and how would I improve them.
- Any architectural issues in my program, and how would I rectify that issue.
- Any techniques I could follow to keep my software more maintainable.
- Any inefficiencies that can be optimised.
- And any sort of points you have in your mind that I could follow to improve my software.
- Anything that you can add to the list above would also highly help.
I also have a preloader for this application, I have provided the code just for the sake of completeness. This preloader was generated by NetBeans.
TeleMart_Preloader.java
/*
* Program developed by Hassan Althaf.
* Copyright © 2015, Hassan Althaf.
* Website: http://hassanalthaf.com
*/
package telemart.preloader;
import javafx.application.Preloader;
import javafx.application.Preloader.ProgressNotification;
import javafx.application.Preloader.StateChangeNotification;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
/**
* Simple Preloader Using the ProgressBar Control
*
* @author hassan
*/
public class TeleMart_Preloader extends Preloader {
ProgressBar bar;
Stage stage;
private Scene createPreloaderScene() {
bar = new ProgressBar();
BorderPane p = new BorderPane();
p.setCenter(bar);
return new Scene(p, 300, 150);
}
@Override
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setScene(createPreloaderScene());
stage.show();
}
@Override
public void handleStateChangeNotification(StateChangeNotification scn) {
if (scn.getType() == StateChangeNotification.Type.BEFORE_START) {
stage.hide();
}
}
@Override
public void handleProgressNotification(ProgressNotification pn) {
bar.setProgress(pn.getProgress());
}
}
com.hassanalthaf.telemart.Main.java:
/*
* Program developed by Hassan Althaf.
* Copyright © 2015, Hassan Althaf.
* Website: http://hassanalthaf.com
*/
package com.hassanalthaf.telemart;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author hassan
*/
public class Main extends Application {
public static final String APPLICATION_TITLE = "TeleMart - ERP System";
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("views/MainView.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setResizable(false);
stage.setTitle(Main.APPLICATION_TITLE);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
com.hassanalthaf.telemart.views.Dashboard.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" fx:id="dashboard" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/dashboard.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hassanalthaf.telemart.viewmodels.DashboardViewModel">
<children>
<MenuBar maxWidth="600.0" minWidth="600.0" prefWidth="600.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="homeMenuItem" mnemonicParsing="false" onAction="#menuItemClick" text="Home" />
<MenuItem fx:id="anotherPageMenuItem" mnemonicParsing="false" onAction="#menuItemClick" text="Another Page" />
<MenuItem fx:id="differentPageMenuItem" mnemonicParsing="false" onAction="#menuItemClick" text="Different Page" />
</items>
</Menu>
</menus>
</MenuBar>
<AnchorPane fx:id="differentPage" layoutY="29.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" opacity="0.0" prefHeight="371.0" prefWidth="600.0">
<children>
<TextArea layoutX="155.0" layoutY="62.0" prefHeight="200.0" prefWidth="200.0" promptText="Page three" />
</children>
</AnchorPane>
<AnchorPane fx:id="anotherPage" layoutY="29.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" opacity="0.0" prefHeight="371.0" prefWidth="600.0">
<children>
<TextField layoutX="180.0" layoutY="77.0" promptText="Page Two" />
</children>
</AnchorPane>
<AnchorPane fx:id="home" layoutY="29.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="371.0" prefWidth="600.0">
<children>
<TextField layoutX="133.0" layoutY="150.0" text="First Page" />
</children>
</AnchorPane>
</children>
</AnchorPane>
com.hassanalthaf.telemart.views.MainView.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" fx:id="mainWindow" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="600.0" stylesheets="@css/style.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hassanalthaf.telemart.viewmodels.MainViewModel">
<children>
<Label layoutX="222.0" layoutY="35.0" styleClass="title" text="TeleMart" />
<TextField layoutX="380.0" layoutY="160.0" onKeyPressed="#loginEnter" promptText="Username">
<styleClass>
<String fx:value="login-field" />
<String fx:value="login-field" />
</styleClass>
</TextField>
<PasswordField layoutX="380.0" layoutY="208.0" onKeyPressed="#loginEnter" promptText="Password" styleClass="login-field" />
<Button layoutX="495.0" layoutY="256.0" mnemonicParsing="false" onMouseClicked="#loginClick" text="Login" />
<Label layoutX="45.0" layoutY="113.0" styleClass="content" text="Welcome to TeleMart's Enterprise Resource Planning System. Please enter your login credentials on the right so that we could verify your identity. Also, please do not share your login credentials with anyone or use another person's login credentials." textAlignment="CENTER" wrapText="true" />
<Label layoutX="220.0" layoutY="309.0" styleClass="content" text="© 2015, Hassan Althaf." />
</children>
</AnchorPane>
com.hassanalthaf.telemart.views.css.style.css:
/*
Program developed by Hassan Althaf.
Copyright © 2015, Hassan Althaf.
Website: http://hassanalthaf.com
*/
/*
Created on : Dec 19, 2015, 6:09:52 PM
Author : hassan
*/
@font-face {
font-family: 'Lato-Regular';
src: url('../fonts/Lato-Regular.ttf');
}
@font-face {
font-family: 'Lato-Hairline';
src: url('../fonts/Lato-Hairline.ttf');
}
.root {
-fx-background-color: #2C3E50;
}
.title {
-fx-font-family: 'Lato-Hairline';
-fx-font-size: 30pt;
-fx-text-fill: #FFFFFF;
}
.login-field {
-fx-background-color: #FFFFFF;
-fx-border-radius: 5pt;
-fx-padding: 10px;
-fx-border-width: 1pt;
-fx-border-style: solid;
-fx-border-color: #202D3A;
-fx-background-insets: 2, 0, 0;
-fx-font-family: 'Lato-Regular';
}
.button {
-fx-background-color: #3498DB;
-fx-text-fill: #FFFFFF;
-fx-font-size: 11pt;
-fx-padding: 8px;
-fx-border-radius: 10pt;
}
.button:hover {
-fx-background-color: #51A7E0;
}
.content {
-fx-font-family: 'Lato-Regular';
-fx-font-size: 11pt;
-fx-text-fill: #FFFFFF;
}
com.hassanalthaf.telemart.views.css.dashboard.css:
/*
Program developed by Hassan Althaf.
Copyright © 2015, Hassan Althaf.
Website: http://hassanalthaf.com
*/
/*
Created on : Dec 19, 2015, 11:29:50 PM
Author : hassan
*/
@font-face {
font-family: 'Lato-Regular';
src: url('../fonts/Lato-Regular.ttf');
}
.menu-bar {
-fx-background-color: #3498DB;
}
.menu:hover {
-fx-background-color: #51A7E0;
}
.menu:showing {
-fx-background-color: #2487C9;
}
.menu .label {
-fx-text-fill: #FFFFFF;
-fx-font-family: 'Lato-Regular';
-fx-font-size: 10pt;
}
.menu-item {
-fx-background-color: #FFFFFF;
}
.menu-item:hover {
-fx-background-color: #51A7E0;
}
.menu-item .label {
-fx-text-fill: #333333;
-fx-font-family: 'Lato-Regular';
-fx-font-size: 10pt;
}
.menu-item:hover .label {
-fx-text-fill: #FFFFFF;
}
com.hassanalthaf.telemart.viewmodels.MainViewModel.java:
/*
* Program developed by Hassan Althaf.
* Copyright © 2015, Hassan Althaf.
* Website: http://hassanalthaf.com
*/
package com.hassanalthaf.telemart.viewmodels;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
/**
*
* @author hassan
*/
public class MainViewModel implements Initializable {
@FXML
private Parent mainWindow;
@FXML
private void loginClick(MouseEvent event) {
try {
this.openDashboard();
} catch (IOException exception) {
}
}
@FXML
private void loginEnter(KeyEvent event) {
if (event.getCode() == KeyCode.ENTER) {
try {
this.openDashboard();
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
private void openDashboard() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/com/hassanalthaf/telemart/views/Dashboard.fxml"));
Parent dashboard = fxmlLoader.load();
DashboardViewModel dashboardViewModel = fxmlLoader.getController();
dashboardViewModel.show(this.mainWindow);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
com.hassanalthaf.telemart.viewmodels.DashboardViewModel.java:
/*
* Program developed by Hassan Althaf.
* Copyright © 2015, Hassan Althaf.
* Website: http://hassanalthaf.com
*/
package com.hassanalthaf.telemart.viewmodels;
import com.hassanalthaf.telemart.Main;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* @author hassan
*/
public class DashboardViewModel implements Initializable {
@FXML
private Parent dashboard;
@FXML
private AnchorPane home;
@FXML
private AnchorPane anotherPage;
@FXML
private AnchorPane differentPage;
private AnchorPane currentPage;
private void changePage(AnchorPane page) {
this.currentPage.setOpacity(0);
this.currentPage = page;
this.currentPage.toFront();
this.currentPage.setOpacity(1);
}
public void menuItemClick(ActionEvent event) {
Object source = (MenuItem)event.getSource();
MenuItem clickedItem;
if(source instanceof MenuItem) {
clickedItem = (MenuItem)source;
} else {
return;
}
String id = clickedItem.getId();
switch (id) {
case "homeMenuItem":
this.changePage(this.home);
break;
case "anotherPageMenuItem":
this.changePage(this.anotherPage);
break;
case "differentPageMenuItem":
this.changePage(this.differentPage);
break;
default:
this.changePage(this.home);
break;
}
}
public void show(Parent main) {
Scene scene = new Scene(this.dashboard);
Stage stage = new Stage();
stage.setScene(scene);
stage.setTitle(Main.APPLICATION_TITLE);
stage.setResizable(false);
stage.show();
Stage mainStage = (Stage)main.getScene().getWindow();
mainStage.close();
}
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
this.currentPage = this.home;
}
}
The entire source code with all the assets can be found here on GitHub.