2
\$\begingroup\$

Some background: The counter was first made as a joke because we have a lecturer who repeats the 9 phrases found in the program over and over during lectures and I thought it would be funny to create a program that (using user input) would count the number of times the lecturer said these phrases. Two days later (and working on it almost the entire time) I ended up with this.

How clean is this code? How can it be improved? Any suggestions accepted and appreciated. I also used a tool called Eclipse Window Builder to help me with the GUI since I'd only used AWT before and wanted to learn Swing due to its greater support.

LoadingScreen.java;

import java.awt.EventQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import javax.swing.JProgressBar;

public class LoadingScreen extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JLabel imageLabel;
    private JProgressBar progressBar;
    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LoadingScreen frame = new LoadingScreen();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     * © Bernard Borg 2019
     */
    public LoadingScreen() {
        setAlwaysOnTop(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(320, 369);
        setUndecorated(true);
        setLocationRelativeTo(null);

        contentPane = new JPanel();
        contentPane.setBackground(Color.WHITE);
        contentPane.setBorder(new LineBorder(Color.BLUE, 10));
        contentPane.setLayout(null);

        setContentPane(contentPane);

        init();
    }

    public void init() {
        progressBar = new JProgressBar();
        progressBar.setForeground(Color.BLUE);
        progressBar.setBackground(Color.WHITE);
        progressBar.setStringPainted(true);
        progressBar.setBounds(120, 325, 175, 25);

        imageLabel = new JLabel("");
        imageLabel.setVerticalAlignment(SwingConstants.TOP);
        imageLabel.setIcon(new ImageIcon("img/stainesPic.jpg"));
        imageLabel.setBounds(10, 10, 300, 350);

        contentPane.add(progressBar);
        contentPane.add(imageLabel);

        progressBarStuff();
    }

    public void progressBarStuff() {
        Runnable myRunnable = new Runnable() {
            public void run() {
                int i = progressBar.getValue();
                i++;
                progressBar.setValue(i);

                if (progressBar.getValue() == 100) {
                    executor.shutdown();
                    loadMain();
                }
            }
        };

        executor.scheduleAtFixedRate(myRunnable, 0, 30, TimeUnit.MILLISECONDS);
    }

    public void loadMain() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MainFrame frame = new MainFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        dispose();
    }
}

MainFrame.java (Main Program)

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.GridLayout;
import javax.swing.border.LineBorder;
import java.awt.Font;
import javax.swing.JTextArea;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import javax.swing.border.CompoundBorder;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;

public class MainFrame extends JFrame implements KeyListener, ActionListener{

    private static final long serialVersionUID = 1L;
    private static final String version = "v0.2.1 [BETA]";
    private JPanel contentPane;
    private JPanel topPanel;
    private JPanel middlePanel;
    private JPanel bottomPanel;
    private JPanel bottomLeftPanel;
    private JPanel bottomRightPanel;

    private JButton ummmButton;
    private JButton understandButton;
    private JButton okButton;
    private JButton noButton;
    private JButton huhButton;
    private JButton staresButton;
    private JButton questionsButton;
    private JButton clearButton;
    private JButton keyButton;
    private JButton reportButton;
    private JButton copyButton;
    private JButton saveButton;
    private JButton settingsButton;
    private JButton undoButton;
    private JButton resetButton;

    private JTextArea textArea;
    private JScrollPane scrollPane;

    private int ummmCounter = 0;
    private int understandCounter = 0;
    private int okCounter = 0;
    private int noCounter = 0;
    private int huhCounter = 0;
    private int staresCounter = 0;
    private int questionsCounter = 0;
    private int clearCounter = 0;
    private int keyCounter = 0;

    private boolean isSaved = true;


    private ArrayList <String> wordList;


