不起作用的JavaFX属性

时间:2018-01-08 18:09:02

标签: javafx

所以当我试图改变Circle半径时,我有一个奇怪的错误,它基本上没有做任何事情,我不明白为什么。

我假设在事件中出现了问题虽然我真的没有问题,但问题是什么

所以当我试图改变Circle半径时,我有一个奇怪的错误,它基本上没有做任何事情,我不明白为什么。

我假设在事件中出现了问题虽然我真的没有问题,但问题是什么

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;

public class CircleController1 extends BorderPane implements EventHandler<ActionEvent> {
    private CircleModel1 model;
    private TextField tfRadius = new TextField();
    ObservableList<Boolean> Filled = FXCollections.observableArrayList(new Boolean(false), new Boolean(true));

    private ComboBox<?> cboFilled = new ComboBox<>(Filled);
    private ColorPicker cp = new ColorPicker();

    /** Creates new form CircleController */
    public CircleController1() {
        HBox radius=new HBox(20,new Label("Radius"),tfRadius);
        HBox filled=new HBox(20,new Label("Filled"),cboFilled);
        HBox color=new HBox(20,new Label("Color"),cp);
        VBox elements = new VBox(20);
        elements.getChildren().addAll(radius, filled, color);
        setLeft(elements);
        tfRadius.setPrefWidth(150);
        cboFilled.setPrefWidth(150);
        cp.setPrefWidth(150);
        cp.setOnAction(this);
        tfRadius.setOnAction(this);
        cboFilled.setOnAction(this);
        cboFilled.getSelectionModel().selectFirst();
        cp.setValue(Color.BLACK);


    }

    public void setModel(CircleModel1 newModel) {
        model = newModel;
        model.setColor(cp.getValue());
        model.setRadius(model.getRadius());
        model.setFilled((Boolean) cboFilled.getValue());
    }

    public CircleModel1 getModel() {
        return model;
    }

    @Override
    public void handle(ActionEvent event) {

        if (model == null)
            return;
        else if (event.getSource() == tfRadius)
            model.setRadius(Double.parseDouble(tfRadius.getText()));
        else if (event.getSource() == cp) {
            model.setColor(cp.getValue());
        } else {
            model.setFilled((Boolean) cboFilled.getValue());

        }

    }
}
  public interface CircleEvents  
{ enum eventType
  { RADIUS, AREA, COLOR, FILLED
  }
}
    import java.util.ArrayList;

    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.Property;
    import javafx.beans.property.SimpleBooleanProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.beans.property.SimpleObjectProperty;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;

    import javafx.scene.paint.Color;

    public class CircleModel1 implements CircleEvents {

        private Property<Number> radius=new SimpleDoubleProperty(20);

        /** Property filled. */
        private Property<Boolean> filled=new SimpleBooleanProperty();
        /** Property color. */
        private ObjectProperty<Color> color=new SimpleObjectProperty<>();
        /** Utility field used by event firing mechanism. */
        private ArrayList<EventHandler<myActionEvent>> EventHandlerList;

        public double getRadius() {
            return (double) radius.getValue();
        }

        public void setRadius(double radius) {
            this.radius.setValue(radius); 
            // Notify the listener for the change on radius
            processEvent(new myActionEvent(new ActionEvent(), eventType.RADIUS));
        }

        public boolean isFilled() {
            return (boolean) filled.getValue();
        }

        public void setFilled(boolean filled) {
            this.filled.setValue(filled); 

            // Notify the listener for the change on filled
            processEvent(new myActionEvent(new ActionEvent(), eventType.FILLED));
        }

        public Color getColor() {
            return color.getValue();
        }

        public void setColor(Color color) {
            this.color.setValue(color);
            // Notify the listener for the change on color
            processEvent(new myActionEvent(new ActionEvent(), eventType.COLOR));
        }

        /** Register an action event listener */
        public synchronized void addEventHandler(EventHandler<myActionEvent> l) {
            if (EventHandlerList == null)
                EventHandlerList = new ArrayList<EventHandler<myActionEvent>>();
            EventHandlerList.add(l);
        }

        /** Remove an action event listener */
        public synchronized void removeActionListener(EventHandler<myActionEvent> l) {
            if (EventHandlerList != null && EventHandlerList.contains(l))
                EventHandlerList.remove(l);
        }

        /** Fire Event */
        private void processEvent(myActionEvent e) {
            synchronized (this) {
                if (EventHandlerList == null)
                    return;

            }
            System.out.println("size of actionListenerList is: " + EventHandlerList.size());

            for (int i = 0; i < EventHandlerList.size(); i++) {
                EventHandler<myActionEvent> event = (EventHandler<myActionEvent>) EventHandlerList.get(i);
                System.out.println("event is: " + e.geteventType().toString());
                event.handle(e);
            }

        }

    }
