如何创建自定义节点 class?
How to create a custom Node class?
我是 java 和 javafx 的新手。我尝试创建一个自定义 class 来显示时间选择器,但它不会在视觉上呈现节点。
下面的问题是什么class?
package customcombobox;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class TLTimePicker extends GridPane{
private int hr = 1;
private int min;
private int sec;
private String meas = "AM";
private String value = hr+":"+ min +":"+ sec +" "+meas;
private final VBox timePicker = new VBox(5);
public TLTimePicker(){
this.render();
}
public TLTimePicker(int hour, int minute, int second, String measure){
this.hr = hour;
this.min = minute;
this.sec = second;
this.meas = measure;
this.value = hr+":"+ min +":"+ sec +" "+meas;
this.render();
}
public GridPane render(){
HBox contnr = new HBox();
TextField txtfld = new TextField();
txtfld.setEditable(false);
Button open = new Button();
contnr.getChildren().addAll(txtfld, open);
ImageView arrow = new ImageView(new Image(getClass().getResourceAsStream("down.png")));
open.setGraphic(arrow);
arrow.setFitWidth(12);
arrow.setFitHeight(12);
Label hrLbl = new Label("Hour");
Spinner hour = new Spinner(1, 13, 1);
Label mntLbl = new Label("minute");
Spinner minute = new Spinner(0, 61, 0);
Label scnLbl = new Label("second");
Spinner second = new Spinner(0, 61, 0);
ComboBox<String> ampm = new ComboBox<String>();
ampm.getItems().addAll("AM", "PM");
ampm.getSelectionModel().selectFirst();
hour.setPrefWidth(52);
minute.setPrefWidth(52);
second.setPrefWidth(52);
ampm.setPrefWidth(64);
hour.setEditable(true);
minute.setEditable(true);
second.setEditable(true);
txtfld.setText(value);
hour.valueProperty().addListener((ob, ov, nv) -> {
hr = (int)nv;
if(ov.equals(12)) {
hour.getValueFactory().setValue(1);
hr = 1;
}
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
minute.valueProperty().addListener((ob, ov, nv) -> {
min = (int)nv;
if(ov.equals(60)) {
minute.getValueFactory().setValue(0);
min = 0;
}
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
second.valueProperty().addListener((ob, ov, nv) -> {
sec = (int)nv;
if(ov.equals(60)) {
second.getValueFactory().setValue(0);
sec = 0;
}
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
ampm.setOnAction((event) -> {
meas = ampm.getValue();
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
GridPane grid = new GridPane();
grid.add(hrLbl, 0, 0);
grid.add(hour, 1, 0);
grid.add(mntLbl, 0, 1);
grid.add(minute, 1, 1);
grid.add(scnLbl, 0, 2);
grid.add(second, 1, 2);
grid.setHgap(5);
grid.setVgap(5);
timePicker.getChildren().addAll(grid, ampm);
timePicker.setStyle("-fx-background-color:"
+ "#ededed; -fx-border-color: "
+ "#dddddd; -fx-border-size:1;"
+ "-fx-padding:5 25;");
hidetimePicker();
arrow.setRotate(0);
EventHandler showHide = (event) -> {
Object[] obj = {hour, minute, second};
String[] arr = txtfld.getText().split("[\s:]+");
for(int i=0; i<arr.length;i++ ){
if(arr[i].matches("^(\d+)$")) {
((Spinner)obj[i]).getValueFactory().setValue(Integer.parseInt(arr[i]));
} else {
ampm.setValue(arr[i].toUpperCase());
}
}
if(timePicker.visibleProperty().getValue()) {
hidetimePicker();
arrow.setRotate(0);
} else {
timePicker.setVisible(true);
timePicker.setManaged(true);
arrow.setRotate(180);
}
};
open.setOnAction(showHide);
txtfld.setOnMousePressed(showHide);
GridPane group = new GridPane();
group.add(contnr, 0, 0);
group.add(timePicker, 0, 1);
timePicker.toFront();
Scene scene = group.getScene();
// scene.setOnMousePressed((event) -> {
// hidetimePicker();
// arrow.setRotate(0);
// });
return group;
}
private void hidetimePicker(){
timePicker.setVisible(false);
timePicker.setManaged(false);
}
}
调用它
用这个调用后显示空白window。
package customcombobox;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class demo extends Application {
@Override
public void start(final Stage primaryStage) {
TLTimePicker timer = new TLTimePicker(5,27,0,"PM");
HBox box = new HBox();
box.getChildren().add(timer);
Scene scene = new Scene(box, 350, 250);
primaryStage.setScene(scene);
primaryStage.setTitle("TimePicker");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
稍微改变一下您的 render()
。
首先,使方法 void
:
public void render() {
// most part of your code just stays as it is
...
其次,更改最后几行(注释掉的是你的行,其余行使其有效):
...
// GridPane group = new GridPane(); ---> you don't need a new one
// group.add(contnr, 0, 0);
// group.add(timePicker, 0, 1);
this.add(contnr, 0, 0);
this.add(timePicker, 0, 1);
timePicker.toFront();
// Scene scene = group.getScene();
// scene.setOnMousePressed((event) -> {
// hidetimePicker();
// arrow.setRotate(0);
// });
// return group;
}
您也可以在 demo
中调用 GridPane timer = new TLTimePicker(5,27,0,"PM").render()
而不是 TLTimePicker timer = new TLTimePicker(5,27,0,"PM")
并且不更改任何其他内容以使其工作,这将使扩展 GridPane 以某种方式过时......
我是 java 和 javafx 的新手。我尝试创建一个自定义 class 来显示时间选择器,但它不会在视觉上呈现节点。
下面的问题是什么class?
package customcombobox;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class TLTimePicker extends GridPane{
private int hr = 1;
private int min;
private int sec;
private String meas = "AM";
private String value = hr+":"+ min +":"+ sec +" "+meas;
private final VBox timePicker = new VBox(5);
public TLTimePicker(){
this.render();
}
public TLTimePicker(int hour, int minute, int second, String measure){
this.hr = hour;
this.min = minute;
this.sec = second;
this.meas = measure;
this.value = hr+":"+ min +":"+ sec +" "+meas;
this.render();
}
public GridPane render(){
HBox contnr = new HBox();
TextField txtfld = new TextField();
txtfld.setEditable(false);
Button open = new Button();
contnr.getChildren().addAll(txtfld, open);
ImageView arrow = new ImageView(new Image(getClass().getResourceAsStream("down.png")));
open.setGraphic(arrow);
arrow.setFitWidth(12);
arrow.setFitHeight(12);
Label hrLbl = new Label("Hour");
Spinner hour = new Spinner(1, 13, 1);
Label mntLbl = new Label("minute");
Spinner minute = new Spinner(0, 61, 0);
Label scnLbl = new Label("second");
Spinner second = new Spinner(0, 61, 0);
ComboBox<String> ampm = new ComboBox<String>();
ampm.getItems().addAll("AM", "PM");
ampm.getSelectionModel().selectFirst();
hour.setPrefWidth(52);
minute.setPrefWidth(52);
second.setPrefWidth(52);
ampm.setPrefWidth(64);
hour.setEditable(true);
minute.setEditable(true);
second.setEditable(true);
txtfld.setText(value);
hour.valueProperty().addListener((ob, ov, nv) -> {
hr = (int)nv;
if(ov.equals(12)) {
hour.getValueFactory().setValue(1);
hr = 1;
}
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
minute.valueProperty().addListener((ob, ov, nv) -> {
min = (int)nv;
if(ov.equals(60)) {
minute.getValueFactory().setValue(0);
min = 0;
}
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
second.valueProperty().addListener((ob, ov, nv) -> {
sec = (int)nv;
if(ov.equals(60)) {
second.getValueFactory().setValue(0);
sec = 0;
}
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
ampm.setOnAction((event) -> {
meas = ampm.getValue();
String value = hr+":"+ min +":"+ sec +" "+meas;
txtfld.setText(value);
});
GridPane grid = new GridPane();
grid.add(hrLbl, 0, 0);
grid.add(hour, 1, 0);
grid.add(mntLbl, 0, 1);
grid.add(minute, 1, 1);
grid.add(scnLbl, 0, 2);
grid.add(second, 1, 2);
grid.setHgap(5);
grid.setVgap(5);
timePicker.getChildren().addAll(grid, ampm);
timePicker.setStyle("-fx-background-color:"
+ "#ededed; -fx-border-color: "
+ "#dddddd; -fx-border-size:1;"
+ "-fx-padding:5 25;");
hidetimePicker();
arrow.setRotate(0);
EventHandler showHide = (event) -> {
Object[] obj = {hour, minute, second};
String[] arr = txtfld.getText().split("[\s:]+");
for(int i=0; i<arr.length;i++ ){
if(arr[i].matches("^(\d+)$")) {
((Spinner)obj[i]).getValueFactory().setValue(Integer.parseInt(arr[i]));
} else {
ampm.setValue(arr[i].toUpperCase());
}
}
if(timePicker.visibleProperty().getValue()) {
hidetimePicker();
arrow.setRotate(0);
} else {
timePicker.setVisible(true);
timePicker.setManaged(true);
arrow.setRotate(180);
}
};
open.setOnAction(showHide);
txtfld.setOnMousePressed(showHide);
GridPane group = new GridPane();
group.add(contnr, 0, 0);
group.add(timePicker, 0, 1);
timePicker.toFront();
Scene scene = group.getScene();
// scene.setOnMousePressed((event) -> {
// hidetimePicker();
// arrow.setRotate(0);
// });
return group;
}
private void hidetimePicker(){
timePicker.setVisible(false);
timePicker.setManaged(false);
}
}
调用它 用这个调用后显示空白window。
package customcombobox;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class demo extends Application {
@Override
public void start(final Stage primaryStage) {
TLTimePicker timer = new TLTimePicker(5,27,0,"PM");
HBox box = new HBox();
box.getChildren().add(timer);
Scene scene = new Scene(box, 350, 250);
primaryStage.setScene(scene);
primaryStage.setTitle("TimePicker");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
稍微改变一下您的 render()
。
首先,使方法 void
:
public void render() {
// most part of your code just stays as it is
...
其次,更改最后几行(注释掉的是你的行,其余行使其有效):
...
// GridPane group = new GridPane(); ---> you don't need a new one
// group.add(contnr, 0, 0);
// group.add(timePicker, 0, 1);
this.add(contnr, 0, 0);
this.add(timePicker, 0, 1);
timePicker.toFront();
// Scene scene = group.getScene();
// scene.setOnMousePressed((event) -> {
// hidetimePicker();
// arrow.setRotate(0);
// });
// return group;
}
您也可以在 demo
中调用 GridPane timer = new TLTimePicker(5,27,0,"PM").render()
而不是 TLTimePicker timer = new TLTimePicker(5,27,0,"PM")
并且不更改任何其他内容以使其工作,这将使扩展 GridPane 以某种方式过时......