如何创建自定义Node类?

时间:2017-07-19 09:35:21

标签: java javafx custom-controls

我是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);
    }    
}

1 个答案:

答案 0 :(得分:0)

稍稍更改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在某种程度上过时...