2016-06-07 12 views
0

Ich bin neu bei javafx. Ich versuche, eine CheckBoxTableCell anzuzeigen, aber es ist immer deaktiviert, wenn ich das Datamodel ignoriere. Das ist, wie ich die Spalte zu erstellen:javafx CheckBoxTableCell immer deaktiviert

@SuppressWarnings("unchecked") 
private static <S, T> TableColumn<S, T> createTableColumn(Class<T> type, String fieldName, String index, String columnHeader) { 
    TableColumn<S, T> col = new TableColumn<S, T>(columnHeader); 
    col.setCellValueFactory(cellData -> { 
     try { 
      Object o = ReflectionUtils.getValue(fieldName, cellData.getValue()); 
      // Erzeuge eine Property, die das Attribut enthält 
      SimpleObjectProperty<T> property = new SimpleObjectProperty<T>((T) o); 
      return property; 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    }); 
    if (type.equals(Boolean.TYPE)) 
     ((TableColumn<S, Boolean>) col).setCellFactory(CheckBoxTableCell.forTableColumn((TableColumn<S, Boolean>) col)); 

    col.setId(index); 
    return col; 
} 

Ich habe in CheckBoxTableCell gesucht und gefunden, dass die factoryFunction i Transformationen bin mit zu

public static <S> Callback<TableColumn<S,Boolean>, TableCell<S,Boolean>> forTableColumn(
     final TableColumn<S, Boolean> column) { 
    return forTableColumn(null, null); 
} 

so weiß ich, warum diese Funktion nicht funktioniert, aber ich weiß nicht, Welchen Weg jetzt zu benutzen. Ich hoffe du kannst mir helfen.

Minimal ausführbares Beispiel: Mein TableGenerator:

package company.viewfx.tables; 

import java.lang.reflect.Field; 
import java.util.ArrayList; 
import java.util.Comparator; 
import java.util.List; 

import org.apache.commons.beanutils.BeanUtilsBean; 

import company.viewfx.annotations.AsTableColumn; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.collections.ObservableList; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.CheckBoxTableCell; 
import lombok.Setter; 
import lombok.extern.log4j.Log4j2; 

/** 
*   Wrapperklasse, die die Benutzung des JavaFX TableView erleichtern soll 
* @param <S> Die Klasse, die in der Tabelle dargestellt werden soll 
*/ 
@Log4j2 
public class GTableView<S> extends TableView<S> { 
    /** 
    * Enthält eine Listen von Attributen aus <S> die in der Tabelle dargestellt werden sollen (optional) 
    */ 
    @Setter 
    private String[] attributes = new String[0]; 
    /** 
    * Die Klasse die dargestellt werden soll 
    */ 
    private Class<S> clazz; 

    /** 
    * @param clazz Die Klasse die dargestellt werden soll 
    * @param items eine ObservableList<S> von Datenelementen 
    */ 
    public GTableView(Class<S> clazz, ObservableList<S> items) { 
     super(items); 
     this.clazz = clazz; 
     initialize(); 
    } 

    /** 
    * Fügt die Spalten + Überschrift und Inhalt zu der rohen Tabelle hinzu 
    */ 
    private void initialize() { 
     getColumns().addAll(process(attributes, "", "", this.clazz)); 
     // Spalten nach Id sortieren 
     getColumns().sort(new Comparator<TableColumn<S, ?>>() { 
      @Override 
      public int compare(TableColumn<S, ?> o1, TableColumn<S, ?> o2) { 
       return o1.getId().compareTo(o2.getId()); 
      } 
     }); 
    } 

    /** 
    * Process the model class. 
    * For the fields declared which have annotation AsTableColumn, create a TableColumn<T,S> 
    * instance for it with the detected field type. 
    * 
    * @param attrList Eine Liste mit Attributen die angezeigt werden sollen (kann auch null sein, dann standard) 
    * @param containerName Entscheidet in welchem Komplexen Attribut nach den Spalten gesucht wird 
    * @param containerIndex Der index des entsprechenden Wurzelobjektes 
    * @param clazz Die Klasse des Attributes, das in dieser Spalte dargestellt werden soll 
    * @return Eine Listen von TableColumns für die mit @AsColumn in this.clazz markierten Attribute 
    */ 
    public static <S> List<TableColumn<S, ? extends Object>> process(String[] attrList, String containerName, String containerIndex, 
      Class<?> clazz) { 
     // Der Rückgabenwert 
     List<TableColumn<S, ? extends Object>> columns = new ArrayList<>(); 
     // Wenn der Index nicht leer ist hänge einen Punkt an 
     containerIndex += !containerIndex.equals("") ? "." : ""; 
     // Wenn der ContainerName nicht leer ist hänge einen Punkt an 
     containerName += !containerName.equals("") ? "." : ""; 
     // Wenn die StandardSpalten verwendet werden sollen 
     if (attrList.length == 0) { 
      // gehe erst alle Felder durch 
      for (Field field : clazz.getDeclaredFields()) { 
       // Wenn das Attribut als Feld angezeigt werden soll 
       if (field.isAnnotationPresent(AsTableColumn.class)) { 
        AsTableColumn anno = field.getAnnotation(AsTableColumn.class); 
        columns.add(createTableColumn(field.getType(), containerName + field.getName(), containerIndex + anno.index(), 
          anno.text())); 
       } 
      } 
     } 
     return columns; 
    } 

    /** 
    * @param type Der Typ des Attributes, das in der Spalte stehen soll 
    * @param fieldName Das Attribut, das in dieser Spalte dargestellt werden soll 
    * @param columnHeader Die Spaltenüberschrift 
    * @param index Der index der Spalte (entscheidet über ihre Reihenfolge) 
    * @return TableColumn 
    */ 
    // Das ist hier erlaubt da immer eine Typprüfung mit type.equals durchgeführt wird 
    @SuppressWarnings("unchecked") 
    private static <S, T> TableColumn<S, T> createTableColumn(Class<T> type, String fieldName, String index, String columnHeader) { 
     TableColumn<S, T> col = new TableColumn<S, T>(columnHeader); 
     col.setCellValueFactory(cellData -> { 
      try { 
       Object o = null; 
       try { 
        o = BeanUtilsBean.getInstance().getPropertyUtils().getNestedProperty(o, fieldName); 
       } catch (Exception e) { 
        log.warn(String.format("Can not reach attribute %s in %s", fieldName, cellData.getValue()), e); 
       } 
       // Erzeuge eine Property, die das Attribut enthält 
       SimpleObjectProperty<T> property = new SimpleObjectProperty<T>((T) o); 
       return property; 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     }); 
     if (type.equals(Boolean.TYPE)) 
      ((TableColumn<S, Boolean>) col).setCellFactory(CheckBoxTableCell.forTableColumn((TableColumn<S, Boolean>) col)); 
     col.setId(index); 
     return col; 
    } 
} 

Die Annotation

package company.viewfx.annotations; 

import java.lang.annotation.Retention; 
import java.lang.annotation.Target; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.RetentionPolicy; 

    @Retention(RetentionPolicy.RUNTIME) 
    @Target({ElementType.FIELD,ElementType.METHOD}) 
    /** 
    * Mit dieser Annotation markierte Attribute werden in GTableView automatisch angezeigt, sofern keine anders lautenden 
    * Parameter übergeben werden. 
    * 
    */ 
    public @interface AsTableColumn { 
     /** 
     * @return Die Überschrift, die im Spaltenkopf angezeigt werden soll 
     */ 
     String text() default ""; 

     /** 
     * @return Die Stelle an der Die Spalte stehen soll 
     */ 
     int index() default Integer.MAX_VALUE; 
    } 

TestDataModel:

package company.viewfx.tables.demo; 

import company.viewfx.annotations.AsTableColumn; 
import lombok.AllArgsConstructor; 
import lombok.Getter; 
import lombok.Setter; 

@SuppressWarnings("javadoc") 
@AllArgsConstructor 
public class Person { 
@Getter 
@Setter 
@AsTableColumn(index=1,text="Alive") 
private boolean alive; 
} 

Testapplication:

package company.viewfx.tables.demo; 

import company.viewfx.tables.GTableView; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

/** 
*   Dient der Vorführung dem Test von GTabelView 
*/ 
public class TableTest extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     // initialize Testdata 
     ObservableList<Person> data = FXCollections.observableArrayList(
       new Person(true), 
       new Person(false)); 
     stage.setScene(new Scene(new GTableView<Person>(Person.class, data))); 
     stage.show(); 
    } 

    @SuppressWarnings("javadoc") 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

build.gradle

apply plugin: 'java' 

// In this section you declare where to find the dependencies of your project 
repositories { 
    jcenter() 
} 

configurations { 
    provided { 
     dependencies.all { dep -> 
      configurations.default.exclude group: dep.group, module: dep.name 
     } 
    } 
    compile.extendsFrom provided 
} 

// In this section you declare the dependencies for your production and test code 
dependencies { 
    compile 'org.slf4j:slf4j-api:1.7.12' 
    provided 'org.projectlombok:lombok:1.12.6' 
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6' 
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6' 
    compile group: 'commons-beanutils', name: 'commons-beanutils', version: '1.8.3' 
    compile 'org.apache.commons:commons-lang3:3.4' 
    compile group: 'org.springframework', name: 'spring-core', version: '2.5.6' 
    compile group: 'org.eclipse.osgi', name: 'org.eclipse.osgi', version: '3.7.1' 
    testCompile 'junit:junit:4.12' 
} 
+0

Ihre Zellenwertfactory erstellt bei jedem Aufruf eine neue 'ObjectProperty'. Wenn Sie den Wert im Datenmodell ändern, wird der Wert dieser Objekteigenschaft nicht geändert. Sie benötigen die Zellenwertfactory, um auf die im Modell direkt definierte "ObjectProperty" zu verweisen. –

+0

@James_D das ist kein Problem für mich jedes Mal, wenn die Daten ändert es aus der Datenbank abgerufen und vollständig ersetzt, aber es wird nie geändert werden. Auch für meine neu definierte ObjectProperty sollte das Kontrollkästchen aktiviert sein oder ich vermisse etwas. –

+1

[Bearbeiten] Ihre Frage zu einem [MCVE] –

Antwort

0

FXML Benutzer verwenden diese als zusätzliche Spalte ein Kontrollkästchen zu machen.

<TableColumn text="Married" fx:id="married"> 
<cellValueFactory> 
    <PropertyValueFactory property="married" /> 
</cellValueFactory> 
</TableColumn> 
<fx:script> 
var myCellValue = javafx.scene.control.cell.CheckBoxTableCell.forTableColumn(married); 
married.setCellFactory(myCellValue); 
</fx:script> 

//Your data model should be exposed as below. 
private final SimpleBooleanProperty married = new SimpleBooleanProperty(false); 
public SimpleBooleanProperty marriedProperty(){ 
    return married; 
} 
Verwandte Themen