如何使按钮背景更改 OnClick

tsP*_*mer 1 java javafx fxml java-11 javafx-11

我正在尝试使用 Scene Builder 解决我正在使用 javafx 11 和 java11 处理的计算器项目的问题。我试图找出一种方法,让计算器上的按钮在从键盘输入相应的值时改变颜色。是否有解决此问题的方法或 onKeyPressed 等类型的解决方案?

当用户用鼠标单击按钮时,我能够使按钮改变颜色(变为绿色)。这是在我的 css 样式表中完成的。我尝试向控制器类中的 onKeyReleased 方法添加一个方法,并且可以通过这种方式更改背景,但无法确定一种在不导致 UI 延迟的情况下及时更改颜色的方法。我希望 UI 更改类似于大多数计算器(例如标准 Windows 计算器)的颜色。这是用户按住键并改变颜色的地方,当释放键时它又变回。

//main.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = 
 FXMLLoader.load(getClass().getResource("calculator.fxml"));
    primaryStage.getIcons().add(new Image("CALC.png"));
    primaryStage.setTitle(" TS Calculator");
    primaryStage.setScene(new Scene(root, 250, 375));
    primaryStage.setResizable(true);
    primaryStage.setMinHeight(375);
    primaryStage.setMinWidth(250);
    primaryStage.show();
}
public static void main(String[] args) {
    launch(args);
}

 /CSS
Button{
-fx-background-color: black;
-fx-text-align: center;
-fx-text-fill: white;
-fx-border-color: green;
-fx-font-size: 1em;
-fx-border-radius: 10 10 10 10;
-fx-background-radius: 10 10 10 10;
}
Button:pressed{
-fx-background-color: green;
}
TextField{
-fx-font-size: 1.5em;
}

//FXML (Only showing 1 button)

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane maxHeight="1.7976931348623157E308" 
maxWidth="1.7976931348623157E308" minHeight="306.00" minWidth="204.0"
      prefHeight="288.0" prefWidth="208.0" style="-fx-background-color: 
DARKSLATEGREY; -fx-border-color: green;"
      stylesheets="@styles.css" xmlns="http://javafx.com/javafx/11.0.1" 
xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="com.trevorsmith.Controller"
      onKeyReleased="#acceptKeyboardInput">
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnSpan="4" 
GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS" 
onKeyPressed="#acceptKeyboardInput">
    <children>
            <TextField fx:id="textFieldDisplay"  editable="false" 
alignment="CENTER_RIGHT" maxHeight="1.7976931348623157E308" 
 maxWidth="1.7976931348623157E308" prefWidth="196.0" 
AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" 
AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
  </children>
</AnchorPane>
<AnchorPane maxHeight="1.7976931348623157E308" 
maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" 
GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
  <children>
      <Button maxHeight="1.7976931348623157E308" 
maxWidth="1.7976931348623157E308" text="0" AnchorPane.bottomAnchor="0.0" 
AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="0.0" 
AnchorPane.topAnchor="0.0" />
  </children>
Run Code Online (Sandbox Code Playgroud)

我无法在单击时更改背景颜色,当我松开键时,它又变回了。

Zep*_*hyr 5

您需要在您的设备上注册几个侦听器Scene来收听按下的键。

获得密钥后,您可以使用 JavaFX 的PseudoClass选择器来更新pressed每个Button.

可能有一种更简化的方法来做到这一点,但这是我的实现。这是一个完整的示例,您可以尝试查看它的实际效果。

请注意,我没有实现计算器的实际功能。

最后的最终结果/屏幕截图。


主.java:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("MainLayout.fxml"));

            Scene scene = new Scene(loader.load());
            scene.getStylesheets().add("style.css");
            primaryStage.setScene(scene);
            primaryStage.setTitle("Calculator");
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

