2016-09-27 9 views
1

Требование: добавить пользовательские элементы меню в tableMenuButton (в RL сделано в пользовательском tableHeader) и те MenuItems должны быть доступны ускорителямиTableView: как включить ускоритель в угловом меню?

Проблема: Добавление элементов меню проста, но ускорители не работают

Ниже приведен пример, который добавляет элемент menuItem в угловое меню и - только для сравнения - другой для контекста таблицыMenu: см., Что последний запускается нажатием на ускоритель, а первый - нет.

Что мне не хватает, ошибка или функция? Любая идея, как настроить, чтобы заставить его работать?

import com.sun.javafx.scene.control.skin.TableHeaderRow; 
import com.sun.javafx.scene.control.skin.TableViewSkin; 

import javafx.application.Application; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ContextMenu; 
import javafx.scene.control.MenuItem; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.input.KeyCombination; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.FlowPane; 
import javafx.stage.Stage; 

/** 
* Problem: accelerator in table's corner menu not working. 
* 
* @author Jeanette Winzenburg, Berlin 
*/ 
public class TableViewAccelerator extends Application { 
    private Parent getContent() { 
     TableView table = new TableView<>(); 
     TableColumn first = new TableColumn<>("first"); 
     table.getColumns().addAll(first); 

     table.setTableMenuButtonVisible(true); 

     Button addMenu = new Button("add MenuItem to corner"); 
     addMenu.setOnAction(e -> { 
      TableViewSkin skin = (TableViewSkin) table.getSkin(); 
      TableHeaderRow header = skin.getTableHeaderRow(); 
      ContextMenu menu = (ContextMenu) invokeGetFieldValue(
        TableHeaderRow.class, 
        header, "columnPopupMenu"); 
      MenuItem item = new MenuItem("do stuff"); 
      item.setOnAction(me -> { 
       LOG.info("from corner"); 
      }); 
      item.setAccelerator(KeyCombination.valueOf("F3")); 
      menu.getItems().add(item); 
      addMenu.setDisable(true); 
     }); 

     ContextMenu menu = new ContextMenu(); 
     MenuItem contextItem = new MenuItem("initial"); 
     contextItem.setOnAction(e -> { 
      LOG.info("from initial"); 
     }); 
     contextItem.setAccelerator(KeyCombination.valueOf("F4")); 
     menu.getItems().addAll(contextItem); 
     table.setContextMenu(menu); 
     Button addToContext = new Button("add MenuItem to context"); 
     addToContext.setOnAction(e -> { 
      MenuItem added = new MenuItem("added"); 
      added.setOnAction(me -> LOG.info("from added")); 
      added.setAccelerator(KeyCombination.valueOf("F5")); 
      menu.getItems().addAll(added); 
      addToContext.setDisable(true); 
     }); 

     BorderPane pane = new BorderPane(table); 
     FlowPane buttons = new FlowPane(10, 10); 
     buttons.getChildren().addAll(addMenu, addToContext); 
     pane.setBottom(buttons); 
     return pane; 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     primaryStage.setScene(new Scene(getContent(), 600, 400)); 
     primaryStage.show(); 
    } 

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

    public static Object invokeGetFieldValue(Class declaringClass, Object target, String name) { 
     try { 
      Field field = declaringClass.getDeclaredField(name); 
      field.setAccessible(true); 
      return field.get(target); 
     } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    @SuppressWarnings("unused") 
    private static final Logger LOG = Logger 
      .getLogger(TableViewAccelerator.class.getName()); 
} 

Пар ноты:

ответ

2

Похоже, что пункты меню углов ускорители не прикреплены к сцене. Вероятно, отсутствует функция. Для того, чтобы заставить его работать, вы можете вручную прикрепить их с помощью ControlAcceleratorSupport класса:

Button addMenu = new Button("add MenuItem to corner"); 
addMenu.setOnAction(e -> { 
    TableViewSkin skin = (TableViewSkin) table.getSkin(); 
    TableHeaderRow header = skin.getTableHeaderRow(); 
    ContextMenu menu = (ContextMenu) invokeGetFieldValue(
        TableHeaderRow.class, 
        header, "columnPopupMenu"); 
    ControlAcceleratorSupport.addAcceleratorsIntoScene(menu.getItems(), table); 
[...] 
+0

doooohhhh .. что юродивый дизайн (в основном Fx) - работает отлично, спасибо за решение :-) – kleopatra