【问题标题】:Center a JavaFX ContextMenu in the middle of a screen?将 JavaFX ContextMenu 居中在屏幕中间?
【发布时间】:2019-05-16 05:45:33
【问题描述】:

我正在尝试创建一个 ContextMenu,只要按下键盘的退出按钮,它就会出现在屏幕中间。我想用它来处理我的游戏中的加载、保存和退出。它将从 Main 之外的类中调用。

问题是我不确定如何找出 ContextMenu 的高度和宽度(以像素为单位)。所以,我不知道如何在窗口中居中。我正在尝试使用 Rectangle2D 来找到中心,但它仍然有点偏离。

如何在屏幕中间显示我的 ContextMenu?

显示我的 ContextMenu:

/**
 * Returns the Pane object so it can be made into a Scene object.
 * Each Scene has it's own class
 * Each class uses this method to create a Pane object for it.
 * @return Pane 
 */
public Pane getPane() {
   // create a GridPane object
   grid = new GridPane();

   // create ContextMenu and set anchor points.
   ContextMenu cm = Main.Org.createPopUpMenu();
   cm.setOnShowing(event -> {
      event.consume();
      cm.setAnchorX(cm.getAnchorX() - cm.getWidth() / 2.0);
      cm.setAnchorY(cm.getAnchorY() - cm.getHeight() / 2.0);
   });
   Rectangle2D bounds = Screen.getPrimary().getVisualBounds();

   // show ContextMenu if escape key is pressed.
   grid.setOnKeyReleased( event -> {
      if(event.getCode() == KeyCode.ESCAPE) {
         cm.show(grid, bounds.getWidth() / 2.0, bounds.getHeight() / 2.0);
      }
   });

   return grid;
}

组织者类createPopUpMenu()方法:

/**
 * Creates a pop-up menu for saving, loading, and exiting the game
 * @return ContextMenu 
 */
public ContextMenu createPopUpMenu() {
   ContextMenu contextMenu = new ContextMenu();

   MenuItem menuItem = new MenuItem();

   //create ImageViews
   image = new ImageView("/images/PopUpMenu_Exit.png");

   // add ImageViews to MenuItems
   menuItem.setGraphic(image);

   contextMenu.getItems().add(menuItem);

   menuItem.setOnAction( a -> {
      // quit the game
      Platform.exit();
      System.exit(0);
   });

   return contextMenu;
}

【问题讨论】:

  • 请提供一个minimal reproducible example 来说明问题。
  • @kleopatra 你觉得可以添加什么来增强这个问题?我可以提供一个无需修改即可运行的代码示例,但它会是几百行代码。
  • 几百行并不是“最少的” ;) 没有人愿意涉足大量不相关的代码,将精髓减少到 50 左右——这总是足以证明你所追求的要点和为什么结果不是你所期望的。
  • 写完这样的例子你会更有经验:)
  • @kleopatra 我已经减少了我的示例,同时仍然使方法本身可以运行,尽管只要它们周围有其他代码。我还修改了 Slaw 建议的代码版本。如果我还能做些什么来改善这个问题,请告诉我。

标签: java javafx javafx-8 contextmenu gridpane


【解决方案1】:

这是一个小例子(一些解释在code-cmets中):

import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.Window;

public class Main extends Application {

  private ContextMenu menu;

  @Override
  public void start(Stage primaryStage) {
    primaryStage.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
      if (event.getCode() == KeyCode.ESCAPE) {
        event.consume();
        showContextMenu(primaryStage);
      }
    });

    Label label = new Label("Press ESC to show ContextMenu.");
    primaryStage.setScene(new Scene(new StackPane(label), 500, 300));
    primaryStage.show();
  }

  private void showContextMenu(Window owner) {
    if (menu == null) {
      menu = new ContextMenu(
          new MenuItem("Copy"),
          new MenuItem("Cut"),
          new MenuItem("Paste"),
          new SeparatorMenuItem(),
          new MenuItem("Delete")
      );

      /*
       * Adjusts the ContextMenu's position once shown so that the center
       * of the ContextMenu is at the center of the screen (rather than
       * the top left corner). Do this here because the ContextMenu needs
       * to have been displayed in order to know the dimensions.
       *
       * Since the top left corner is already centered on the screen we don't need
       * to know the dimensions of the screen. We only need to move the ContextMenu
       * relative to itself.
       */
      menu.setOnShown(event -> {
        event.consume();
        menu.setAnchorX(menu.getAnchorX() - menu.getWidth() / 2.0);
        menu.setAnchorY(menu.getAnchorY() - menu.getHeight() / 2.0);
      });
    }

    /*
     * Displays the ContextMenu on the primary screen. The top left corner
     * of the ContextMenu will be at the center of the screen. Will need
     * to adjust the ContextMenu's position after it's shown.
     */
    Rectangle2D bounds = Screen.getPrimary().getVisualBounds();
    menu.show(owner, bounds.getWidth() / 2.0, bounds.getHeight() / 2.0);
  }

}

【讨论】:

  • 感谢您提供详细的示例。不幸的是,这似乎对我不起作用。我认为这可能是因为我是从 Main 类之外调用它的。我会在我的问题中提到这一点。你觉得我还有什么可以尝试的吗?
  • @LuminousNutria 据我所知,您从哪里调用此代码并不重要。
  • 我不介意这样做,但您能否提供更多关于您希望看到的内容的信息?如果没有几百行代码,我无法提供一个可以自行运行的示例。
  • @LuminousNutria A minimal reproducible example 应该是专门为 Stack Overflow 创建的。它基本上应该是你想要做的任何事情的(可运行的)模拟。您当前的大部分代码可能与手头的问题无关。如果在您创建 MCVE 的过程中问题消失了,您甚至可以自己找到问题。
  • 这是我很困惑的问题。我不知道如何在没有大量与手头问题无关的代码的情况下在 JavaFX 中创建 runnable 示例。我并不总是确定相关的。
猜你喜欢
  • 2016-04-07
  • 2022-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-20
  • 2014-03-24
  • 2010-12-23
相关资源
最近更新 更多