0
javafx를 처음 사용합니다. CheckBoxTableCell을 표시하려고하지만 항상 Datamodel을 무시하고 선택을 취소합니다.javafx CheckBoxTableCell은 항상 선택 취소되었습니다.
@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에 보니
public static <S> Callback<TableColumn<S,Boolean>, TableCell<S,Boolean>> forTableColumn(
final TableColumn<S, Boolean> column) {
return forTableColumn(null, null);
}
에 내가 변환을 사용하고있는 factoryFunction 그래서 난이 기능이 작동하지 않는 이유를 알고하지만 난 잘 모릅니다 것으로 나타났습니다 : 그건 내가 열을 생성하는 방법이다 어떤 방법으로 지금 사용하십시오. 도와 주시면 감사하겠습니다.
최소한의 실행 예 : 내 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'
}
셀 값 팩토리가 호출 될 때마다 새로운'ObjectProperty'가 생성됩니다. 데이터 모델의 값을 변경하면 해당 객체 속성 값이 변경되지 않습니다. 모델에 직접 정의 된'ObjectProperty'를 참조하려면 셀 값 팩토리가 필요합니다. –
@James_D 데이터가 변경 될 때마다 나에게 아무런 문제가되지 않으며 DB에서 검색되어 완전히 대체되지만 변경되지 않습니다. 새 정의 된 ObjectProperty에 대해서도 확인란이 선택되어 표시되거나 누락되었습니다. –
귀하의 질문에 [MCVE] –