zoukankan      html  css  js  c++  java
  • JavaFx2.0Binding

    1.首先阅读文档,了解Javafx2.0中的属性和绑定:Using JavaFX Properties and Binding

    2.简单总结:

    (1)JavaBean不再是以前的pojo了,Javafx添加了一系列的封装类,进一步封装了Java中的基本类型的封装类,使得它可以被绑定或者绑定,也就是它实现了Observable接口,具体请看API。

    (2)上面的以Simple开头的是相应的property的简单实现类,所以在类(Javabean)中一般是使用初始化为simple...

    (3)property都有一些方法用于绑定特定的对象,例如,绑定其他的property,或者其他的property组合而成的,例如,StringProperty

    (4)除了使用bind方法绑定其他的property之外,它还可以添加listener,比如,当这个属性发生变化的时候就可以通知给其他的对象!

    下面显示了StringProperty的实现的接口

    3.实践

    编写一个JavaBean,符合JavaFx2.0的规范

    LightButton.java

    package light;
    
    import util.ProtocolUtil;
    import javafx.beans.property.IntegerProperty;
    import javafx.beans.property.SimpleIntegerProperty;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    
    public class LightButton {
    
        private IntegerProperty id = new SimpleIntegerProperty();// init here
    
        private StringProperty name = new SimpleStringProperty();
    
        private IntegerProperty state = new SimpleIntegerProperty(ProtocolUtil.STATE_OFF);
    
    //    public LightButton(){//可以没有
    //        
    //    }
    
        public LightButton(int id, String name) {
            setId(id);
            setName(name);
        }
    
        public void setState(int value) {
            state.set(value);
        }
    
        public int getState() {
            return state.get();
        }
    
        public IntegerProperty stateProperty() {
            return state;
        }
    
        public void setId(int value) {
            id.set(value);
        }
    
        public int getId() {
            return id.get();
        }
    
        public IntegerProperty idProperty() {
            return id;
        }
    
        public void setName(String value) {
            name.set(value);
        }
    
        public String getName() {
            return name.get();
        }
    
        public StringProperty nameProperty() {
            return name;
        }
    
    }

    LightView.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.geometry.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.effect.*?>
    <?import javafx.scene.image.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.paint.*?>
    <?import javafx.scene.text.*?>
    <?import light.Light?>
    
    <AnchorPane id="AnchorPane" fx:id="lightAnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="150.0" prefWidth="150.0" xmlns:fx="http://javafx.com/fxml" fx:controller="light.LightViewController">
      <children>
        <StackPane id="StackPane" fx:id="lightStackPane" onMouseEntered="#handleShowButtons" onMouseExited="#handleHideButtons" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
          <children>
            <ImageView fx:id="lightImageView" onMouseClicked="#handleLight" style="-fx-cursor:hand;" StackPane.alignment="TOP_CENTER">
              <effect>
                <Reflection bottomOpacity="0.2" fraction="0.5" />
              </effect>
              <image>
                <Image url="@light_off.png" preserveRatio="true" smooth="true" />
              </image>
              <StackPane.margin>
                <Insets top="20.0" />
              </StackPane.margin>
            </ImageView>
            <Text id="text1" fx:id="textLightName" boundsType="VISUAL" scaleX="1.3438942202036481" scaleY="1.5467894807101856" stroke="#0c9900" strokeLineCap="ROUND" strokeLineJoin="ROUND" text="LightName" StackPane.alignment="TOP_CENTER">
              <effect>
                <Reflection bottomOpacity="0.2" fraction="0.6" />
              </effect>
              <StackPane.margin>
                <Insets top="120.0" />
              </StackPane.margin>
            </Text>
            <Button fx:id="btnOpen" alignment="CENTER" contentDisplay="CENTER" defaultButton="true" onAction="#handleOpenLight" text="*Open" StackPane.alignment="CENTER_LEFT">
              <StackPane.margin>
                <Insets left="4.0" />
              </StackPane.margin>
            </Button>
            <Button fx:id="btnClose" onAction="#handleCloseLight" text="*Close" StackPane.alignment="CENTER_RIGHT">
              <StackPane.margin>
                <Insets right="4.0" />
              </StackPane.margin>
            </Button>
          </children>
        </StackPane>
      </children>
    </AnchorPane>

    LightViewController.java

    package light;
    
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ResourceBundle;
    
    import util.ProtocolUtil;
    
    import javafx.animation.FadeTransition;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.AnchorPane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.text.Text;
    import javafx.util.Duration;
    import app.AppControllers2;
    
    public class LightViewController implements Initializable {
    
        private LightButton lightButton;
    
        private Image lightOnImage;
        private Image lightOffImage;
    
        @FXML
        private AnchorPane lightAnchorPane;
        @FXML
        private StackPane lightStackPane;
        @FXML
        private ImageView lightImageView;
        @FXML
        private Button btnOpen;
        @FXML
        private Button btnClose;
        @FXML
        private Text textLightName;
    
        private List<Button> buttons = new ArrayList<Button>();
    
        @Override
        public void initialize(URL arg0, ResourceBundle arg1) {
            lightOnImage = new Image(getClass().getResourceAsStream("light_on.png"));
            lightOffImage = new Image(getClass().getResourceAsStream("light_off.png"));
            lightButton = AppControllers2.getNewLightButton();
            changeImage();
            textLightName.setText(lightButton.getName());
    //        lightButton.nameProperty().bind(textLightName.textProperty());//(1)fails!
            // java.lang.RuntimeException: A bound value cannot be set.
    //        textLightName.textProperty().bind(lightButton.nameProperty());//(2)ok
    
            textLightName.textProperty().bindBidirectional(lightButton.nameProperty());// (3)ok
            lightButton.nameProperty().bindBidirectional(textLightName.textProperty());// (4)ok
            // (3)+(4) ok
    //        lightButton.nameProperty().bind(textLightName.textProperty());//(1)+(2) fails
            // can not do this!StackOverflowError
            lightButton.stateProperty().addListener(new ChangeListener<Number>() {
                public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                    changeImage();
                }
            });
            buttons.add(btnOpen);
            buttons.add(btnClose);
            handleHideButtons(null);
        }
    
        private void changeImage() {
            if (lightButton.getState() == ProtocolUtil.STATE_OFF) {
                lightImageView.setImage(lightOffImage);
            } else {
                lightImageView.setImage(lightOnImage);
            }
        }
    
        @FXML
        private void handleOpenLight(ActionEvent event) {
            System.out.println("handle open");
            lightButton.setName("open");
            lightButton.setState(ProtocolUtil.STATE_ON);
        }
    
        @FXML
        private void handleCloseLight(ActionEvent event) {
            System.out.println("handle close");
            lightButton.setName("close");
            lightButton.setState(ProtocolUtil.STATE_OFF);
        }
    
        @FXML
        private void handleLight(MouseEvent event) {
            System.out.println("handle light");
            lightButton.setName("name");
            lightButton.setState(1 - lightButton.getState());
        }
    
        @FXML
        private void handleShowButtons(MouseEvent me) {
            System.out.println("handle show buttons");
            for (Button button : buttons) {
                FadeTransition f = new FadeTransition(Duration.millis(250), button);
                f.setFromValue(0.2);
                f.setToValue(0.8);
                f.play();
            }
        }
    
        @FXML
        // TODO:bug here!if the mouse moves very fast,the buttons will not disappear!
        private void handleHideButtons(MouseEvent me) {
            System.out.println("handle hide buttons");
            for (Button button : buttons) {
                button.setOpacity(0);
            }
        }
    
    }

    然后用FXMLLoader加载fxml文件,显示在stage中,即可看到效果:

    文字会发生变化,图片也会发生变化!其中文字使用的是bind,而图片使用的是addListener

    注意:请注意Controller类中的注释代码,这个很重要,绑定是有方向性的,一般是UI控件的值绑定到了bean的某个属性对象上。

    并且要注意,不要以为 a.bind(b) 再加上 b.bind(a) 就可以是想双向绑定,这个是错误的,会发生栈溢出错误!例如(1)+(2)

    代码片段反映了不同的情况下的情况,注意两个不同的方法:bind 和 bindBidirectional 方法,后者是由StringProperty提供的,可以实现双向绑定(貌似是,没有看过源码)

    所以,使用(3)和使用(4)是一样的,写上一个就可以了。

    4.但是,实际开发中,我们的bean对象中不仅仅只是int,float,double,string等等这些基本类型吧!那如果是一些比较复杂的Java类怎么进行绑定呢?

    仔细查看API,不能发现还有一个ObjectProperty,它对应一个简单的实现类SimpleObjectProperty,看看它怎么使用吧,其实和其他的XXXProperty是一样的

    下面是一个例子:目的是让rectangle的color和bill中的color属性一致!

    package demo;
    
    import javafx.beans.InvalidationListener;
    import javafx.beans.Observable;
    import javafx.beans.binding.Bindings;
    import javafx.beans.binding.NumberBinding;
    import javafx.beans.property.DoubleProperty;
    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.beans.property.SimpleObjectProperty;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Rectangle;
    
    public class BindingDemo {
    
        public static void main(String[] args) {
            Bill bill1 = new Bill();
            Bill bill2 = new Bill();
    
            NumberBinding total = Bindings.add(bill1.dpProperty(), bill2.dpProperty());
            total.addListener(new InvalidationListener() {
                public void invalidated(Observable arg0) {
                    System.out.println("now invalid!");
                }
            });
    
            bill1.setDp(12);//valid->invalid
    //        System.out.println(total.getValue());// (1)//invalid->valid
            bill2.setDp(13);//valid->invalid
            System.out.println(total.getValue());// (2)//invalid->valid
    
            // if (1)+(2)
    //        now invalid!
    //        12.0
    //        now invalid!
    //        25.0
            
            //if (1) commented
    //        now invalid!
    //        25.0
    
            Rectangle rectangle = new Rectangle(20, 20, Color.RED);
            System.out.println(rectangle.getFill());// Color[red=255,green=0,blue=0,opacity=1.0]
            rectangle.fillProperty().bind(bill1.colorProperty());
            bill1.setColor(Color.GREEN);
            System.out.println(rectangle.getFill());// Color[red=0,green=128,blue=0,opacity=1.0]
    
            // ChangeListener<Object> right and ChangeListener<Color> wrong
    //        rectangle.fillProperty().addListener(new ChangeListener<Object>() {
    //            public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
    //                //when the rectangle color changes,this method will be invoked
    //            }
    //        });
        }
    
    }
    
    class Bill {
    
        private DoubleProperty dp = new SimpleDoubleProperty();
        private ObjectProperty<Color> color = new SimpleObjectProperty<Color>();
    
        public final Color getColor() {
            return color.get();
        }
    
        public final void setColor(Color color) {
            this.color.set(color);
        }
    
        public ObjectProperty<Color> colorProperty() {
            return color;
        }
    
        public final double getDp() {
            return dp.get();
        }
    
        public final void setDp(double dp) {
            this.dp.set(dp);
        }
    
        public DoubleProperty dpProperty() {
            return dp;
        }
    
    }
  • 相关阅读:
    Kali 2020.3安装docker和vulhub
    Web渗透——身份管理测试
    Web渗透——配置管理测试
    网站信息收集
    linux修改MAC的方法
    '文件上传总结'
    美杜莎和九头蛇的对比
    渗透测试常见开放端口及利用
    Google hacking 语法
    web渗透测试基本步骤
  • 原文地址:https://www.cnblogs.com/yinger/p/2459803.html
Copyright © 2011-2022 走看看