我是javafx的新手。我尝试显示一个CheckBoxTableCell但它总是未经检查忽略Datamodel。这就是我创建列的方式:
@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;
}
我查看了CheckBoxTableCell并发现我正在使用的factoryFunction转换为
public static <S> Callback<TableColumn<S,Boolean>, TableCell<S,Boolean>> forTableColumn(
final TableColumn<S, Boolean> column) {
return forTableColumn(null, null);
}
所以我知道为什么这个功能不起作用,但我不知道现在使用哪种方式。 我希望你能帮助我。
最小的可执行示例: 我的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;
}
}
注释
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 :(得分:0)
FXML用户将此作为附加列来呈现复选框。
>>> res
{(3, 4, 6), (3, 8, 10), (1, 2, 8), (2, 6, 9), (3, 4, 7), (1, 2, 9), (4, 6, 9), (2, 6, 8), (1, 8, 9), (4, 6, 8), (1, 4, 6), (3, 6, 8), (4, 8, 10), (3, 6, 9), (1, 6, 8), (4, 6, 10), (4, 8, 9), (1, 6, 9), (3, 9, 10), (1, 3, 4), (2, 8, 9), (4, 7, 8), (2, 7, 8), (1, 3, 9), (2, 4, 7), (3, 4, 8), (2, 7, 9), (1, 3, 8), (2, 4, 6), (2, 8, 10), (3, 4, 9), (2, 7, 10), (3, 4, 10), (1, 2, 4), (2, 3, 4), (2, 9, 10), (2, 3, 8), (2, 4, 9), (2, 3, 9), (3, 7, 9), (2, 4, 10), (2, 4, 8), (1, 4, 8), (3, 7, 8), (1, 7, 8), (3, 8, 9), (1, 8, 10), (3, 7, 10), (4, 6, 7)}