2016-01-17 5 views
0

Я пытаюсь иметь JavaFX Pane (VBox в моем случае, но я не думаю, что это имеет значение), у которого есть ContextMenu, который ведет себя правильно.Контекстное меню на панели, которая правильно исчезает

Я нашел эти два вопроса: why Panes can't have ContextMenus и How to create ContextMenu within a Pane.

Проблема, с которой я сталкиваюсь с этими двумя решениями (которые очень похожи) заключается в том, что, хотя контекстное меню правильно исчезает, если я нажимаю на панель, оно не исчезает, если я нажимаю внутри элемента управления внутри этой панели. Самый простой способ заметить этот недостаток - создать такую ​​панель с помощью TextField. Щелкните правой кнопкой мыши на панели, чтобы отобразить контекстное меню, затем нажмите внутри, чтобы сосредоточиться на TextField. В то время как правильное контекстное меню исчезло в этот момент, это контекстное меню «взломанное» (из-за отсутствия лучшего термина) с радостью остается на своем месте, возможно, блокируя представление пользователя в текстовом поле, которое они пытаются заполнить.

Теперь я знаю, что могу добавить слушателя изменений в свойство focused каждого элемента управления на моей панели, но это кажется излишним. Есть ли лучший способ убедиться, что контекстное меню скрыто при выборе элемента управления в моей панели (или, точнее, когда пользователь нажимает мышью в любом месте в окне владения за пределами контекстного меню)?

То, что я пытался до сих пор и не работает -

  1. Добавление изменения слушателя focused собственности на панели в - появляется это панель не считается сосредоточены, если один из его детей является
  2. Добавление прослушиватель изменений в свойство контекстного меню focused - кажется, что фокус контекстного меню не изменяется при нажатии за его пределами.

ответ

1

Хорошо, поэтому после некоторого копания в исходном коде JavaFX я нашел это обходное решение (это то, что «решает» эту проблему для обычных элементов управления). Просто добавьте эту строку кода -

contextMenu.setImpl_showRelativeToWindow(true); 

Теперь я знаю, используя внутренние методы реализации отвергающих, так как они могут исчезнуть, но это единственное решение, которое я нашел. Если у кого-то есть лучшее решение, я буду рад это услышать, но я подозреваю, что это просто ошибка, которая должна быть подана (т. Е. Должен быть способ использовать механизм showRelativeToWindow при настройке контекстных меню на панелях).

Я думаю, несколько безопаснее решение будет иметь контроль (одноразовый не в графе сцены), на котором установить контекстное меню, но я не знаю, если это будет иметь какие-либо нежелательные побочные эффекты:

Label throwaway = new Label(); // No special reason for using Label, could be any Control. 
throwaway.setContextMenu(contextMenu); // note that this is the only place `throwaway` is used, it is never added to the scene graph 
             // or referenced again, but just setting the context menu on a control solves the problem. 

Редактировать
Порывшись еще немного я нашел this, и решение в дискуссии - вы должны вызвать перегрузку show метод, который принимает окно, а не узел! Не очень ясно, но он работает:

myPane.setOnContextMenuRequested(event -> 
    contextMenu.show(myPane.getScene().getWindow(), event.getScreenX(), event.getScreenY()) 
);