1
\$\begingroup\$

I've decided it would be best to break this project down into several parts. Consider this Part 1(GUI Design).

I'm looking for help making 2 main improvements:

  1. Whenever I make a GUI, its always very repetitive to add JLabels, panels, buttons, adding panels to cards, etc. Is there a way to simplify this?
  2. How can I Improve the GUI appearance? Ex: Page 4 (Welcome Message), the Welcome and buttons are very close to each-other, however when changed the gridBagLayout automatically minimizes this distance, how can i space the Label and Buttons out?

Im Open to any other suggests to the code.

OnlineBankingApp Class (Main)

package com.app.bank;

import javax.swing.*;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import java.awt.*;

public class OnlineBankingApp {
    public static void main(String args[]) {
        try{
            UIManager.setLookAndFeel(new NimbusLookAndFeel());
        }catch(Exception e){
            e.printStackTrace();
        }
        EventQueue.invokeLater(() -> new BankFrame().setVisible(true));
    }
}

BankFrame Class

package com.app.bank;

import javax.swing.*;
import java.awt.*;

public class BankFrame extends JFrame {
    BankFrame(){
        this.add(new BankPanel());
        ImageIcon logo = new ImageIcon("BankLogo.png");
        this.setTitle("G-Bank inc.");
        this.setResizable(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.getContentPane().setBackground(new Color(0x123456));
        this.setLayout(new GridBagLayout());
        this.setIconImage(logo.getImage());
        this.setLocationRelativeTo(null);
        this.pack();

    }
}

BankPanel Class

package com.app.bank;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;

public class BankPanel extends JPanel{
    //Primitive Type Initialized
    String name;
    int balance;

    //Initialize Buttons
    JButton loginButton;
    JButton signUpButton;
    JButton createAccount;
    JButton backButton1;
    JButton verifyLogin;
    JButton backButtonP2;
    JButton transactionHistoryButton;
    JButton depositButton;
    JButton withdrawButton;
    JButton checkBalanceButton;
    JButton backButtonP3;
    JButton finalDepositButton;
    JButton backButtonP4;
    JButton finalWithdrawButton;
    JButton backButtonP5;
    JButton backButtonP6;
    JButton logout;

    //Initialize JTables
    JTable transactionHistoryTable;

    //Initialize panels
    JPanel cards;
    JPanel panelOption;
    JPanel panelLogin;
    JPanel panelSignup;
    JPanel panelTable;
    JPanel panelUnlocked;
    JPanel subPanelTable;
    JPanel panelDeposit;
    JPanel panelWithdraw;
    JPanel panelBalance;

    //Initialize Labels
    JLabel usernameSignup;
    JLabel passwordSignup;
    JLabel usernameLogin;
    JLabel passwordLogin;
    JLabel welcomeMessage;
    JLabel depositAmount;
    JLabel withdrawAmount;
    JLabel balanceLabel;

    //Initialize GridBag
    GridBagLayout gridLayout;

    GridBagConstraints loginConstraints;
    GridBagConstraints signUpConstraints;
    GridBagConstraints loginTextConstraints;
    GridBagConstraints PasswordConstraints;
    GridBagConstraints createAccountConstraints;
    GridBagConstraints backButtonConstraints;

    GridBagConstraints usernameLoginConstraints;
    GridBagConstraints userTextLoginConstraints;
    GridBagConstraints passwordLoginConstraints;
    GridBagConstraints passTextLoginConstraints;
    GridBagConstraints checkLoginConstraints;

    GridBagConstraints welcomeMessageConstraints;
    GridBagConstraints transactionHistoryConstraints;
    GridBagConstraints depositConstraints;
    GridBagConstraints withdrawConstraints;
    GridBagConstraints checkBalanceConstraints;
    GridBagConstraints logoutConstraints;

    GridBagConstraints depositLabelConstraints;
    GridBagConstraints depositAmountConstraints;
    GridBagConstraints finalDepositButtonConstraints;
    GridBagConstraints back4Constraints;

    GridBagConstraints withdrawLabelConstraints;
    GridBagConstraints withdrawAmountConstraints;
    GridBagConstraints finalWithdrawButtonConstraints;
    GridBagConstraints back5Constraints;


    //Initialize User/Pass Fields
    JTextField createUserLogin;
    JPasswordField createUserPass;
    JTextField userTextLogin;
    JPasswordField passTextLogin;
    JTextField enterDepositAmount;
    JTextField enterWithdrawAmount;

    //Initialize CardLayout
    CardLayout cardLayout;