    /**
     * Create the frame.
     */
    public MainFrame() {
        setIconImage(Toolkit.getDefaultToolkit().getImage("img/logo.png"));
        setBackground(Color.WHITE);
        setTitle("Staines Counter " + version);
        addKeyListener(this);
        setFocusable(true);
        requestFocus();

        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        setSize(700, 700);
        setMinimumSize(new Dimension (700, 700));
        setLocationRelativeTo(null);

        addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent windowEvent) {
                if(isSaved == false) {
                    int choice = JOptionPane.showConfirmDialog(null, "Do you want to save?", "Save", JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
                    if (choice == JOptionPane.YES_OPTION){
                        saveAction();
                    } else if (choice == JOptionPane.NO_OPTION){
                        System.exit(0);
                    } else {

                    }
                } else {
                    System.exit(0);
                }
            }
        });

        contentPane = new JPanel();
        contentPane.setForeground(new Color(128, 0, 0));
        contentPane.setBackground(Color.WHITE);
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));

        setContentPane(contentPane);

        init();
    }

    public void init() {
        //Buttons
        ummmButton = new JButton("Ummm");
        ummmButton.setForeground(Color.WHITE);
        ummmButton.setBackground(new Color(128, 0, 0));
        ummmButton.addActionListener(this);

        understandButton = new JButton("Understand?");
        understandButton.setForeground(Color.WHITE);
        understandButton.setBackground(new Color(128, 0, 0));
        understandButton.addActionListener(this);

        okButton = new JButton("Ok");
        okButton.setForeground(Color.WHITE);
        okButton.setBackground(new Color(128, 0, 0));
        okButton.addActionListener(this);

        noButton = new JButton("No?");
        noButton.setForeground(Color.WHITE);
        noButton.setBackground(new Color(128, 0, 0));
        noButton.addActionListener(this);

        huhButton = new JButton("Huh");
        huhButton.setForeground(Color.WHITE);
        huhButton.setBackground(new Color(128, 0, 0));
        huhButton.addActionListener(this);

        staresButton = new JButton("*stares*");
        staresButton.setForeground(Color.WHITE);
        staresButton.setBackground(new Color(128, 0, 0));
        staresButton.addActionListener(this);

        questionsButton = new JButton("Questions?");
        questionsButton.setForeground(Color.WHITE);
        questionsButton.setBackground(new Color(128, 0, 0));
        questionsButton.addActionListener(this);

        clearButton = new JButton("It is clear?");
        clearButton.setForeground(Color.WHITE);
        clearButton.setBackground(new Color(128, 0, 0));
        clearButton.addActionListener(this);

        keyButton = new JButton("Key Point");
        keyButton.setForeground(Color.WHITE);
        keyButton.setBackground(new Color(128, 0, 0));
        keyButton.addActionListener(this);

        copyButton = new JButton("Copy Text");
        copyButton.setForeground(Color.WHITE);
        copyButton.setBackground(new Color(128, 0, 0));
        copyButton.addActionListener(this);

        reportButton = new JButton("Get Report");
        reportButton.setForeground(Color.WHITE);
        reportButton.setBackground(new Color(128, 0, 0));
        reportButton.addActionListener(this);

        settingsButton = new JButton("");
        settingsButton.setForeground(Color.WHITE);
        settingsButton.setBackground(Color.WHITE);
        settingsButton.setIcon(new ImageIcon("img/settings.png"));
        settingsButton.setBounds(80, 0, 35, 35);
        settingsButton.setToolTipText("Settings");
        settingsButton.addActionListener(this);
        settingsButton.setBorderPainted(false);

        saveButton = new JButton("Save");
        saveButton.setBackground(new Color(128, 0, 0));
        saveButton.setForeground(Color.WHITE);
        saveButton.addActionListener(this);

        resetButton = new JButton("Clear");
        resetButton.setForeground(Color.WHITE);
        resetButton.setBackground(new Color(128, 0, 0));
        resetButton.addActionListener(this);

        undoButton = new JButton("");
        undoButton.setBackground(Color.WHITE);
        undoButton.setIcon(new ImageIcon("img/undoIcon.png"));
        undoButton.setBounds(35, 0, 35, 35);
        undoButton.setBorderPainted(false);
        undoButton.addActionListener(this);

        //Text Area
        textArea = new JTextArea();
        textArea.setFont(new Font("Dialog", Font.PLAIN, 14));
        textArea.setRows(20);
        textArea.setWrapStyleWord(true);
        textArea.setForeground(new Color(128, 0, 0));
        textArea.setEditable(false);
        textArea.setLineWrap(true);

        scrollPane = new JScrollPane(textArea);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        //Panels
        topPanel = new JPanel();
        topPanel.setForeground(new Color(128, 0, 0));
        topPanel.setBackground(Color.WHITE);
        topPanel.setLayout(new GridLayout(0, 3, 10, 10));
        topPanel.add(ummmButton);
        topPanel.add(understandButton);
        topPanel.add(okButton);
        topPanel.add(noButton);
        topPanel.add(huhButton);
        topPanel.add(staresButton);
        topPanel.add(questionsButton);
        topPanel.add(clearButton);
        topPanel.add(keyButton);

        middlePanel = new JPanel();
        middlePanel.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10), new LineBorder(new Color(0, 0, 0))));
        middlePanel.setForeground(new Color(128, 0, 0));
        middlePanel.setBackground(Color.WHITE);
        middlePanel.setLayout(new CardLayout(10, 10));
        middlePanel.add(scrollPane, "name_272268444365100");    

        bottomLeftPanel = new JPanel();
        bottomLeftPanel.setBackground(Color.WHITE);
        FlowLayout fl_bottomLeftPanel = (FlowLayout) bottomLeftPanel.getLayout();
        fl_bottomLeftPanel.setHgap(25);
        bottomLeftPanel.add(copyButton);
        bottomLeftPanel.add(reportButton);
        bottomLeftPanel.add(saveButton);
        bottomLeftPanel.add(resetButton);

        bottomRightPanel = new JPanel();
        bottomRightPanel.setBackground(Color.WHITE);
        bottomRightPanel.setLayout(null);
        bottomRightPanel.add(settingsButton);
        bottomRightPanel.add(undoButton);

        bottomPanel = new JPanel();
        bottomPanel.setForeground(new Color(128, 0, 0));
        bottomPanel.setBackground(Color.WHITE);
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS));        
        bottomPanel.add(bottomLeftPanel);
        bottomPanel.add(bottomRightPanel);

        contentPane.add(topPanel, BorderLayout.NORTH);
        contentPane.add(middlePanel, BorderLayout.CENTER);
        contentPane.add(bottomPanel, BorderLayout.SOUTH);

        wordList = new ArrayList <String> ();
    }

    @Override
    public void actionPerformed (ActionEvent e) {
        if(e.getSource() == ummmButton) {
            ummmAction();
        } else if (e.getSource() == understandButton) {
            understandAction();
        } else if (e.getSource() == okButton) {
            okAction();
        } else if (e.getSource() == noButton) {
            noAction();
        } else if (e.getSource() == huhButton) {
            huhAction();
        } else if (e.getSource() == staresButton) {
            staresAction();
        } else if (e.getSource() == questionsButton) {
            questionsAction();
        } else if (e.getSource() == clearButton) {
            clearAction();
        } else if (e.getSource() == keyButton) {
            keyAction();
        } else if (e.getSource() == reportButton) {
            reportAction();
        } else if (e.getSource() == copyButton) {
            copyAction();
        } else if (e.getSource() == saveButton) {
            saveAction();
        } else if (e.getSource() == settingsButton) {
            settingsAction();
        } else if (e.getSource() == resetButton) {
            resetAction();
        } else if (e.getSource() == undoButton) {
            undoAction();
        }
        this.requestFocus();
    }

    @Override
    public void keyPressed (KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_NUMPAD1) {
            questionsAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD2) {
            clearAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD3) {
            keyAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD4) {
            noAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD5) {
            huhAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD6) {
            staresAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD7) {
            ummmAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD8) {
            understandAction();
        } else if (e.getKeyCode() == KeyEvent.VK_NUMPAD9) {
            okAction();
        }
    }

    @Override
    public void keyTyped (KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    public void ummmAction() {
        textArea.setText(textArea.getText() + "ummm...");
        ummmCounter++;
        wordList.add("ummm...");
        isSaved = false;
    }

    public void understandAction() {
        textArea.setText(textArea.getText() + "understand?...");
        understandCounter++;
        wordList.add("understand?...");
        isSaved = false;
    }

    public void okAction() {
        textArea.setText(textArea.getText() + "ok...");
        okCounter++;
        wordList.add("ok...");
        isSaved = false;
    }

    public void noAction() {
        textArea.setText(textArea.getText() + "no...");
        noCounter++;
        wordList.add("no...");
        isSaved = false;
    }

    public void huhAction() {
        textArea.setText(textArea.getText() + "huh...");
        huhCounter++;
        wordList.add("huh...");
        isSaved = false;
    }

    public void staresAction() {
        textArea.setText(textArea.getText() + "*stares*...");
        staresCounter++;
        wordList.add("*stares*...");
        isSaved = false;
    }

    public void questionsAction() {
        textArea.setText(textArea.getText() + "Any questions?...");
        questionsCounter++;
        wordList.add("Any questions?...");
        isSaved = false;
    }

    public void clearAction() {
        textArea.setText(textArea.getText() + "Is it clear?...");
        clearCounter++;
        wordList.add("Is it clear?...");
        isSaved = false;
    }

    public void keyAction() {
        textArea.setText(textArea.getText() + "Did you understand this KEY POINT?...");
        keyCounter++;
        wordList.add("Did you understand this KEY POINT?...");
        isSaved = false;
    }

    public void reportAction() {
        JOptionPane.showMessageDialog(null, "ummm(s): " + ummmCounter + "\nUnderstand?(s): " + understandCounter + "\nOk(s): " + okCounter
                + "\nNo?(s): " + noCounter + "\nHuh(s): " + huhCounter + "\n*stares*: " + staresCounter + "\nQuestions?: " + questionsCounter
                + "\nIt is clear?(s): " + clearCounter + "\nKey point(s): " + keyCounter, "Staines Counter Report", JOptionPane.PLAIN_MESSAGE);
    }

    public void copyAction() {
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(textArea.getText()), null);
    }

    public void saveAction() {
        try{
            DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
            Date date = new Date();

            BufferedWriter bw = new BufferedWriter (new FileWriter ("logs/" + dateFormat.format(date) + ".txt"));

            bw.write(dateFormat.format(date));
            bw.newLine();
            bw.write(String.valueOf("Ummm(s): " + ummmCounter));
            bw.newLine();
            bw.write(String.valueOf("Understand?(s): " + understandCounter));
            bw.newLine();
            bw.write(String.valueOf("Ok(s): " + okCounter));
            bw.newLine();
            bw.write(String.valueOf("No?(s): " + noCounter));
            bw.newLine();
            bw.write(String.valueOf("Huh(s): " + huhCounter));
            bw.newLine();
            bw.write(String.valueOf("*stares*:" + staresCounter));
            bw.newLine();
            bw.write(String.valueOf("Questions?:" + questionsCounter));
            bw.newLine();
            bw.write(String.valueOf("It is clear?(s): " + clearCounter));
            bw.newLine();
            bw.write(String.valueOf("Key point(s): " + keyCounter));
            bw.newLine();
            bw.close();
        } catch (Exception e){
            JOptionPane.showMessageDialog (null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
        isSaved = true;
    }

    public void settingsAction() {
        JOptionPane.showMessageDialog(null, "This feature is not yet available!", "Unavailable Feature", JOptionPane.PLAIN_MESSAGE);
    }

    public void resetAction() {
        textArea.setText("");
        wordList.clear();
        ummmCounter = 0;
        understandCounter = 0;
        okCounter = 0;
        noCounter = 0;
        huhCounter = 0;
        staresCounter = 0;
        questionsCounter = 0;
        clearCounter = 0;
        keyCounter = 0;
        isSaved = true;
    }

    public void undoAction() {
        switch(wordList.get(wordList.size()-1)) {
        case "ummm...":
            ummmCounter--;
            break;
        case "understand?...":
            understandCounter--;
            break;
        case "ok...":
            okCounter--;
            break;
        case "no...":
            noCounter--;
            break;
        case "huh...":
            huhCounter--;
            break;
        case "*stares*...":
            staresCounter--;
            break;
        case "Any questions?...":
            questionsCounter--;
            break;
        case "Is it clear?...":
            clearCounter--;
            break;
        case "Did you understand this KEY POINT?...":
            keyCounter--;
            break;
        }
        wordList.remove(wordList.size()-1);
        textArea.setText("");
        for(String w : wordList) {
            textArea.setText(textArea.getText() + w);
        }
        isSaved = false;
    }
}
```
\$\endgroup\$
1
\$\begingroup\$

I'm on mobile so I'll be brief...

You have 9 copy pasted buttons with identical behaviour, just a different label. Turn those into a reusable class that take the label and action listener as parameters. Instead of hard coding the phrase buttons into instance fields, define the phrases as array of strings and create the buttons from the array. You'll be able to introduce phrases like "I know you post to CodeReview" later. Stuff the JButtons into a list if you need to refer to them later (you probably don't need to).

You've put all your code into the GUI classes. Refactor the counter into a separate model class to adhere to the single responsibility principle. It'll also move your code closer to the MVC model.

The action listener should be it's own class. The UI classes should just be about setting up the components.

What the heck does your loading screen do? Loading screens are evil. Apps should start instantly. Kill it with fire and never do it again. :)

\$\endgroup\$
  • \$\begingroup\$ Thank you for this feedback, will do :) \$\endgroup\$ – Bernard Borg Nov 3 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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