MainLayout.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox alignment="TOP_CENTER" spacing="10.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
      fx:controller="UI.BaseApps.Calculator.MainController">
    <padding>
        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
    </padding>
    <children>
        <TextField fx:id="txtDisplay" disable="true" alignment="CENTER_RIGHT" editable="false" minHeight="-Infinity"
                   prefHeight="50.0" text="0"/>
        <GridPane hgap="10.0" vgap="10.0" VBox.vgrow="ALWAYS">
            <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="-Infinity"/>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="-Infinity"/>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="-Infinity"/>
                <ColumnConstraints hgrow="NEVER" minWidth="-Infinity"/>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="-Infinity"/>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="-Infinity"/>
            </columnConstraints>
            <rowConstraints>
                <RowConstraints minHeight="-Infinity" vgrow="SOMETIMES"/>
                <RowConstraints minHeight="-Infinity" vgrow="SOMETIMES"/>
                <RowConstraints minHeight="-Infinity" vgrow="SOMETIMES"/>
                <RowConstraints minHeight="-Infinity" vgrow="SOMETIMES"/>
            </rowConstraints>
            <children>
                <Button fx:id="btn7" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="7"/>
                <Button fx:id="btn8" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="8" GridPane.columnIndex="1"/>
                <Button fx:id="btn9" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="9" GridPane.columnIndex="2"/>
                <Separator orientation="VERTICAL" prefHeight="200.0" GridPane.columnIndex="3" GridPane.rowSpan="4"/>
                <Button fx:id="btnDivide" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="÷" GridPane.columnIndex="4"/>
                <Button fx:id="btnClear" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="C" GridPane.columnIndex="5"/>
                <Button fx:id="btn4" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="4" GridPane.rowIndex="1"/>
                <Button fx:id="btn5" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="5" GridPane.columnIndex="1"
                        GridPane.rowIndex="1"/>
                <Button fx:id="btn6" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="6" GridPane.columnIndex="2"
                        GridPane.rowIndex="1"/>
                <Button fx:id="btnMultiply" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="x" GridPane.columnIndex="4"
                        GridPane.rowIndex="1"/>
                <Button fx:id="btn1" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="1" GridPane.rowIndex="2"/>
                <Button fx:id="btn2" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="2" GridPane.columnIndex="1"
                        GridPane.rowIndex="2"/>
                <Button fx:id="btn3" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="3" GridPane.columnIndex="2"
                        GridPane.rowIndex="2"/>
                <Button fx:id="btn0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" text="0" GridPane.columnSpan="2"
                        GridPane.rowIndex="3"/>
                <Button fx:id="btnDecimal" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="." GridPane.columnIndex="2"
                        GridPane.rowIndex="3"/>
                <Button fx:id="btnSubtract" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="-" GridPane.columnIndex="4"
                        GridPane.rowIndex="2"/>
                <Button fx:id="btnAdd" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="+" GridPane.columnIndex="4"
                        GridPane.rowIndex="3"/>
                <Button fx:id="btnEquals" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="="
                        GridPane.columnIndex="5" GridPane.rowIndex="2" GridPane.rowSpan="2"/>
                <Button fx:id="btnBackspace" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                        mnemonicParsing="false" prefHeight="50.0" prefWidth="50.0" text="?" GridPane.columnIndex="5"
                        GridPane.rowIndex="1"/>
            </children>
        </GridPane>
    </children>
</VBox>
Run Code Online (Sandbox Code Playgroud)

主控制器.java:

import javafx.application.Platform;
import javafx.css.PseudoClass;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;

public class MainController {

    // Here we'll define our PseudoClass needed to set the style for each pressed Button
    private static final PseudoClass PRESSED = PseudoClass.getPseudoClass("pressed");

    // Define FXML controls
    @FXML
    private TextField txtDisplay;
    @FXML
    private Button btn7, btn8, btn9;
    @FXML
    private Button btn4, btn5, btn6;
    @FXML
    private Button btn1, btn2, btn3;
    @FXML
    private Button btn0, btnDecimal;
    @FXML
    private Button btnMultiply, btnSubtract, btnAdd, btnDivide;
    @FXML
    private Button btnClear, btnEquals, btnBackspace;

    @FXML
    private void initialize() {

        // We need access to the Scene to register our key listeners, so we need to wrap the code in a Platform.runLater(). If we try to do this without Platform.runLater(), we'll get a NullPointerException because txtDisplay hasn't been rendered yet.
        Platform.runLater(() -> {

            Scene scene = txtDisplay.getScene();

            // Add a listener to capture any key that is pressed. We add this to the entire scene and we can then change the style of the corresponding button accordingly.
            scene.setOnKeyPressed(event -> {

                // We need to know which Button we're working with
                Button button = getButton(event.getCode());

                // Add our "pressed" style to the Button
                if (button != null) button.pseudoClassStateChanged(PRESSED, true);
            });

            // Once the user releases the key, remove our custom style and trigger whatever onAction() code has been applied to the corresponding Button.
            scene.setOnKeyReleased(event -> {

                Button button = getButton(event.getCode());
                if (button != null) {
                    button.pseudoClassStateChanged(PRESSED, false);

                    // Fire the button's onAction()
                    button.fire();
                }

            });
        });


    }

    // Helper method to get the Button that corresponds to the pressed key. The Scene.setOnKeyPressed() listener provides the KeyCode for the pressed key. We can use that to determine which of our Buttons to trigger.
    private Button getButton(KeyCode keyCode) {
        switch (keyCode) {
            case NUMPAD0: return btn0;
            case NUMPAD1: return btn1;
            case NUMPAD2: return btn2;
            case NUMPAD3: return btn3;
            case NUMPAD4: return btn4;
            case NUMPAD5: return btn5;
            case NUMPAD6: return btn6;
            case NUMPAD7: return btn7;
            case NUMPAD8: return btn8;
            case NUMPAD9: return btn9;
            case DECIMAL: return btnDecimal;
            case DIVIDE: return btnDivide;
            case ADD: return btnAdd;
            case MULTIPLY: return btnMultiply;
            case SUBTRACT: return btnSubtract;
            case ENTER: return btnEquals;
            case BACK_SPACE: return btnBackspace;
            case ESCAPE: return btnClear;
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

样式.css:

.text-field {
    -fx-opacity: 1.0;
    -fx-font-family: Consolas;
    -fx-font-size: 200%;
}

.button {
    -fx-font-family: Consolas;
    -fx-font-size: 150%;
    -fx-background-radius: 25px;
    -fx-border-radius: 25px;

    /* Remove focus highlighting */
    -fx-focus-traversable: false;
}

.button:pressed {
    -fx-background-color: lightgreen;
    -fx-border-color: green;
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

动画截图