如何创建自定义节点类?
问题描述:
我是java和javafx的新手。我试图创建一个自定义类来显示timepicker,但它不会直观地呈现节点。如何创建自定义节点类?
下列课程出了什么问题?
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);
}
}
叫它 这表明被称为本后的空白窗口。
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;
}
你也可以拨打GridPane timer = new TLTimePicker(5,27,0,"PM").render()
在demo
而不是TLTimePicker timer = new TLTimePicker(5,27,0,"PM")
而不会改变任何东西使其工作,这将使扩展GridPane以某种方式过时...
首先,您应该使用fxml文件的布局层次结构深度。 然后我注意到,你从render方法返回一个GridPane,但你只是在构造函数中调用它,而不使用'使用它的值...这可能吗? 所以你的GridPane组在最后已经过时了,因为你可以添加内容到“this”,因为你的类已经是一个(n空的)GridPane了。 – deHaar