3
\$\begingroup\$

In my project I used this code to create a GUI using JavaFX. The aim was to have a screen with 7 buttons on it. Next, depending on which button is pressed another set of buttons will appear on the screen. The user then chooses one of these which then sets an integer variable subchapter to a value and calls the next methods. However, from looking at my code to do this, it seems very inefficient and I was wondering if there was a better way to code this.

Firstly, this is my code to declare the buttons I use:

Label choice;
Button chapter1;
Button chapter2;
Button chapter3;
Button chapter4;
Button chapter5;
Button chapter6;
Button chapter7;
public int subchapter = 0;

Next this is the code where I use the buttons:

private void chooseQuiz() {


    root.getChildren().clear();
    choice = new Label();
    choice.setText("Please choose a chapter ");
    choice.setLayoutX(50);
    choice.setLayoutY(0);


    chapter1 = new Button();
    chapter1.setText("Applied Anatomy and physiology");
    chapter1.setLayoutX(30);
    chapter1.setLayoutY(50);
    chapter1.setWrapText(true);
    chapter1.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("The cardiovascular and respiratory system");
        chapter1.setOnAction(event1 -> {
            subchapter = 1;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter2.setText("The neuromuscular and musculoskeletal system");
        chapter2.setOnAction(event1 -> {
            subchapter = 2;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter3.setText("Energy systems");
        chapter3.setOnAction(event1 -> {
            subchapter = 3;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1, chapter2, chapter3);
    });

    chapter2 = new Button();
    chapter2.setText("Skill acquisition");
    chapter2.setLayoutX(30);
    chapter2.setLayoutY(150);
    chapter2.setWrapText(true);
    chapter2.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("Skill classifications and Information processing and transfer of skills");
        chapter1.setOnAction(event1 -> {
            subchapter = 4;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter2.setText("Theories of learning and guidance and feedback and methods of presenting practice");
        chapter2.setOnAction(event1 -> {
            subchapter = 5;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1, chapter2);
    });

    chapter3 = new Button();
    chapter3.setText("Sport and society");
    chapter3.setLayoutX(30);
    chapter3.setLayoutY(250);
    chapter3.setWrapText(true);
    chapter3.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("Pre-industrial/industrial/post industrial sport");
        chapter1.setOnAction(event1 -> {
            subchapter = 6;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter2.setText("Sociology in sport");
        chapter2.setOnAction(event1 -> {
            subchapter = 7;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1, chapter2);
    });

    chapter4 = new Button();
    chapter4.setText("Exercise physiology");
    chapter4.setLayoutX(30);
    chapter4.setLayoutY(350);
    chapter4.setWrapText(true);
    chapter4.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("Diet and nutrition and training methods and injury prevention and rehabilitation");
        chapter1.setOnAction(event1 -> {
            subchapter = 8;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1);
    });

    chapter5 = new Button();
    chapter5.setText("Biomechanical movement");
    chapter5.setLayoutX(30);
    chapter5.setLayoutY(450);
    chapter5.setWrapText(true);
    chapter5.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("Biomechanical principles and levers");
        chapter1.setOnAction(event1 -> {
            subchapter = 9;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter2.setText("Linear motion and Angular motion ");
        chapter2.setOnAction(event1 -> {
            subchapter = 10;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter3.setText("Projectile motion and Fluid mechanics");
        chapter3.setOnAction(event1 -> {
            subchapter = 11;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1, chapter2, chapter3);
    });

    chapter6 = new Button();
    chapter6.setText("Sport Psychology");
    chapter6.setLayoutX(30);
    chapter6.setLayoutY(550);
    chapter6.setWrapText(true);
    chapter6.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("Personality and attitudes");
        chapter1.setOnAction(event1 -> {
            subchapter = 12;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter2.setText("Arousal and anxiety");
        chapter2.setOnAction(event1 -> {
            subchapter = 13;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter3.setText("Aggression and motivation");
        chapter3.setOnAction(event1 -> {
            subchapter = 14;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter4.setText("Achievement motivation and self-efficacy");
        chapter4.setOnAction(event1 -> {
            subchapter = 15;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter5.setText("Social facilitation and group dynamics and goal setting");
        chapter5.setOnAction(event1 -> {
            subchapter = 16;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter6.setText("Attribution theory and leadership and stress management");
        chapter6.setOnAction(event1 -> {
            subchapter = 17;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1, chapter2, chapter3, chapter4, chapter5, chapter6);
    });

    chapter7 = new Button();
    chapter7.setText("Sport and society and technology in sport");
    chapter7.setLayoutX(30);
    chapter7.setLayoutY(650);
    chapter7.setWrapText(true);
    chapter7.setOnAction(event -> {
        root.getChildren().clear();
        choice.setText("Please choose a topic");
        chapter1.setText("Physical activity and sport and the development of elite performers");
        chapter1.setOnAction(event1 -> {
            subchapter = 18;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter2.setText("Ethics and violence in sport");
        chapter2.setOnAction(event1 -> {
            subchapter = 19;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter3.setText("Drugs in sport and sport and the law");
        chapter3.setOnAction(event1 -> {
            subchapter = 20;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter4.setText("Commercialisation");
        chapter4.setOnAction(event1 -> {
            subchapter = 21;
            getQuestionsAndScores();
            runQuiz();
        });
        chapter5.setText("Technology in sport");
        chapter5.setOnAction(event1 -> {
            subchapter = 22;
            getQuestionsAndScores();
            runQuiz();
        });
        root.getChildren().addAll(choice, chapter1, chapter2, chapter3, chapter4, chapter5);
    });


    root.getChildren().addAll(choice, chapter1, chapter2, chapter3, chapter4, chapter5, chapter6, 
    chapter7);

    Scene scene = new Scene(root, 500, 800);
    subStage.setScene(scene);
    subStage.show();
}
```
\$\endgroup\$
1
  • \$\begingroup\$ My thoughts are to use a database or text file to hold the information and load the information as you move forward. Here is a simpler question game I created a while back. I hope it helps. It loads all the questions at the beginning of the program. \$\endgroup\$
    – SedJ601
    Commented Feb 14, 2021 at 7:17

1 Answer 1

3
\$\begingroup\$

First thing that comes to mind is subclassing Button, perhaps nesting it in your main class so it can easily modify class variables:

import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;

public class Quiz {

    private int subchapter;
    private Pane root = new Pane();

    private void chooseQuiz() {
        MyButton chapter1 = new MyButton("Skill acquisition", 30, 150, e -> {...});
        chapter1.setSubchapter(18);
    }
    private void getQuestionsAndScores() {...}
    private void runQuiz() {...}

    private class MyButton extends Button {
        private MyButton(String text, int x, int y, EventHandler<ActionEvent> onClick) {
            super(text);
            this.setLayoutX(30);
            this.setLayoutY(50);
            this.setWrapText(true);
            this.setOnAction(onClick);
            root.getChildren().add(this);
        }
        private void setSubchapter(int value) {
            this.setOnAction(e -> {
                subchapter = value;
                getQuestionsAndScores();
                runQuiz();
            });
        }
    }
}

This is essentially streamlining your code, delegating verbose code and repetitive calls to the constructor/class functions, which I assume is what you mean by "efficient".

EDIT:

As mjt pointed out, this could be considered an abuse of inheritance. A more proper way that avoids the use of inheritance would be using functions:

import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;

public class Quiz {

    private int subchapter;
    private Pane root = new Pane();

    private void chooseQuiz() {
        MyButton chapter1 = createButton("Skill acquisition", 30, 150, e -> {...});
        setSubchapter(chapter1, 18);
    }
    private void getQuestionsAndScores() {...}
    private void runQuiz() {...}

    private Button createButton(String text, int x, int y, EventHandler<ActionEvent> onClick) {
        Button button = new Button();
        button.setText(text);
        button.setLayoutX(x);
        button.setLayoutY(y);
        button.setWrapText(true);
        button.setOnAction(onClick);
        root.getChildren().add(button);
        return button;
    }
    private void setSubchapter(Button target, int value) {
        target.setOnAction(e -> {
            subchapter = value;
            getQuestionsAndScores();
            runQuiz();
        });
    }
}

```
\$\endgroup\$
4
  • \$\begingroup\$ Would you mind explaining why it should be made a private class specifically? I'm not questioning your answer, simply wondering why this would be better/worse than making it a 'regular' public class. \$\endgroup\$
    – cliesens
    Commented Dec 13, 2019 at 2:19
  • \$\begingroup\$ Look up "Java data encapsulation". Basically, you want to restrict access to methods, fields, and classes as much as possible so that we don't have outside classes depending on them when they shouldn't be. In the above example, I assumed that MyButton would only by used in the Quiz class, so I set its access to as restrictive as possible. As for the different types of access mods, (private, public), see here \$\endgroup\$
    – Kein
    Commented Dec 13, 2019 at 3:02
  • 1
    \$\begingroup\$ With inheritance viewed quite critically nowadays (e.g. softwareengineering.stackexchange.com/questions/260343/…) a simple configuration of a button probably does not warrant a subclass. Rather create a method to create and fully initialize a button. \$\endgroup\$
    – mtj
    Commented Dec 13, 2019 at 6:21
  • \$\begingroup\$ That's interesting, I haven't seen that mentioned anywhere in my time lurking on SO... I suppose it is unnecessary to use a subclass. I'll update the answer. \$\endgroup\$
    – Kein
    Commented Dec 13, 2019 at 21: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.