2017-01-26 6 views
0

У меня есть этот суперкласс, расширяющий TableView, что каждая таблица, которую я хочу сделать, должна наследовать.Как обеспечить выполнение кода в определенном порядке по наследованию

Эта строка кода должна быть выполнена для каждого класса, который наследует от суперкласса и нуждается в ContextMenu:

// Sets the context menu for each specific row. This way no 
// context menu will appear if we click on a row that is 
// empty. 
setRowFactory(r -> { 
    TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() { 
     public void updateItem(ObservableList<String> item, boolean empty) { 
      super.updateItem(item, empty); 
      if (isEmpty()) { 
       setContextMenu(null); 
      } else { 
       setContextMenu(contextMenu); 
      } 
     } 
    }; 
}); 

Проблема заключается в том, что ContextMenu потребности быть обработан прежде, чем этот код может быть выполнен, следовательно, Я не могу добавить конструктор суперкласса.

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

  1. инстанцировать ContextMenu с MenuItem экземпляров (I предположим, что экземпляры MenuItem могут быть созданы и добавлены позже, теоретически).
  2. Призовите «setRowFactory» код выше с помощью контекстного меню реализованного в шаге 1.

У меня было несколько итераций на решение этого вопроса, и до сих пор не удался придумать удовлетворительным решением. Может быть, мне не хватает чего-то очевидного.

Edit: Было бы идеально, если вы могли бы каким-то образом отключить пользователя от использования оригинального setContextMenu метод TableView, чтобы гарантировать, что `ContextMenu добавляется в правильный путь. Но я думаю, это невозможно.

ответ

1

Похоже, вы просто пытаетесь подавить контекстное меню в пустых строках таблицы. Простой способ сделать это

public class MyTableView<T> extends TableView<T> { 

    public MyTableView() { 
     setRowFactory(tv -> { 
      TableRow<T> row = new TableRow<>(); 
      row.setOnContextMenuRequested(e -> { 
       if (row.isEmpty()) { 
        e.consume(); 
       } 
      } 
      return row ; 
     }); 
    } 

    // ... 
} 

Чтобы ответить на вопрос, который вы просили (обеспечивая вам только (и всегда) называют setRowFactory после вызова setContextMenu):

Вы можете сделать

public class MyTableView<T> extends TableView<T> { 

    private final ContextMenu contextMenu ; 

    public MyTableView(ContextMenu contextMenu) { 
     this.contextMenu = contextMenu ; 

     setRowFactory(r -> { 
      TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() { 
       public void updateItem(ObservableList<String> item, boolean empty) { 
        super.updateItem(item, empty); 
        if (isEmpty()) { 
         setContextMenu(null); 
        } else { 
         setContextMenu(contextMenu); 
        } 
       } 
      }; 
     }); 

    } 

    // ... 
} 

или

public class MyTableView<T> extends TableView<T> { 

    private ContextMenu rowContextMenu ; 

    public ContextMenu getRowContextMenu() { 
     return rowContextMenu ; 
    } 

    public void setRowContextMenu(ContextMenu contextMenu) { 
     this.rowContextMenu = contextMenu ; 

     setRowFactory(r -> new TableRow<ObservableList<String>>() { 
      public void updateItem(ObservableList<String> item, boolean empty) { 
       super.updateItem(item, empty); 
       if (isEmpty()) { 
        setContextMenu(null); 
       } else { 
        setContextMenu(rowContextMenu); 
       } 
      } 
     }); 
    } 

    // ... 
} 

или даже

public class MyTableView<T> extends TableView<T> { 

    public MyTableView() { 
     contextMenuProperty().addListener((obs, oldContextMenu, newContextMenu) -> { 
      if (newContextMenu == null) { 
       setRowFactory(r -> new TableRow<>()); 
      } else 
       setRowFactory(r -> new TableRow<ObservableList<String>>() { 
        public void updateItem(ObservableList<String> item, boolean empty) { 
         super.updateItem(item, empty); 
         if (isEmpty()) { 
          setContextMenu(null); 
         } else { 
          setContextMenu(newContextMenu); 
         } 
        } 
       }); 
      } 
     }); 
    } 

    // ... 
} 
+0

Спасибо, что предоставили мне пару альтернатив! Второй не будет компилироваться, поскольку «SetContextMenu» является окончательным методом и не может быть переопределен. Но переопределение супер-метода, вероятно, не было точкой вашего примера. Было бы идеально, если бы вы могли каким-то образом отключить пользователя от использования 'setContextMenu' из' TableView', чтобы гарантировать, что 'ContextMenu добавляется корректно. Но я думаю, это невозможно. –

+0

@JonatanStenbacka Просмотреть обновления. Если все, что вы делаете, это подавление контекстного меню в пустых строках, вам просто нужно использовать событие «контекстное меню», когда оно встречается в этих строках. Исправлена ​​проблема с переопределением конечных методов, а также была перепрофилирована идея в последнем варианте. –

+0

Быстрое замечание в последнем примере: я думаю, что вам нужно вызвать 'setContextMenu (null)' в начале, иначе 'ContextMenu' будет одинаковым для всей таблицы в любом случае. Также он не компилируется, так как вам нужно вернуть строку внутри 'rowFactory'. Я думаю, что буду использовать этот пример, спасибо за вашу помощь! –

 Смежные вопросы

  • Нет связанных вопросов^_^