    //Page Text
    final static String OPTION_PANEL = "Card with Options";
    final static String LOGIN_PANEL = "Card with Login";
    final static String SIGN_UP_PANEL = "Card with Sign Up";
    final static String TABLE_PANEL = "Card with Table";
    final static String UNLOCKED_PANEL = "Card with Unlocked Options";
    final static String DEPOSIT_PANEL = "Card with Deposit";
    final static String WITHDRAW_PANEL = "Card with Withdraw";
    final static String BALANCE_PANEL = "Card with Balance";

    BankPanel() {
        new Functionality(name);
        Color blue = new Color(0x123456);
        this.setBackground(blue);
        //Initialize Cards
        cards = new JPanel();
        cards.setLayout(cardLayout = new CardLayout());
        gridLayout = new GridBagLayout();
        //Page 1
        panelOption = new JPanel(gridLayout);
        panelOption.setBackground(blue);
        //Page 2
        panelSignup = new JPanel(gridLayout);
        panelSignup.setBackground(blue);
        //Page 3
        panelLogin = new JPanel(gridLayout);
        panelLogin.setBackground(blue);
        //Page 4
        panelUnlocked = new JPanel(gridLayout);
        panelUnlocked.setBackground(blue);
        //Page 5
        subPanelTable = new JPanel();
        subPanelTable.setBackground(blue);
        panelTable = new JPanel();
        panelTable.setBackground(blue);
        panelTable.add(subPanelTable, BorderLayout.SOUTH);

        //Page 6
        panelDeposit = new JPanel(gridLayout);
        panelDeposit.setBackground(blue);
        //Page 7
        panelWithdraw = new JPanel(gridLayout);
        panelWithdraw.setBackground(blue);
        //Page 8
        panelBalance = new JPanel();
        panelBalance.setBackground(blue);

        constraints();
        addComponents();
        addActionListener();
    }
     void constraints() {
        //Initialize Constraints
        loginConstraints = new GridBagConstraints();
        loginConstraints.gridx = 0;
        loginConstraints.gridy = 0;

        signUpConstraints = new GridBagConstraints();
        signUpConstraints.gridx = 0;
        signUpConstraints.gridy = 1;

        loginTextConstraints = new GridBagConstraints();
        loginTextConstraints.gridx = 2;
        loginTextConstraints.gridy = 0;

        PasswordConstraints = new GridBagConstraints();
        PasswordConstraints.gridx = 2;
        PasswordConstraints.gridy = 1;

        createAccountConstraints = new GridBagConstraints();
        createAccountConstraints.gridx = 1;
        createAccountConstraints.gridy = 2;

        backButtonConstraints = new GridBagConstraints();
        backButtonConstraints.gridx = 0;
        backButtonConstraints.gridy = 2;

        usernameLoginConstraints = new GridBagConstraints();
        usernameLoginConstraints.gridx = 0;
        usernameLoginConstraints.gridy = 0;

        userTextLoginConstraints = new GridBagConstraints();
        userTextLoginConstraints.gridx = 2;
        userTextLoginConstraints.gridy = 0;

        passwordLoginConstraints = new GridBagConstraints();
        passwordLoginConstraints.gridx = 0;
        passwordLoginConstraints.gridy = 1;

        passTextLoginConstraints = new GridBagConstraints();
        passTextLoginConstraints.gridx = 2;
        passTextLoginConstraints.gridy = 1;

        checkLoginConstraints = new GridBagConstraints();
        checkLoginConstraints.gridx = 1;
        checkLoginConstraints.gridy = 2;

        welcomeMessageConstraints = new GridBagConstraints();
        welcomeMessageConstraints.gridx = 4;
        welcomeMessageConstraints.gridy = 0;

        transactionHistoryConstraints = new GridBagConstraints();
        transactionHistoryConstraints.gridx = 1;
        transactionHistoryConstraints.gridy = 8;

        depositConstraints = new GridBagConstraints();
        depositConstraints.gridx = 3;
        depositConstraints.gridy = 8;

        withdrawConstraints = new GridBagConstraints();
        withdrawConstraints.gridx = 5;
        withdrawConstraints.gridy = 8;

        checkBalanceConstraints = new GridBagConstraints();
        checkBalanceConstraints.gridx = 7;
        checkBalanceConstraints.gridy = 8;

        depositLabelConstraints = new GridBagConstraints();
        depositLabelConstraints.gridx = 0;
        depositLabelConstraints.gridy = 0;

        depositAmountConstraints = new GridBagConstraints();
        depositAmountConstraints.gridx = 0;
        depositAmountConstraints.gridy = 1;

        finalDepositButtonConstraints = new GridBagConstraints();
        finalDepositButtonConstraints.gridx = 1;
        finalDepositButtonConstraints.gridy = 1;

        back4Constraints = new GridBagConstraints();
        back4Constraints.gridx = 0;
        back4Constraints.gridy = 2;

        withdrawLabelConstraints  = new GridBagConstraints();
        withdrawLabelConstraints.gridx = 0;
        withdrawLabelConstraints.gridy = 0;

        withdrawAmountConstraints = new GridBagConstraints();
        withdrawAmountConstraints.gridx = 0;
        withdrawAmountConstraints.gridy = 1;

        finalWithdrawButtonConstraints = new GridBagConstraints();
        finalWithdrawButtonConstraints.gridx = 1;
        finalWithdrawButtonConstraints.gridy = 1;

        back5Constraints = new GridBagConstraints();
        back5Constraints.gridx = 0;
        back5Constraints.gridy = 2;

        logoutConstraints = new GridBagConstraints();
        logoutConstraints.gridx = 7;
        logoutConstraints.gridy = 9;

    }

