TableView
とその項目に問題があります。 Dialog
私のアプリケーションに関する警告を表示する小さなウィンドウを作成しました。Dialog
には、警告の名前とボタンをクリックするとその情報が表示されるTableView
があります。JavaFX:ダイアログ内のTableViewに重複した項目があります
Dialog
を開く/閉じるだけで、WarningUtil
クラス(Singleton
パターン)を作成しました。関連するコードは次のとおりです。
(一度だけ呼ばれる)WarningUtil
クラスのコンストラクタ:
private WarningUtil(RootCtrl rootCtrl) {
this.rootCtrl = rootCtrl;
warnings = new HashMap<>();
setupWarningCallbacks(); // not relevant
setupTable();
setupColumns(); // not relevant
setupDialog();
}
Dialog
の建設を管理する機能:
private void setupTable() {
// create the content pane
content = new AnchorPane(); // class variable - reference needed for further uses
content.setPrefSize(480, 240);
// create the root nodes of the view (table + 2 columns)
warningTable = new TableView<>(); // class variable - reference needed for further uses
warnDescriptionCol = new PTableColumn<>(); // class variable - reference needed for further uses
warnDetailsCol = new PTableColumn<>(); // class variable - reference needed for further uses
// settings anchors to keep the ration between dialog <-> table
AnchorPane.setBottomAnchor(warningTable, 15.0);
AnchorPane.setTopAnchor(warningTable, 15.0);
AnchorPane.setLeftAnchor(warningTable, 15.0);
AnchorPane.setRightAnchor(warningTable, 15.0);
// setting up the columns
warnDescriptionCol.setText(i18n("label.desc"));
warnDetailsCol.setText(i18n("label.details"));
warnDescriptionCol.setPercentageWidth(0.7);
warnDetailsCol.setPercentageWidth(0.3);
warnDescriptionCol.setResizable(false);
warnDetailsCol.setResizable(false);
// adding nodes to containers
warningTable.getColumns().addAll(warnDescriptionCol, warnDetailsCol);
content.getChildren().add(warningTable);
}
Dialog
を作成し、content
を設定するために使用される関数:
private void setupDialog() {
// creation and saving of the dialog in a variable reused later
warningDialog = DialogFactory.getInstance(rootCtrl.getPrimaryStage()).createWarningDialog();
warningDialog.getDialogPane().setContent(content);
warningDialog.getDialogPane().getScene().getWindow().sizeToScene();
}
// The DialogFactory function creating the dialog
public Dialog createWarningDialog(){
CustomDialog dialog = new CustomDialog(rootStage);
dialog.setTitle(i18n("warning.description"));
ButtonType cancelBt = new ButtonType(i18n("button.close"), ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(cancelBt);
return dialog.setupLayout();
}
Main
クラスは、警告の読み込みを担当します(.json
ファイルに格納され、アプリの起動時に逆シリアル化されます)。今のところファイルには1つのエントリしか含まれていません。
私は私の警告]ボタンをクリックし
は、以下の関数が呼び出されます:私は私の.jsonファイルで唯一のエントリ、最初の時間を持っているとき、私はをクリックしてください:public void showWarnings() {
warningTable.getItems().clear(); // BP
warningTable.setItems(FXCollections.observableArrayList(warnings.values()));
warningDialog.showAndWait();
}
は何が起こることは以下のとおりです。ボタン、only one warning is shown。
- ロジック制約:私は二度目、a second entry appears (the same)をクリックすると、次の理由による可能にすべきではないどの
warnings.values()
は鍵がすることはできません警告(WarningType
クラス)>のタイプであるHashMap
から来ています二つの同一のキー - デバッグを持っている:私は「// BP」にブレークポイントを設定すると、私ははっきり
warningTable
は一つのアイテムを持っていることがわかり、そして明確な後のアイテムの数がゼロ - デバッグです:それでも同じブレークポイントでまた、
warnings.values()
には1つのアイテムしかないことが確認されます。その場合は です
ボタンを5回クリックした後、the Dialog
clearly shows something is bugging。
驚くべきことに、2番目の警告(最初のタイプ、別のタイプと異なる)を追加すると、問題は発生しません。重複はなく、警告は正しく表示されます。
私の質問は:この警告ダイアログを作成する方法が珍しいエラーにつながることでしょうか?もしそうなら、なぜ2つの警告があるのでしょうか?
EDITはthe documentationで説明したように、セルが空の場合は、セルの工場であなたの細胞をクリアする必要がありcellFactories/cellValueFactories
private void setupColumns() {
warnDescriptionCol.setCellFactory(new Callback<TableColumn<CustomWarning, String>, TableCell<CustomWarning, String>>() {
@Override
public TableCell<CustomWarning, String> call(TableColumn<CustomWarning, String> param) {
TableCell<CustomWarning, String> cell = new TableCell<CustomWarning, String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
Label label = new Label(item);
setGraphic(label);
}
}
};
return cell;
}
});
warnDetailsCol.setCellFactory(new Callback<TableColumn<CustomWarning, CustomWarning>, TableCell<CustomWarning, CustomWarning>>() {
@Override
public TableCell<CustomWarning, CustomWarning> call(TableColumn<CustomWarning, CustomWarning> param) {
TableCell<CustomWarning, CustomWarning> cell = new TableCell<CustomWarning, CustomWarning>() {
@Override
protected void updateItem(CustomWarning item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
Button button = new Button(i18n("button.view"));
button.getStyleClass().add("save");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
showWarning(item);
}
});
setGraphic(button);
}
}
};
return cell;
}
});
warnDescriptionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<CustomWarning, String>, ObservableValue<String>>() {
TableViewObjectWrapper<CustomWarning, String> wrapper = new TableViewObjectWrapper<CustomWarning, String>() {
@Override
public String getData() {
return getModel().getTitle();
}
};
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<CustomWarning, String> param) {
return new ReadOnlyObjectWrapper<>(wrapper.setModel(param.getValue()).getData());
}
});
warnDetailsCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<CustomWarning, CustomWarning>, ObservableValue<CustomWarning>>() {
TableViewObjectWrapper<CustomWarning, CustomWarning> wrapper = new TableViewObjectWrapper<CustomWarning, CustomWarning>() {
@Override
public CustomWarning getData() {
return getModel();
}
};
@Override
public ObservableValue<CustomWarning> call(TableColumn.CellDataFeatures<CustomWarning, CustomWarning> param) {
return new ReadOnlyObjectWrapper<>(wrapper.setModel(param.getValue()).getData());
}
});
}
'TableView'のセルファクトリとセル値ファクトリを設定する部分を含めてください。 – Itai
@sillyfly編集 – Jacks