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'
}
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. –
@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. –
[Bearbeiten] Ihre Frage zu einem [MCVE] –