    void addComponents(){
        //Add Page1 Components
        loginButton = new JButton("Login");
        panelOption.add(loginButton);

        signUpButton = new JButton("Sign Up");
        panelOption.add(signUpButton);

        //Add page 2 components
        usernameSignup = new JLabel("Enter Your Full Name:");
        panelSignup.add(usernameSignup, loginConstraints);
        createUserLogin = new JTextField(15);
        panelSignup.add(createUserLogin, loginTextConstraints);

        passwordSignup = new JLabel("Enter New Password:");
        panelSignup.add(passwordSignup, signUpConstraints);
        createUserPass = new JPasswordField(15);
        panelSignup.add(createUserPass, PasswordConstraints);

        createAccount = new JButton("Create Account");
        panelSignup.add(createAccount, createAccountConstraints);

        backButton1 = new JButton("Back");
        panelSignup.add(backButton1, backButtonConstraints);

        //Add page 3 components
        usernameLogin = new JLabel("Username:");
        panelLogin.add(usernameLogin, usernameLoginConstraints);
        userTextLogin = new JTextField(15);
        panelLogin.add(userTextLogin, userTextLoginConstraints);

        passwordLogin = new JLabel("Password:");
        panelLogin.add(passwordLogin, passwordLoginConstraints);
        passTextLogin = new JPasswordField(15);
        panelLogin.add(passTextLogin, passTextLoginConstraints);

        verifyLogin = new JButton("Login");
        panelLogin.add(verifyLogin, checkLoginConstraints);

        backButtonP2 = new JButton("Back");
        panelLogin.add(backButtonP2, backButtonConstraints);

        //Page 4 components
        welcomeMessage = new JLabel("Welcome!");
        welcomeMessage.setFont(new Font("SansSerif Bold", Font.PLAIN, 18));
        panelUnlocked.add(welcomeMessage, welcomeMessageConstraints);

        transactionHistoryButton = new JButton("Transaction History");
        panelUnlocked.add(transactionHistoryButton, transactionHistoryConstraints);
        depositButton = new JButton("Deposit");
        panelUnlocked.add(depositButton, depositConstraints);
        withdrawButton = new JButton("Withdraw");
        panelUnlocked.add(withdrawButton, withdrawConstraints);
        checkBalanceButton = new JButton("Check Balance");
        panelUnlocked.add(checkBalanceButton, checkBalanceConstraints);
        logout = new JButton("Logout");
        panelUnlocked.add(logout, logoutConstraints);


        //Page 5 components
        String [] tableColumns = {"Name", "Location", "Amount", "Date-Time"};
        String[][] tableData = new String[4][];
        transactionHistoryTable = new JTable(new DefaultTableModel(tableData, tableColumns));

        transactionHistoryTable.setBackground(Color.WHITE);
        transactionHistoryTable.setForeground(Color.BLACK);
        transactionHistoryTable.setSelectionBackground(Color.red);
        transactionHistoryTable.setGridColor(Color.red);
        transactionHistoryTable.setSelectionForeground(Color.white);
        transactionHistoryTable.setFont(new Font("Tahoma", Font.PLAIN, 17));
        transactionHistoryTable.setRowHeight(30);
        transactionHistoryTable.setAutoCreateRowSorter(true);

        JScrollPane scrollPane = new JScrollPane(transactionHistoryTable);
        transactionHistoryTable.setFillsViewportHeight(true);
        scrollPane.setBackground(Color.white);
        scrollPane.setForeground(Color.red);

        backButtonP3 = new JButton("Back");
        subPanelTable.add(backButtonP3, BorderLayout.LINE_START);

        panelTable.add(scrollPane);

        //Page 6
        depositAmount = new JLabel("How Much Would You Like To Deposit Today?: ");
        depositAmount.setFont(new Font("Tahoma", Font.PLAIN, 17));
        enterDepositAmount = new JTextField(15);
        panelDeposit.add(depositAmount, depositLabelConstraints);
        panelDeposit.add(enterDepositAmount, depositAmountConstraints);
        finalDepositButton = new JButton("Deposit Money");
        panelDeposit.add(finalDepositButton, finalDepositButtonConstraints);
        backButtonP4 = new JButton("Back");
        panelDeposit.add(backButtonP4, back4Constraints);

        //Page 7
        withdrawAmount = new JLabel("How Much Would You Like To Withdraw Today?: ");
        withdrawAmount.setFont(new Font("Tahoma", Font.PLAIN, 17));
        enterWithdrawAmount = new JTextField(15);
        panelWithdraw.add(withdrawAmount, withdrawLabelConstraints);
        panelWithdraw.add(enterWithdrawAmount, withdrawAmountConstraints);
        finalWithdrawButton = new JButton("Withdraw Money");
        panelWithdraw.add(finalWithdrawButton, finalWithdrawButtonConstraints);
        backButtonP5 = new JButton("Back");
        panelWithdraw.add(backButtonP5, back5Constraints);

        //Page 8
        balanceLabel = new JLabel("Your Current Balance Is: " + balance);
        panelBalance.add(balanceLabel);
        backButtonP6 = new JButton("Back");
        panelBalance.add(backButtonP6);

        //add pages to cards
        cards.add(panelOption, OPTION_PANEL);
        cards.add(panelLogin, LOGIN_PANEL);
        cards.add(panelSignup,SIGN_UP_PANEL);
        cards.add(panelTable, TABLE_PANEL);
        cards.add(panelUnlocked, UNLOCKED_PANEL);
        cards.add(panelDeposit, DEPOSIT_PANEL);
        cards.add(panelWithdraw, WITHDRAW_PANEL);
        cards.add(panelBalance, BALANCE_PANEL);
        cardLayout.show(cards, OPTION_PANEL);
        this.add(cards);

    }
    void addActionListener(){
        //Switch to page 2
        signUpButton.addActionListener(e -> cardLayout.show(cards, SIGN_UP_PANEL));

        //Switch to Page 3
        loginButton.addActionListener(e -> cardLayout.show(cards, LOGIN_PANEL));

        //Return to Option Screen
        backButton1.addActionListener(e -> cardLayout.show(cards, OPTION_PANEL));
        backButtonP2.addActionListener(e -> cardLayout.show(cards, OPTION_PANEL));
        logout.addActionListener(e -> cardLayout.show(cards, OPTION_PANEL));

        //Open Bank Screen Page 4
        verifyLogin.addActionListener(e -> cardLayout.show(cards, UNLOCKED_PANEL));
        createAccount.addActionListener(e -> cardLayout.show(cards, UNLOCKED_PANEL));
        backButtonP3.addActionListener(e -> cardLayout.show(cards, UNLOCKED_PANEL));
        backButtonP4.addActionListener(e -> cardLayout.show(cards, UNLOCKED_PANEL));
        backButtonP5.addActionListener(e -> cardLayout.show(cards, UNLOCKED_PANEL));
        backButtonP6.addActionListener(e -> cardLayout.show(cards, UNLOCKED_PANEL));

        //Open Transaction History Page 5
        transactionHistoryButton.addActionListener(e -> cardLayout.show(cards,TABLE_PANEL));

        //Open Deposit Page
        depositButton.addActionListener(e -> cardLayout.show(cards, DEPOSIT_PANEL));
        //Open Withdraw Page
        withdrawButton.addActionListener(e -> cardLayout.show(cards, WITHDRAW_PANEL));
        //Open Check Balance Page
        checkBalanceButton.addActionListener(e -> cardLayout.show(cards,BALANCE_PANEL));
    }
}
\$\endgroup\$

3 Answers 3

2
\$\begingroup\$

I do not have launched your app so I cannot (I do not want to) tell anything about the UI/UX.

However, about the code and your two questions:

