4 files changed
+433
-28
No files matched your search
@@ -55,3 +55,46 @@ Who won the 2022 World Championship?|Max Verstappen
|
|||||||
Which driver has the most career race starts?|Fernando Alonso
|
Which driver has the most career race starts?|Fernando Alonso
|
||||||
What does VSC stand for?|Virtual Safety Car
|
What does VSC stand for?|Virtual Safety Car
|
||||||
Who is the most successful British F1 driver in terms of wins?|Lewis Hamilton
|
Who is the most successful British F1 driver in terms of wins?|Lewis Hamilton
|
||||||
|
What planet is closest to the sun?|Mercury
|
||||||
|
What is the longest bone in the human body?|Femur
|
||||||
|
Which ocean lies on the east coast of the USA?|Atlantic
|
||||||
|
Which organ helps you breathe?|Lungs
|
||||||
|
Who invented the telephone?|Alexander Graham Bell
|
||||||
|
What is the capital of Spain?|Madrid
|
||||||
|
What number comes after 999?|1000
|
||||||
|
Which fruit is yellow and curved?|Banana
|
||||||
|
What is a baby dog called?|Puppy
|
||||||
|
What is the largest country in the world by area?|Russia
|
||||||
|
What is the main language spoken in China?|Mandarin
|
||||||
|
What instrument has six strings?|Guitar
|
||||||
|
What is the hottest planet in the solar system?|Venus
|
||||||
|
What natural satellite orbits Earth?|Moon
|
||||||
|
What is the capital of Australia?|Canberra
|
||||||
|
What gas do humans need to breathe?|Oxygen
|
||||||
|
How many minutes are in an hour?|60
|
||||||
|
What do cows drink?|Water
|
||||||
|
Which continent is Egypt part of?|Africa
|
||||||
|
What is 10 × 10?|100
|
||||||
|
Who wrote “Harry Potter”?|J.K. Rowling
|
||||||
|
What food do pandas primarily eat?|Bamboo
|
||||||
|
What is the capital of Germany?|Berlin
|
||||||
|
How many colors are in a rainbow?|7
|
||||||
|
What is the largest bird?|Ostrich
|
||||||
|
What machine measures temperature?|Thermometer
|
||||||
|
What is the capital of Russia?|Moscow
|
||||||
|
Which animal is known for laughing?|Hyena
|
||||||
|
What planet is known for its big red spot?|Jupiter
|
||||||
|
What is the main ingredient in sushi?|Rice
|
||||||
|
Who painted The Starry Night?|Vincent van Gogh
|
||||||
|
Which country invented pizza?|Italy
|
||||||
|
What is the capital of Mexico?|Mexico City
|
||||||
|
How many letters are in the English alphabet?|26
|
||||||
|
What is the biggest internal organ?|Liver
|
||||||
|
What animal is the symbol of Canada?|Beaver
|
||||||
|
What is the process of water turning into vapor?|Evaporation
|
||||||
|
What is the capital of South Korea?|Seoul
|
||||||
|
Which bird cannot fly?|Penguin
|
||||||
|
What is the name of Earth’s largest continent?|Asia
|
||||||
|
How many sides does a square have?|4
|
||||||
|
Who was the first president of the United States?|George Washington
|
||||||
|
What part of the plant is typically green?|Leaf
|
||||||
@@ -1,5 +1,19 @@
|
|||||||
package ca.bcit.comp2522.lab11;
|
package ca.bcit.comp2522.lab11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a single quiz question containing a question prompt
|
||||||
|
* and one or more valid answers. A user-provided answer is considered
|
||||||
|
* correct if it matches any of the stored answers, ignoring case.
|
||||||
|
*
|
||||||
|
* This class performs validation to ensure question text and answer
|
||||||
|
* strings are never null or blank.
|
||||||
|
*
|
||||||
|
* @author Braeden Sowinski
|
||||||
|
* @author Nico Agostini
|
||||||
|
* @author Trishaan Shetty
|
||||||
|
* @author Calvin Arifianto
|
||||||
|
* @version 1.0.0
|
||||||
|
*/
|
||||||
public class Question
|
public class Question
|
||||||
{
|
{
|
||||||
private static final int MIN_ANSWERS = 1;
|
private static final int MIN_ANSWERS = 1;
|
||||||
@@ -7,6 +21,12 @@ public class Question
|
|||||||
private final String question;
|
private final String question;
|
||||||
private final String[] answers;
|
private final String[] answers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that a string is not null or blank.
|
||||||
|
*
|
||||||
|
* @param str the string to validate
|
||||||
|
* @throws IllegalArgumentException if the string is null or blank
|
||||||
|
*/
|
||||||
private static void validateString(final String str)
|
private static void validateString(final String str)
|
||||||
{
|
{
|
||||||
if (str == null || str.isBlank())
|
if (str == null || str.isBlank())
|
||||||
@@ -15,9 +35,18 @@ public class Question
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Question with a prompt and accepted answers.
|
||||||
|
*
|
||||||
|
* @param question the question text
|
||||||
|
* @param answers the list of valid answers
|
||||||
|
* @throws IllegalArgumentException if question is invalid,
|
||||||
|
* or if answers is empty,
|
||||||
|
* or if any individual answer is invalid
|
||||||
|
*/
|
||||||
public Question(
|
public Question(
|
||||||
final String question,
|
final String question,
|
||||||
final String[] answers
|
final String[] answers
|
||||||
) {
|
) {
|
||||||
validateString(question);
|
validateString(question);
|
||||||
|
|
||||||
@@ -35,21 +64,38 @@ public class Question
|
|||||||
this.answers = answers;
|
this.answers = answers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the question text.
|
||||||
|
*
|
||||||
|
* @return the question string
|
||||||
|
*/
|
||||||
public String getQuestion()
|
public String getQuestion()
|
||||||
{
|
{
|
||||||
return this.question;
|
return this.question;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of accepted answers.
|
||||||
|
*
|
||||||
|
* @return an array of valid answers
|
||||||
|
*/
|
||||||
public String[] getAnswers()
|
public String[] getAnswers()
|
||||||
{
|
{
|
||||||
return this.answers;
|
return this.answers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user's answer is correct.
|
||||||
|
* Matching is case-insensitive.
|
||||||
|
*
|
||||||
|
* @param userAnswer the answer provided by the user
|
||||||
|
* @return true if it matches one of the valid answers; false otherwise
|
||||||
|
*/
|
||||||
public boolean validateAnswer(final String userAnswer)
|
public boolean validateAnswer(final String userAnswer)
|
||||||
{
|
{
|
||||||
for (final String answer : this.answers)
|
for (final String answer : this.answers)
|
||||||
{
|
{
|
||||||
if (answer.equals(userAnswer))
|
if (answer.equalsIgnoreCase(userAnswer))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +1,336 @@
|
|||||||
package ca.bcit.comp2522.lab11;
|
package ca.bcit.comp2522.lab11;
|
||||||
|
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A timed quiz application that loads questions from an external file
|
||||||
|
* and presents them to the user in randomized order. The user has a
|
||||||
|
* limited amount of time to answer a fixed number of questions.
|
||||||
|
* Final results are shown when time expires or all questions are answered.
|
||||||
|
*
|
||||||
|
* @author Braeden Sowinski
|
||||||
|
* @author Nico Agostini
|
||||||
|
* @author Trishaan Shetty
|
||||||
|
* @author Calvin Arifianto
|
||||||
|
* @version 1.0.0
|
||||||
|
*/
|
||||||
public class Quiz extends Application
|
public class Quiz extends Application
|
||||||
{
|
{
|
||||||
private static final int WIDTH = 800;
|
private static final int WIDTH = 800;
|
||||||
private static final int HEIGHT = 600;
|
private static final int HEIGHT = 600;
|
||||||
private static final int QUESTION_SPLIT = 0;
|
private static final int QUESTION_SPLIT = 0;
|
||||||
private static final int ANSWER_SPLIT = 1;
|
private static final int COUNTER_STARTER = 0;
|
||||||
private static final String DELIMITER = "\\|";
|
private static final int ANSWER_SPLIT = 1;
|
||||||
private static final int NUM_QUESTIONS = 10;
|
private static final int ONE_SECOND = 1;
|
||||||
|
private static final int MIN_LENGTH = 2;
|
||||||
|
private static final String DELIMITER = "\\|";
|
||||||
|
private static final int NUM_QUESTIONS = 10;
|
||||||
|
private static final int START_TIME_SECS = 90;
|
||||||
|
private static final Path QUIZ_FILE_PATH = Paths.get("comp2522", "data", "quiz.txt");
|
||||||
|
|
||||||
private final List<Question> questions = new ArrayList<>();
|
private final List<Question> questions = new ArrayList<>();
|
||||||
|
private List<Question> quizQuestions = new ArrayList<>();
|
||||||
|
|
||||||
private Question current;
|
private Question current;
|
||||||
|
|
||||||
private void readQuestions(final String file)
|
private int currentQuestionIndex;
|
||||||
|
private int correctCount;
|
||||||
|
private int wrongCount;
|
||||||
|
private int remainingSeconds;
|
||||||
|
|
||||||
|
private Timeline timeline;
|
||||||
|
|
||||||
|
private VBox root;
|
||||||
|
private Label questionLabel;
|
||||||
|
private Label feedbackLabel;
|
||||||
|
private Label statusLabel;
|
||||||
|
private TextField answerField;
|
||||||
|
private Button submitButton;
|
||||||
|
private Button startButton;
|
||||||
|
private Button playAgainButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and loads quiz questions from a file.
|
||||||
|
*
|
||||||
|
* @param path the path to the quiz data file
|
||||||
|
*/
|
||||||
|
private void readQuestions(final Path path)
|
||||||
{
|
{
|
||||||
final BufferedReader reader;
|
if (!questions.isEmpty())
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
reader = new BufferedReader(new FileReader(file));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (BufferedReader reader =
|
||||||
|
new BufferedReader(new FileReader(path.toAbsolutePath().toFile())))
|
||||||
|
{
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null)
|
while ((line = reader.readLine()) != null)
|
||||||
{
|
{
|
||||||
final String question;
|
final String[] parts = line.split(DELIMITER);
|
||||||
final String[] answers;
|
if (parts.length < MIN_LENGTH)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
question = line.split(DELIMITER)[QUESTION_SPLIT];
|
final String questionText = parts[QUESTION_SPLIT];
|
||||||
answers = line.split(DELIMITER)[ANSWER_SPLIT].split(",");
|
final String[] answers = parts[ANSWER_SPLIT].split(",");
|
||||||
|
|
||||||
questions.add(new Question(
|
questions.add(new Question(
|
||||||
question,
|
questionText,
|
||||||
answers
|
answers
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (final FileNotFoundException e)
|
catch (final FileNotFoundException e)
|
||||||
{
|
{
|
||||||
System.out.println("Unable to open file: " + file);
|
System.out.println("Unable to open file: " + path);
|
||||||
}
|
}
|
||||||
catch (final IOException e)
|
catch (final IOException e)
|
||||||
{
|
{
|
||||||
System.out.println("Error reading file: " + file);
|
System.out.println("Error reading file: " + path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the UI and starts the JavaFX application.
|
||||||
|
*
|
||||||
|
* @param stage the primary stage
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void start(final Stage stage)
|
public void start(final Stage stage)
|
||||||
{
|
{
|
||||||
final Scene scene;
|
|
||||||
final VBox root;
|
|
||||||
|
|
||||||
root = new VBox();
|
root = new VBox();
|
||||||
root.setPrefSize(WIDTH, HEIGHT);
|
root.setPrefSize(WIDTH, HEIGHT);
|
||||||
scene = new Scene(root);
|
|
||||||
|
|
||||||
this.current = this.questions.get(new Random().nextInt(this.questions.size()));
|
questionLabel = new Label("Click \"Start quiz\" to begin.");
|
||||||
|
feedbackLabel = new Label();
|
||||||
|
statusLabel = new Label();
|
||||||
|
|
||||||
|
answerField = new TextField();
|
||||||
|
answerField.setPromptText("Type your answer here");
|
||||||
|
|
||||||
|
submitButton = new Button("Submit");
|
||||||
|
startButton = new Button("Start quiz");
|
||||||
|
playAgainButton = new Button("Play again");
|
||||||
|
|
||||||
readQuestions("./data/quiz.txt");
|
answerField.setDisable(true);
|
||||||
|
submitButton.setDisable(true);
|
||||||
|
playAgainButton.setDisable(true);
|
||||||
|
playAgainButton.setVisible(false);
|
||||||
|
|
||||||
|
root.getChildren().addAll(
|
||||||
|
questionLabel,
|
||||||
|
answerField,
|
||||||
|
submitButton,
|
||||||
|
feedbackLabel,
|
||||||
|
statusLabel,
|
||||||
|
startButton,
|
||||||
|
playAgainButton
|
||||||
|
);
|
||||||
|
|
||||||
|
Scene scene = new Scene(root);
|
||||||
|
|
||||||
|
scene.getStylesheets().add(
|
||||||
|
getClass().getResource("style.css").toExternalForm()
|
||||||
|
);
|
||||||
|
|
||||||
|
readQuestions(QUIZ_FILE_PATH);
|
||||||
|
|
||||||
|
if (questions.isEmpty())
|
||||||
|
{
|
||||||
|
questionLabel.setText("No questions loaded. Check quiz.txt path/contents.");
|
||||||
|
startButton.setDisable(true);
|
||||||
|
stage.setScene(scene);
|
||||||
|
stage.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Runnable submitAction = () -> {
|
||||||
|
if (current == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String userAnswer;
|
||||||
|
userAnswer = answerField.getText();
|
||||||
|
|
||||||
|
if (userAnswer == null || userAnswer.isBlank())
|
||||||
|
{
|
||||||
|
feedbackLabel.setText("Please enter an answer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String cleaned = userAnswer.trim();
|
||||||
|
|
||||||
|
if (current.validateAnswer(cleaned))
|
||||||
|
{
|
||||||
|
correctCount++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wrongCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentQuestionIndex++;
|
||||||
|
showNextQuestion();
|
||||||
|
};
|
||||||
|
|
||||||
|
submitButton.setOnAction(event -> submitAction.run());
|
||||||
|
answerField.setOnAction(event -> submitAction.run());
|
||||||
|
startButton.setOnAction(event -> startGame());
|
||||||
|
playAgainButton.setOnAction(event -> startGame());
|
||||||
|
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
|
stage.setTitle("Quiz");
|
||||||
stage.show();
|
stage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new quiz round, resets counters, shuffles questions,
|
||||||
|
* and initializes the timer.
|
||||||
|
*/
|
||||||
|
private void startGame()
|
||||||
|
{
|
||||||
|
correctCount = COUNTER_STARTER;
|
||||||
|
wrongCount = COUNTER_STARTER;
|
||||||
|
remainingSeconds = START_TIME_SECS;
|
||||||
|
currentQuestionIndex = COUNTER_STARTER;
|
||||||
|
|
||||||
|
feedbackLabel.setText("");
|
||||||
|
questionLabel.setText("");
|
||||||
|
|
||||||
|
quizQuestions = new ArrayList<>(questions);
|
||||||
|
Collections.shuffle(quizQuestions);
|
||||||
|
|
||||||
|
if (quizQuestions.size() > NUM_QUESTIONS)
|
||||||
|
{
|
||||||
|
quizQuestions = new ArrayList<>(quizQuestions.subList(COUNTER_STARTER, NUM_QUESTIONS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeline != null)
|
||||||
|
{
|
||||||
|
timeline.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline = new Timeline(
|
||||||
|
new KeyFrame(Duration.seconds(ONE_SECOND), event -> {
|
||||||
|
remainingSeconds--;
|
||||||
|
updateStatusLabel();
|
||||||
|
|
||||||
|
if (remainingSeconds <= COUNTER_STARTER)
|
||||||
|
{
|
||||||
|
endGame("Time's up!");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
timeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
|
timeline.play();
|
||||||
|
|
||||||
|
answerField.setDisable(false);
|
||||||
|
submitButton.setDisable(false);
|
||||||
|
startButton.setDisable(true);
|
||||||
|
playAgainButton.setDisable(true);
|
||||||
|
playAgainButton.setVisible(false);
|
||||||
|
|
||||||
|
showNextQuestion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the next question or ends the quiz if none remain.
|
||||||
|
*/
|
||||||
|
private void showNextQuestion()
|
||||||
|
{
|
||||||
|
if (currentQuestionIndex >= quizQuestions.size())
|
||||||
|
{
|
||||||
|
endGame("You answered all questions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = quizQuestions.get(currentQuestionIndex);
|
||||||
|
|
||||||
|
questionLabel.setText(current.getQuestion());
|
||||||
|
answerField.clear();
|
||||||
|
feedbackLabel.setText("");
|
||||||
|
|
||||||
|
updateStatusLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the status label to show progress and remaining time.
|
||||||
|
*/
|
||||||
|
private void updateStatusLabel()
|
||||||
|
{
|
||||||
|
if (quizQuestions.isEmpty())
|
||||||
|
{
|
||||||
|
statusLabel.setText("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int displayIndex =
|
||||||
|
Math.min(currentQuestionIndex + ONE_SECOND, quizQuestions.size());
|
||||||
|
|
||||||
|
statusLabel.setText(
|
||||||
|
displayIndex + "/" + quizQuestions.size()
|
||||||
|
+ " ::: " + remainingSeconds + "s remaining"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the game, stops the timer, and displays the final score.
|
||||||
|
*
|
||||||
|
* @param reason explanation for ending (e.g., time expired)
|
||||||
|
*/
|
||||||
|
private void endGame(final String reason)
|
||||||
|
{
|
||||||
|
if (timeline != null)
|
||||||
|
{
|
||||||
|
timeline.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
submitButton.setDisable(true);
|
||||||
|
answerField.setDisable(true);
|
||||||
|
current = null;
|
||||||
|
|
||||||
|
final String finalScore =
|
||||||
|
reason + "\n\nFinal score:"
|
||||||
|
+ "\nCorrect: " + correctCount
|
||||||
|
+ "\nWrong: " + wrongCount;
|
||||||
|
|
||||||
|
feedbackLabel.setText(finalScore);
|
||||||
|
|
||||||
|
questionLabel.setText("Game over.");
|
||||||
|
statusLabel.setText("");
|
||||||
|
|
||||||
|
playAgainButton.setVisible(true);
|
||||||
|
playAgainButton.setDisable(false);
|
||||||
|
startButton.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard Java entry point. Launches the JavaFX app.
|
||||||
|
*
|
||||||
|
* @param args CLI arguments
|
||||||
|
*/
|
||||||
public static void main(final String[] args)
|
public static void main(final String[] args)
|
||||||
{
|
{
|
||||||
launch(args);
|
launch(args);
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/* Overall background */
|
||||||
|
.root {
|
||||||
|
-fx-background-color: linear-gradient(to bottom, #fafafa, #eaeaea);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VBox container (add style class "vbox" in code if you want this) */
|
||||||
|
.vbox {
|
||||||
|
-fx-spacing: 10;
|
||||||
|
-fx-alignment: center;
|
||||||
|
-fx-padding: 20;
|
||||||
|
-fx-background-color: #f5f5f5;
|
||||||
|
-fx-border-color: #dddddd;
|
||||||
|
-fx-border-width: 1;
|
||||||
|
-fx-border-radius: 8;
|
||||||
|
-fx-background-radius: 8;
|
||||||
|
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.15), 10, 0.2, 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Labels */
|
||||||
|
.label {
|
||||||
|
-fx-font-size: 16px;
|
||||||
|
-fx-text-fill: #444444;
|
||||||
|
-fx-padding: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text fields */
|
||||||
|
.text-field {
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
-fx-text-fill: #222222;
|
||||||
|
-fx-prompt-text-fill: gray;
|
||||||
|
-fx-background-color: #ffffff;
|
||||||
|
-fx-border-color: #2196F3;
|
||||||
|
-fx-border-radius: 5;
|
||||||
|
-fx-background-radius: 5;
|
||||||
|
-fx-padding: 5 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Optional: highlight on focus */
|
||||||
|
.text-field:focused {
|
||||||
|
-fx-border-color: #1976D2;
|
||||||
|
-fx-effect: dropshadow(gaussian, rgba(25, 118, 210, 0.4), 8, 0.3, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.button {
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
-fx-background-color: linear-gradient(to bottom, #4CAF50, #388E3C);
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-border-radius: 5;
|
||||||
|
-fx-background-radius: 5;
|
||||||
|
-fx-padding: 5 14;
|
||||||
|
-fx-cursor: hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover and pressed effects for buttons */
|
||||||
|
.button:hover {
|
||||||
|
-fx-background-color: linear-gradient(to bottom, #66BB6A, #43A047);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:pressed {
|
||||||
|
-fx-background-color: linear-gradient(to bottom, #388E3C, #2E7D32);
|
||||||
|
-fx-translate-y: 1;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user