问题
I'm building a calculator and I need to do a general event handler for buttons. Following questions are stopping me:
- How can I make it so it only works when a button is pressed, not outside of window.
- How can I store the displayed value?
- When I press 1 more than once, it doesn't keep going. It maintains only 1 digit and I need like: 111111
Thank you
This is what I have so far, but it doesn't work:
scene.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
tres.pressedProperty().addListener((o, old, newValue) ->
Result.setText("3"));
DisplayingText = Result.getText();
System.out.println(DisplayingText);
if(Result.getText().equals("3"))
{
System.out.println("mouse click detected! ");
}
}
});
回答1:
This app simulates a watered-down calculator. It shows how to use TextField
's appendText
. It also demonstrates how to use one EventHandler
to handle multiple Nodes
.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author blj0011
*/
public class WateredDownCalCulator extends Application
{
@Override
public void start(Stage stage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?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?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="watereddowncalculator.FXMLDocumentController">
<children>
<VBox prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<TextField fx:id="tfDisplay">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</VBox.margin>
</TextField>
<StackPane prefHeight="150.0" prefWidth="200.0">
<children>
<GridPane maxHeight="100.0" maxWidth="100.0" prefHeight="50.0" prefWidth="50.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="50.0" prefWidth="50.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="50.0" prefWidth="50.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleButtonAction" text="1">
<GridPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</GridPane.margin>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleButtonAction" text="2" GridPane.columnIndex="1">
<GridPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</GridPane.margin>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleButtonAction" text="3" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</GridPane.margin>
</Button>
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleButtonAction" text="+" GridPane.columnIndex="1" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</GridPane.margin>
</Button>
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleButtonAction" text="=" GridPane.columnSpan="2" GridPane.rowIndex="2" />
</children>
</GridPane>
</children>
</StackPane>
</children>
</VBox>
</children>
</AnchorPane>
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
/**
*
* @author blj0011
*/
public class FXMLDocumentController implements Initializable
{
@FXML TextField tfDisplay;//TextField create using FXML
//Method use the handle the different buttons' action.
@FXML
private void handleButtonAction(ActionEvent event)
{
Button tempButton = ((Button)event.getSource());//Get the Button that is being pressed
String currentButtonPress = tempButton.getText();//Get the text of the button that is being pressed
//Depending on the Button text do some action
switch(currentButtonPress)
{
case "=":
//do some calculation
break;
case "+":
tfDisplay.appendText(currentButtonPress);
break;
default:
tfDisplay.appendText(currentButtonPress);
}
}
@Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
}
Pure Code Version
import javafx.application.*;
import javafx.event.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
/**
*
* @author Sedrick
*/
public class JavaFXApplication60 extends Application {
@Override
public void start(Stage primaryStage)
{
AnchorPane root = new AnchorPane();
VBox vBox = new VBox();
AnchorPane.setBottomAnchor(vBox, 0.0);
AnchorPane.setTopAnchor(vBox, 0.0);
AnchorPane.setRightAnchor(vBox, 0.0);
AnchorPane.setLeftAnchor(vBox, 0.0);
root.getChildren().add(vBox);
TextField display = new TextField();
display.setEditable(false);//Don't allow the TextField to be editable.
vBox.getChildren().add(display);
VBox.setMargin(display, new Insets(10, 10, 10, 10));
StackPane stackPane = new StackPane();
stackPane.setPrefSize(200, 150);
vBox.getChildren().add(stackPane);
GridPane gridPane = new GridPane();
//gridPane.gridLinesVisibleProperty().set(true);
gridPane.setMinSize(50, 50);
gridPane.setPrefSize(50, 50);
gridPane.setMaxSize(100, 100);
gridPane.setVgap(2);
gridPane.setHgap(2);
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setVgrow(Priority.SOMETIMES);
gridPane.getRowConstraints().addAll(rowConstraints, rowConstraints, rowConstraints);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setHgrow(Priority.SOMETIMES);
columnConstraints.setMinWidth(50);
columnConstraints.setPrefWidth(50);
gridPane.getColumnConstraints().addAll(columnConstraints, columnConstraints);
stackPane.getChildren().add(gridPane);
//Create Buttons
Button btn1 = new Button("1");
Button btn2 = new Button("2");
Button btn3 = new Button("3");
Button btnPlus = new Button("+");
Button btnEqual = new Button("=");
btn1.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btn2.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btn3.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnPlus.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnEqual.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
//Create event handler
EventHandler handle = new EventHandler() {
@Override
public void handle(Event event)
{
Button tempButton = ((Button) event.getSource());//Get the Button that is being pressed
String currentButtonPress = tempButton.getText();//Get the text of the button that is being pressed
//Depending on the Button text do some action
switch (currentButtonPress) {
case "=":
display.setText("results!");
break;
case "+":
display.appendText(currentButtonPress);
break;
default:
display.appendText(currentButtonPress);
}
}
};
//Set buttons' handlers;
btn1.setOnAction(handle);
btn2.setOnAction(handle);
btn3.setOnAction(handle);
btnPlus.setOnAction(handle);
btnEqual.setOnAction(handle);
gridPane.add(btn1, 0, 0, 1, 1);
gridPane.add(btn2, 1, 0, 1, 1);
gridPane.add(btn3, 0, 1, 1, 1);
gridPane.add(btnPlus, 1, 1, 1, 1);
gridPane.add(btnEqual, 0, 2, 2, 1);
Scene scene = new Scene(root, 300, 220);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
You might want to handle the +
action differently.
回答2:
You can use button javafx.scene.control.Button
for numbers and operations to your scene.
Button pressed action handles like this:
button.setOnAction((ActionEvent e) -> {
displayingText = result.getText();
});
回答3:
@Arturo, I remember your application.
For #1 sub-question: no ideas, not clear for me the final goal.
For #2 sub-question: you already have displayed value in Result field.
For #3 sub-question: to append new pressed value you may do the next:
tres.pressedProperty().addListener((o, old, newValue) -> {
if (newValue) {
if ("0".equals(Result.getText()) {
Result.setText("3");
} else {
Result.appendText("3");
}
}
});
As result you will get like: "11113"
Edit: added the protection from first zero. To avoid duplication on each button you may extract if/else into private method and call like updateResult("3");
来源:https://stackoverflow.com/questions/45103809/how-can-i-get-the-text-from-textfield-javafx