  1. Whenever I make a GUI, its always very repetitive to add JLabels, panels, buttons, adding panels to cards, etc. Is there a way to simplify this?

You can always use a more descriptive language that will be parsed later to build your views. Or use a GUI designer. But, at the end, whenever it is done by yourself or via another library/framework/tool/generator/.. the components have to be instantiated and configured.

But you can create other components when you see an emerging pattern. You can also create a "magic" component that will build itself from a shorter description model. You can also create a factory or builder to reduce the amount of code you need to create a view.

ToolBarBuilder
  .action("Save", ()->onSave())
  .separator()
  .action("Delete", ()->onDelete())
  .build(); // Icons added based on action name

new EditDialog(new MyEditForm(..), (form)->onSaveChange(form)); // Set the size, position, headers and default "Save" and "Cancel" buttons. 

About your code I think you should already extract many components, this will help you to understand and maintain your code. At least, one component per page. You can also try to move the constraints closer to the component, this is easier when you want to build a mental image of how your GUI will look. When I was doing intensive Swing development with almost all panels using the GridBagLayout, I create a GridBagConstraintBuilder with a tiny dsl with names close to the HTML tables (I was used with HTML tables at that time) and sane defaults (for our app). So that the addition and positioning of one component was easy to read and understand:

add(new JLabel(".."), at(1, 2) // set gridx and gridy
  .colspan(3) // set gridwidth
  .build()    // always fill horizontal with 1.0 weightx
 
  1. How can I Improve the GUI appearance? Ex: Page 4 (Welcome Message), the Welcome and buttons are very close to each-other, however when changed the gridBagLayout automatically minimizes this distance, how can i space the Label and Buttons out?

If you want to add space between your components there are two solutions:

\$\endgroup\$
1
\$\begingroup\$

methods

you have a lot of redundant code - you could use methods to reduce code & increase readability. for that purpose it won't hurt to use static methods from an utility class

example 1 (two lines --> one line)

//Page 1
panelOption = new JPanel(gridLayout);
panelOption.setBackground(blue);

would be

panelOption = BankPanelUtility.newJPanel(gridLayout, blue); 

example 2 (three lines --> one line)

loginConstraints = new GridBagConstraints();
loginConstraints.gridx = 0;
loginConstraints.gridy = 0;

would be

loginConstraints = BankPanelUtility.newGridBagConstraints(0, 0);

example 3 (four lines --> one line)

//Add page 2 components
usernameSignup = new JLabel("Enter Your Full Name:");
panelSignup.add(usernameSignup, loginConstraints);
createUserLogin = new JTextField(15);
panelSignup.add(createUserLogin, loginTextConstraints);

would be

usernameSignup = BankPanelUtility.newLogin(panelSignup, "Enter Your Full Name:", 15 loginConstraints, loginTextConstraints);

Note: consider recommend to create the constraints directly within BankPanelUtility.newLogin() instead of doing that in the previous constraints() method. if you would do it within the BankPanelUtility the method would only have two parameters: usernameSignup = BankPanelUtility.newLogin(panelSignup, "Enter Your Full Name:");

Using local variables

a lot of your components are only created to display something (JLabel) or arrange something (GridBagConstraints). these Object don^t need to be stored in class variables. they can be created ad hoc!

example 1

signUpButton = new JButton("Sign Up");
panelOption.add(signUpButton);

would be

panelOption.add(new JButton("Sign Up"));

you could remove all display-only fields, all fields that have no action on it (i see some JButton and some JTtextField that HAVE actions on, these should be kept as class variables)

predefined values

you have some magic numbers (new JTextField(15)) and some re-occuring definitions (new Font("Tahoma", Font.PLAIN, 17)). assigne these values as final class variables:

class BankPanel{

    private final Font panelFont = new Font("Tahoma", Font.PLAIN, 17);
    private final int textFieldSize = 15;

    ...

    void addComponents(){

        ...

        enterDepositAmount = new JTextField(textFieldSize);

        ...

        transactionHistoryTable.setFont(panelFont);       
}

\$\endgroup\$
-5
\$\begingroup\$

Not sure where to start here:

  1. You are using Java
  2. The UX is bad
  3. It looks ugly
  4. The code isn't formtted
  5. It's just bad you know
\$\endgroup\$
1
  • 2
    \$\begingroup\$ This isn't what I'd call a helpful review - most of these observations are highly subjective, and would be better if you showed fragments of the code and what the improved code would look like for comparison. Some justification as to why your proposed changes are improvements would be welcome, too. \$\endgroup\$ Commented Jun 15, 2021 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.