1

http://docs.oracle.com/javafx/2/ui_controls/tree-view.htmのJavaFXチュートリアルに触発されて、編集モードでセルに入る動作を変更するにはどうすればよいか疑問に思っています。私が取得したい動作は

  • マウスの左クリックで:セルを選択するだけです
  • マウスを2回左クリックした場合:セルを選択してアクションを呼び出します
  • マウスの右クリックで:セルを編集モードで入力します

TreeView / TreeCellにマウスイベントハンドラーをインストールしようとしましたが、イベントはすでにTreeCellBehaviorによって消費されているようです。

TreeCellBehviorクラスには、次のメソッドがあります。

private void simpleSelect(MouseEvent e) {
    TreeView tv = getControl().getTreeView();
    TreeItem treeItem = getControl().getTreeItem();
    int index = getControl().getIndex();
    MultipleSelectionModel sm = tv.getSelectionModel();
    boolean isAlreadySelected = sm.isSelected(index);

    tv.getSelectionModel().clearAndSelect(index);

    // handle editing, which only occurs with the primary mouse button
    if (e.getButton() == MouseButton.PRIMARY) {
        if (e.getClickCount() == 1 && isAlreadySelected) {
            tv.edit(treeItem);
        } else if (e.getClickCount() == 1) {
            // cancel editing
            tv.edit(null);
        } else if (e.getClickCount() == 2/* && ! getControl().isEditable()*/) {
            if (treeItem.isLeaf()) {
                // attempt to edit
                tv.edit(treeItem);
            } else {
                // try to expand/collapse branch tree item
                treeItem.setExpanded(! treeItem.isExpanded());
            }
        }
    }
}

TreeCellBehaviorを自分の実装に置き換えることができるかどうかはわかりません。この方法は私的なものですが、これが正しい方法かどうかはわかりません。何か案が?

4

1 に答える 1

2

私は自分でそれを解決しました。デフォルトで TreeView の編集可能を無効にしています。各 TreeItem には、項目名を変更できるコンテキスト メニューがあります。コンテキスト メニュー アクションが呼び出されると、TreeView が編集可能に設定され、現在の TreeItem で TreeView.edit() が呼び出されます。これで、startEdit() がバックグラウンドで呼び出され、編集モードがアクティブになります。

ただし、Enter キーを押して commitEdit() を呼び出した後、奇妙な動作が発生しました。このメソッドは、セルがまだ編集モードであるかどうかをチェックします (編集モードであるため true を返します)。回避策として、commitModeProperty を導入し、設定されている場合は cancelEdit() をチェックインします。そうしないと、新しいテキスト値が設定されません。

これが私のコードです:

public class FolderTreeCell extends TreeCell<FolderCellType> {

// workaround for a strange behaviour in commitEdit.. see initTextFieldListener() 
private BooleanProperty commitModeProperty = new SimpleBooleanProperty(false);

public FolderTreeCell() {
    assert Platform.isFxApplicationThread();
}

private ContextMenu createContextMenu() {
    MenuItem menuItem = new MenuItem("Change folder name");

    menuItem.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent evt) {
            getTreeView().setEditable(true);
            getTreeView().edit(getTreeItem());
        }

    });

    return new ContextMenu(menuItem);
}

private void initTextFieldListener() {
    getItem().textFieldProperty().get().setOnKeyReleased(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent evt) {
            if (evt.getCode() == KeyCode.ENTER) {
                commitEdit(getItem()); // TODO calls updateItem() when isEditing() is true causing invocation of cancelEdit() ?!?!
            } 
        }

    });
}

@Override
public void commitEdit(FolderCellType newFolderCellType) {
    commitModeProperty.set(true);
    super.commitEdit(newFolderCellType);
    commitModeProperty.set(false);
}

@Override
public void startEdit() {
    super.startEdit();

    setGraphic(getItem().getEditBox());

    if (getItem().textFieldProperty().get().getOnKeyReleased() == null) {
        initTextFieldListener();
    }

    getItem().textFieldProperty().get().selectAll();
    getItem().textFieldProperty().get().requestFocus();
}

@Override
public void cancelEdit() {
    super.cancelEdit();

    getTreeView().setEditable(false);
    if (!commitModeProperty.getValue()) {
        getItem().resetCurrentEntry();
    }

    setGraphic(getItem().getViewBox());
}

@Override
public void updateItem(FolderCellType item, boolean empty) {
    super.updateItem(item, empty);

    if (empty || item == null) {
        setText(null);
        setGraphic(null);
    } else {
        if (isEditing()) {
            setGraphic(item.getEditBox());
        } else {
            setGraphic(item.getViewBox());

            if (getContextMenu() == null) {
                setContextMenu(createContextMenu());
            }
        }
    }

    getTreeView().setEditable(false);
}

}

于 2013-01-29T09:44:50.307 に答える