1

错误:类型不匹配:无法从 转换SimpleStringPropertyObservableValue<Object>

我正在尝试创建一个包含管理各种数据类型的列的 TreeTableView。这意味着每一行可以使用三种左右的数据类型之一(StringintStringPropertyObjectProperty< LocalDate >.

鉴于我的数据类型是“对象”,那么setCellValueFactory( cellDataFeatures -> { return ...; })需要一个ObservableValue< Object >. 我在尝试从 CellValueFactory 回调的属性中获取所需的 ObservableValue 时不知所措。:(

这篇文章建议使用 aReadOnlyStringWrapper但我想保持可编辑的值(在大多数情况下)。我还找到了对#asObject()StringProperty 中不可用的方法的建议。

        /*-------------------------+------------+ 
         | columnPeople            | columnData |
         +-------------------------+------------+ 
         |                         |            |
         | + Bob Rozz ============ | 33 ======= |
         |   + SKILLS              |            |
         |     + testskill 1       | 0.7        |
         |                         | 3/14/2017  |
         |     + testskill 2       |            |
         |                         | 0.9        |
         |                         | 3/11/2017  |
         |                         |            |
         | + Bob Dilly =========== | 34 ======= |
         |   + SKILLS              |            |
         |     + testskill 1       | 0.6        |
         |                         | 3/10/2017  |
         |     + testskill 2       |            |
         |                         | 0.5        |
         |                         | 3/17/2017  |
         +-------------------------+------------+ 
        */

注意1:尚未解决setCellFactory(...)

注2:如前所述,我意识到这个例子是不切实际的。作为所需功能的示例,它与我的项目完全分开。

package testGenericTableTreeColumn;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javafx.application.Platform;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TextFieldTreeTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Pair;
import javafx.util.converter.DefaultStringConverter;



public class testGenericTableTreeColumn extends javafx.application.Application {

    class Skill {

        private StringProperty        name = new SimpleStringProperty( "" );
        public  final String          getName(){ return this.name.get();         }
        public  final void            setName( String v ){ name.set(v); return;  }
        public  StringProperty        nameProperty(){ return this.name;          }

        private SimpleFloatProperty   value = new SimpleFloatProperty( 0f );
        public  final String          getValue(){ return this.name.get();        }
        public  final void            setValue( String v ){ name.set(v); return; }
        public  StringProperty        valueProperty(){ return this.name;         }

        private SimpleObjectProperty< LocalDate > date = new SimpleObjectProperty< LocalDate >( LocalDate.now() );//LocalDate date  = LocalDate.now();
        public  final String          getDate(){ return this.name.get();         }
        public  final void            setDate( String v ){ name.set(v); return;  }
        public  StringProperty        dateProperty(){ return this.name;          }

        public Skill( String name ){
            java.util.Random r = new java.util.Random();
            this.name  .set( name );                        //this.name  = name;
            this.value .set( 100 * ( r.nextFloat() ));      //this.value = 100 * ( r.nextFloat() );
            this.date  .get().minusWeeks( r.nextInt(10) );  //date.minusWeeks( r.nextInt(10) );
            return;
        }
    }
    class Person {

        private StringProperty  name = new SimpleStringProperty( "" );
        public final String     getName()          { return this.name.get(); }
        public final void       setName( String v ){ name.set(v); return;    }
        public StringProperty   nameProperty()     { return this.name;       }

        private IntegerProperty age = new SimpleIntegerProperty( 0 );
        public final int        getAge()           { return this.age.get();  }
        public final void       setAge( int v )    { age.set(v); return;     }
        public IntegerProperty  ageProperty()      { return this.age;        }

        public  List< Skill >   skills = new ArrayList<>();

        public Person( String name, int age ){
            this.name .set( name );
            this.age  .set( age  );
            skills.add( new Skill( "testskill 1" ));
            skills.add( new Skill( "testskill 2" ));
            return;
        }
    }

    public TreeTableView< Pair< Object, Object >> table = new TreeTableView<>();

    @Override public void start( Stage primaryStage ){

        TreeItem< Pair< Object, Object >> itemRoot = new TreeItem<>( new Pair<>( "PEOPLE", null ));
        this.table.setRoot( itemRoot );

        Person person1 = new Person( "Bob Rozz"  ,33 );
        Person person2 = new Person( "Bob Dilly" ,34 );

        List< Person > people = new ArrayList<>();
        people.add( person1 );
        people.add( person2 );

        /*-------------------------+------------+ 
         | columnPeople            | columnData |
         +-------------------------+------------+ 
         |                         |            |
         | + Bob Rozz ============ | 33 ======= |
         |   + SKILLS              |            |
         |     + testskill 1       | 0.7        |
         |                         | 3/14/2017  |
         |     + testskill 2       |            |
         |                         | 0.9        |
         |                         | 3/11/2017  |
         |                         |            |
         | + Bob Dilly =========== | 34 ======= |
         |   + SKILLS              |            |
         |     + testskill 1       | 0.6        |
         |                         | 3/10/2017  |
         |     + testskill 2       |            |
         |                         | 0.5        |
         |                         | 3/17/2017  |
         +-------------------------+------------+ 
        */

        for ( Person person : people ){

            TreeItem< Pair< Object, Object >> treeItemPerson = new TreeItem<>( new Pair< Object, Object >( person.nameProperty(), person.ageProperty() ));
            TreeItem< Pair< Object, Object >> treeItemSkills = new TreeItem<>( new Pair< Object, Object >( "Skills"             , null ));

            itemRoot       .getChildren().add( treeItemPerson );
            treeItemPerson .getChildren().add( treeItemSkills );

            for ( Skill skill : person.skills ){

                TreeItem< Pair< Object, Object >> treeItemSkillName  = new TreeItem<>( new Pair< Object, Object >( null, skill.nameProperty  () ));
                TreeItem< Pair< Object, Object >> treeItemSkillValue = new TreeItem<>( new Pair< Object, Object >( null, skill.valueProperty () ));
                TreeItem< Pair< Object, Object >> treeItemSkillDate  = new TreeItem<>( new Pair< Object, Object >( null, skill.dateProperty  () ));

                treeItemSkills    .getChildren().add( treeItemSkillName  );
                treeItemSkillName .getChildren().add( treeItemSkillDate  );
                treeItemSkillName .getChildren().add( treeItemSkillValue );
            }
        }

        TreeTableColumn< Pair< Object, Object>, String > colName = new TreeTableColumn<>("People"); colName.setMinWidth(100);
        colName.setCellValueFactory( cellDataFeatures -> {

            // Could be a String, StringProperty, or ObjectProperty< LocalDate >
            Object item   = cellDataFeatures.getValue().getValue().getKey();

            //String
            if ( item instanceof String ){
                /* ERROR */ return ( String ) item; //ERROR: Type mismatch: cannot convert from SimpleStringProperty to ObservableValue< Object >
            }

            //StringProperty
            if ( item instanceof StringProperty ){
                /* ERROR */ return (( StringProperty ) item ); //ERROR: Type mismatch: cannot convert from SimpleStringProperty to ObservableValue< Object >
            }
        });

        TreeTableColumn< Pair< Object, Object>, Object > colData = new TreeTableColumn<>("Skills"); colData.setMinWidth(200);
        colData.setCellValueFactory( cellDataFeatures -> {

            //itemKey : Could be a String, IntegerProperty, StringProperty, or ObjectProperty< LocalDate >
            Object item = cellDataFeatures.getValue().getValue().getValue();

            //String
            if ( item instanceof String ){
                /* ERROR */ return (String) item; //ERROR: Type mismatch: cannot convert from SimpleStringProperty to ObservableValue< Object >
            }

            //IntegerProperty
            if ( item instanceof IntegerProperty ){
                /* ERROR */ return (( IntegerProperty ) item ); //ERROR: Type mismatch: cannot convert from SimpleIntegerProperty to ObservableValue< Object >
            }

            //StringProperty
            if ( item instanceof StringProperty ){
                /* ERROR */ return (( StringProperty ) item ); //ERROR: Type mismatch: cannot convert from SimpleStringProperty to ObservableValue< Object >
            }

            //ObjectProperty< LocalDate >
            if ( item instanceof ObjectProperty< ? >){
                Object value = (( ObjectProperty<?> ) item ).getBean();
                if ( value instanceof LocalDate ){
                    //@TODO LocalDate cell
                }
            }
        });

        /*
        //colData.setCellFactory( new Callback< TreeTableColumn< Person, Object >, TreeTableCell< Person, Object >>());
        colData.setCellFactory( column -> {

            TreeTableCell< Object, Object > cell = new TreeTableCell< Object, Object >(){
                @Override protected void updateItem( Object newValue, boolean empty ){

                    this.setEditable( false );

                    super.updateItem( newValue, empty );
                    if ( empty || newValue == null ){
                        setText    ( null );
                        setGraphic ( null );
                        return;
                    }

                    if ( newValue instanceof String ){
                        return;
                    }

                    this.setEditable( true );

                    if ( newValue instanceof LocalDate ){
                        return;
                    }

                    return;
                }   // updateItem( ... );
            };
        });
        // */

        // Type safety: A generic array of Table... is created for a varargs
        // parameter
        // -> @SuppressWarnings("unchecked") to start method!
        table.getColumns().addAll( colName, colData );

        // Output in console the selected table view's cell value/class to check
        // that the data type is correct.
        //  SystemOutTreeTableViewSelectedCell.set(tableView);
        /*
        // To check that table view is correctly refreshed on data changed..
        final Button agePlusOneButton = new Button("Age +1");
        agePlusOneButton.setOnAction((ActionEvent e) -> {
            Person<?> person = tableView.getSelectionModel().getSelectedItem();
            try {
                person.setAge(person.getAge() + 1);
            } catch (NullPointerException npe ){
                //
            }
        });
        */

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll( table );

        Scene scene = new Scene(new Group());
        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        primaryStage.setWidth(600);
        primaryStage.setHeight(750);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

错误:

Description Resource    Path    Location    Type
Type mismatch: cannot convert from IntegerProperty to ObservableValue<Object>   testGenericTableTreeColumn.java /testGenericTableTreeColumn/src/testGenericTableTreeColumn  line 300    Java Problem
Type mismatch: cannot convert from String to ObservableValue<Object>    testGenericTableTreeColumn.java /testGenericTableTreeColumn/src/testGenericTableTreeColumn  line 295    Java Problem
Type mismatch: cannot convert from String to ObservableValue<String>    testGenericTableTreeColumn.java /testGenericTableTreeColumn/src/testGenericTableTreeColumn  line 278    Java Problem
Type mismatch: cannot convert from StringProperty to ObservableValue<Object>    testGenericTableTreeColumn.java /testGenericTableTreeColumn/src/testGenericTableTreeColumn  line 305    Java Problem

Java版本:

java version "1.8.0_121" Java(TM)
SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
4

1 回答 1

2

对于 a TreeTableColumn<S,T>cellValueFactory具有类型Callback<CellDataFeatures<S,T>, ObservableValue<S,T>>,它本质上是一个函数,它接受一个 的实例CellDataFeatures<S,T>并返回一个ObservableValue<S,T>

colName是一个TreeTableColumn<Pair<Object, Object>, String>,所以SPair<Object, Object>TString。所以cellValueFactoryforcolName是一个函数,CellDataFeatures<Pair<Object, Object>>它接受一个实例(你称之为cellDataFeatures)并返回一个ObservableValue<String>.

您的实施存在多个问题。首先是 if item,它被声明为 an Object,不是Stringor的一个实例StringProperty,那么代码实际上永远不会到达一个return语句。所以这甚至不是一个有效的 lambda 表达式。

第二个问题是 ifitem是一个String实例(第一条if语句),你返回 a String,它不是 a ObservableValue<String>,所以你返回了错误的类型。

因此,至少可以编译的实现是

    TreeTableColumn< Pair< Object, Object>, String > colName = new TreeTableColumn<>("People"); colName.setMinWidth(100);
    colName.setCellValueFactory( cellDataFeatures -> {

        // Could be a String, StringProperty, or ObjectProperty< LocalDate >
        Object item   = cellDataFeatures.getValue().getValue().getKey();

        //String
        if ( item instanceof String ){
            return new SimpleStringProperty(( String ) item); 
        }

        //StringProperty
        if ( item instanceof StringProperty ){
            return (( StringProperty ) item ); 
        }

        // must return something: you probably don't want to return null though, so you should fix this as needed.
        return null ;
    });

同样,对于 for colData,您的代码路径永远不会到达 return 语句,因此您没有定义有效的 lambda 表达式。在这种情况下,colData是 a TreeTableColumn<Pair<Object, Object>, Object>,所以TObject,并且返回类型必须是ObservableValue<Object>。您的各种if块尝试返回String, IntegerProperty, StringProperty, (或待确定的内容),但这些都不是ObservableValue<Object>.

实际编译的实现是

    TreeTableColumn< Pair< Object, Object>, Object > colData = new TreeTableColumn<>("Skills"); colData.setMinWidth(200);
    colData.setCellValueFactory( cellDataFeatures -> {

        //itemKey : Could be a String, IntegerProperty, StringProperty, or ObjectProperty< LocalDate >
        Object item = cellDataFeatures.getValue().getValue().getValue();

        //String
        if ( item instanceof String ){
            return new SimpleObjectProperty<>( item ); 
        }

        //IntegerProperty
        if ( item instanceof IntegerProperty ){
            return new SimpleObjectProperty<>(((IntegerProperty) item).getValue()); 
        }

        //StringProperty
        if ( item instanceof StringProperty ){
            return new SimpleObjectProperty<>(((IntegerProperty) item).getValue()); 
        }

        //ObjectProperty< LocalDate >
        if ( item instanceof ObjectProperty< ? >){
            Object value = (( ObjectProperty<?> ) item ).getBean();
            if ( value instanceof LocalDate ){
                //@TODO LocalDate cell
            }
        }

        // TODO return something appropriate here
        return null ;
    });
于 2017-03-22T13:14:11.990 回答