4

javafx UI を作成しており、クリックされた MenuItem の eventHandler から contextMenu の所有者 Node を取得したいと考えています。

私のコード:

TabPane tabPane = new TabPane();
Tab tab1 = new Tab();
Tab tab2 = new Tab();

tabPane.getTabs().addAll(tab1,tab2);

ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Do Some Action");

menuItem.setOnAction(new EventHandler<ActionEvent>(){
    @override
    public void handle(ActionEvent e){
        // Get the tab which was clicked on and do stuffs with it
    }
});

contextMenu.getItems().add(menuItem);

for(Tab tab: tabPane.getTabs()){
    tab.setContextMenu(contextMenu);
}

私がやりたいのは、contextMenu が選択されているタブへの参照を取得することです。

menuItem eventHandler の handle(ActionEvent e) メソッド内の次のコードを使用して、MenuItem の ContextMenu と思われるものへの参照を取得できました。

ContextMenu menu = ((ContextMenu)((MenuItem)e.getSource()).getParentPopup());

そこからの私の考えは、メニューで ContextMenu の .getOwnerNode() メソッドを使用してからタブへの参照を取得することでしたが、それを実行すると、意味をなさない項目への参照が取得されます。

.getOwnerNode() によって返されたオブジェクトの toString() メソッドは、意味を理解できない "TabPaneSkin$TabHeaderSkin$3@14f59cef" を返します。

ノードに到達するまでチェーンを上っていくという私のアプローチは正しいですか、それともよりうまく機能するまったく異なるアプローチがありますか?

必要なのは ContextMenu の機能だけです。MenuItem がクリックされたときに、ContextMenu が選択されたタブへの参照が必要なので、それを使ってクールなことを行うことができます。

4

1 に答える 1

4
  1. タブごとに ContextMenu を作成します。
  2. 各タブを最終的なものにします。
  3. コンテキスト メニューのメニュー項目イベント ハンドラで最終タブを直接参照します。

コード スニペットを次に示します。

final Tab tab = new Tab("xyzzy");
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Do Some Action");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
  @Override public void handle(ActionEvent e){
    tab.setText("Activated by User");
  }
});

ユーザーがタブ ヘッダーを右クリックして [クリックのカウント] メニューを選択するたびに、関連するタブのコンテンツが、そのタブでこれまでにカウントされたクリック数のカウントで更新されます。

クリックカウンター

実行可能なサンプルは次のとおりです。

import javafx.application.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class TabContext extends Application {
  @Override public void start(Stage stage) {
    TabPane tabPane = new TabPane();

    tabPane.getTabs().addAll(
      createTab("xyzzy",   "aliceblue"),
      createTab("frobozz", "blanchedalmond")
    );

    stage.setScene(new Scene(tabPane));
    stage.show();
  }

  private Tab createTab(String tabName, String webColor) {
    final Label content = new Label("0");
    content.setAlignment(Pos.CENTER);
    content.setPrefSize(200, 100);
    content.setStyle("-fx-font-size: 30px; -fx-background-color: " + webColor + ";");

    final Tab tab = new Tab(tabName);
    tab.setContent(content);

    ContextMenu contextMenu = new ContextMenu();

    MenuItem menuItem = new MenuItem("Count Click");
    menuItem.setOnAction(new EventHandler<ActionEvent>(){
      @Override public void handle(ActionEvent e){
        content.setText(
          "" + (Integer.parseInt(content.getText()) + 1)
        );
      }
    });

    contextMenu.getItems().add(menuItem);

    tab.setContextMenu(contextMenu);

    return tab;
  }

  public static void main(String[] args) { Application.launch(args); }
}

この方法で匿名内部クラスを使用する代わりに、EventHandler がアタッチされている Tab を含むコンストラクターを使用して EventHandler サブクラスを作成できます。

class TabContextMenuHandler implements EventHandler<ActionEvent> {
  private final Tab tab;

  TabContextMenuHandler(Tab tab) {
    this.tab = tab;
  }

  @Override public void handle(ActionEvent event) {
    tab.setText("Activated by User");
  }
}
于 2013-05-28T20:36:11.427 に答える