import javafx.event.EventHandler;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

public class CircleView1 extends StackPane implements EventHandler<myActionEvent> {

    private CircleModel1 model;


    public CircleModel1 getModel()

    {
        return model;
    }

    public void setModel(CircleModel1 newModel) {
        model = newModel;
        if (model!=null) {
        model.addEventHandler(this);
        createViewByModel(newModel);
        }

    }

    public void createViewByModel(CircleModel1 model) {
        if (model==null) return;
        this.getChildren().clear();
        Circle circle = new Circle();
        circle.setRadius(model.getRadius());
        if (model.isFilled()) {
            circle.setFill(model.getColor());
           this.getChildren().addAll(circle);
        }

        else {
            circle.setFill(Color.TRANSPARENT);
            circle.setStroke(model.getColor());
            this.getChildren().addAll(circle);
        }
    }

    public void handle(myActionEvent event) {
        createViewByModel(model);
    }
}
import javafx.event.ActionEvent;
public class myActionEvent extends ActionEvent implements CircleEvents {

    private static final long serialVersionUID = 1L;

    private eventType type;
    public myActionEvent(ActionEvent event,eventType type) {

        this.type=type;
    }
    public eventType geteventType() {

        return type;
    }

}

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class SingleCircleMVC1 extends Application {
    private Button btController = new Button("Show Controller");
    private Button btView = new Button("Show View");
    private CircleModel1 model = new CircleModel1();

    @Override
    public void start(Stage primaryStage) {
        HBox buttons = new HBox();
        buttons.setSpacing(10);
        buttons.setPadding(new Insets(10,0,0,20));
        buttons.getChildren().addAll(btController, btView);
        primaryStage.setTitle("SingleCircleMvc1");
        primaryStage.setX(100);
        primaryStage.setY(100);
        primaryStage.setScene(new Scene(buttons, 200, 300));
        primaryStage.setResizable(false);
        primaryStage.setAlwaysOnTop(true);
        primaryStage.setHeight(100);
        primaryStage.setWidth(300);
        primaryStage.setOnCloseRequest(e -> Platform.exit());
        btController.setOnAction(e->stagePressed());
        btView.setOnAction(e->viewPressed());
        primaryStage.show();
    }
    public void stagePressed() {
        Stage ControllerStage = new Stage();
        CircleController1 controller = new CircleController1();

        ControllerStage.setOnCloseRequest(e -> {
            try {
                stop();
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        });
        controller.setModel(model);
        ControllerStage.setScene(new Scene(controller,100,100));
        ControllerStage.setTitle("Controller");
        ControllerStage.setWidth(300);
        ControllerStage.setHeight(200);
        ControllerStage.setOnCloseRequest(e->e.consume());
        ControllerStage.setResizable(false);
        ControllerStage.setX(200);
        ControllerStage.setY(200);
        ControllerStage.setAlwaysOnTop(true);
        ControllerStage.show();
    }
    public void viewPressed() {
        Stage ViewStage = new Stage();
        CircleView1 view = new CircleView1();
        view.setModel(model);
        ViewStage.setScene(new Scene(view, 200, 300));
        ViewStage.setTitle("View");
        ViewStage.setWidth(500);
        ViewStage.setHeight(250);
        ViewStage.setOnCloseRequest(e->e.consume());
        ViewStage.setX(300);
        ViewStage.setY(300);
        ViewStage.setAlwaysOnTop(true);
        ViewStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}

enter image description here

1 个答案:

答案 0 :(得分:0)

您的代码对我来说很合适:当我在半径文本字段中按Enter键时,圆圈将被指定半径的新圆所替换。

为什么要编写这么多代码来实现这一点并不是很清楚。 JavaFX properties的重点在于它们已经实现了维护监听器列表并在它们发生变化时通知它们。没有必要自己复制所有这些。 (您的代码看起来有点像1998年左右的AWT应用程序。)

这是一种更现代的“惯用语”(即用于工具包的使用方式)方法:

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.paint.Color;

public class CircleModel1 {

    private final DoubleProperty radius = new SimpleDoubleProperty(20);

    private final BooleanProperty filled = new SimpleBooleanProperty(false);

    private final ObjectProperty<Color> color = new SimpleObjectProperty<>(Color.BLACK);

    public DoubleProperty radiusProperty() {
        return radius;
    }

    public final double getRadius() {
        return radiusProperty().get();
    }

    public final void setRadius(double radius) {
        radiusProperty().set(radius);
    }

    public BooleanProperty filledProperty() {
        return filled;
    }

    public final boolean isFilled() {
        return filledProperty().get();
    }

    public final void setFilled(boolean filled) {
        filledProperty().set(filled);
    }

    public ObjectProperty<Color> colorProperty() {
        return color;
    }

    public final Color getColor() {
        return colorProperty().get();
    }

    public final void setColor(Color color) {
        colorProperty().set(color);
    }

}
import javafx.beans.binding.Bindings;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

public class CircleView1 extends StackPane {

    public CircleView1(CircleModel1 model) {
        Circle circle = new Circle();
        circle.radiusProperty().bind(model.radiusProperty());
        circle.fillProperty().bind(Bindings
                .when(model.filledProperty())
                .then(model.colorProperty())
                .otherwise(Color.TRANSPARENT)
        );
        getChildren().add(circle);
    }

}
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

public class CircleController1 extends BorderPane {

    /** Creates new form CircleController */
    public CircleController1(CircleModel1 model) {

        TextField tfRadius = new TextField(Double.toString(model.getRadius()));

        // Personally, I would never use a combo box for something that is true/false
        // Use a checkbox instead
        ComboBox<Boolean> cboFilled = new ComboBox<>();
        cboFilled.getItems().setAll(Boolean.FALSE, Boolean.TRUE);

        ColorPicker cp = new ColorPicker();

        HBox radius = new HBox(20, new Label("Radius"), tfRadius);
        HBox filled = new HBox(20, new Label("Filled"), cboFilled);
        HBox color = new HBox(20, new Label("Color"), cp);
        VBox elements = new VBox(20);
        elements.getChildren().addAll(radius, filled, color);
        setLeft(elements);

        tfRadius.setPrefWidth(150);
        cboFilled.setPrefWidth(150);
        cp.setPrefWidth(150);

        cp.valueProperty().bindBidirectional(model.colorProperty());
        cboFilled.valueProperty().bindBidirectional(model.filledProperty());

        tfRadius.setOnAction(e -> model.setRadius(Double.parseDouble(tfRadius.getText())));
        model.radiusProperty().addListener((obs, oldRadius, newRadius) -> tfRadius.setText(newRadius.toString()));
    }

}
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class SingleCircleMVC1 extends Application {
    private Button btController = new Button("Show Controller");
    private Button btView = new Button("Show View");
    private CircleModel1 model = new CircleModel1();

    @Override
    public void start(Stage primaryStage) {
        HBox buttons = new HBox();
        buttons.setSpacing(10);
        buttons.setPadding(new Insets(10, 0, 0, 20));
        buttons.getChildren().addAll(btController, btView);
        primaryStage.setTitle("SingleCircleMvc1");
        primaryStage.setX(100);
        primaryStage.setY(100);
        primaryStage.setScene(new Scene(buttons, 200, 300));
        primaryStage.setResizable(false);
        primaryStage.setAlwaysOnTop(true);
        primaryStage.setHeight(100);
        primaryStage.setWidth(300);
        primaryStage.setOnHidden(e -> Platform.exit());
        btController.setOnAction(e -> stagePressed());
        btView.setOnAction(e -> viewPressed());
        primaryStage.show();
    }

    public void stagePressed() {
        Stage controllerStage = new Stage();
        CircleController1 controller = new CircleController1(model);

        controllerStage.setOnCloseRequest(e -> Platform.exit());
        controllerStage.setScene(new Scene(controller, 100, 100));
        controllerStage.setTitle("Controller");
        controllerStage.setWidth(300);
        controllerStage.setHeight(200);
        controllerStage.setOnCloseRequest(e -> e.consume());
        controllerStage.setResizable(false);
        controllerStage.setX(200);
        controllerStage.setY(200);
        controllerStage.setAlwaysOnTop(true);
        controllerStage.show();
    }

    public void viewPressed() {
        Stage viewStage = new Stage();
        CircleView1 view = new CircleView1(model);
        viewStage.setScene(new Scene(view, 200, 300));
        viewStage.setTitle("View");
        viewStage.setWidth(500);
        viewStage.setHeight(250);
        viewStage.setOnCloseRequest(e -> e.consume());
        viewStage.setX(300);
        viewStage.setY(300);
        viewStage.setAlwaysOnTop(true);
        viewStage.show();
    }

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

}