2017-01-26 52 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. 實例化ContextMenuMenuItem實例(我理論上可以猜想MenuItem實例可以被實例化並稍後添加)。
  2. 援引「setRowFactory」以上代碼與第1步

實例化的上下文菜單中我有幾次反覆上解決這一問題,仍然沒能拿出一個令人滿意的解決方案。也許我錯過了一些明顯的東西。

編輯:將是完美的,如果你能以某種方式使用的TableViewsetContextMenu方法,以確保`在正確的方式添加文本菜單禁用用戶。但我想這是不可能的。

回答

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 ; 
     }); 
    } 

    // ... 
} 

要回答你問的問題(確保你只(始終)調用setContextMenu後調用setRowFactory):

您可以做

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'是最後一個方法,不能重寫。但是重寫超級方法可能不是你的例子。如果你能以某種方式禁止用戶使用'TableView'中的'setContextMenu'來確保ContextMenu以正確的方式添加,那麼這將是完美的。但我想這是不可能的。 –

+0

@JonatanStenbacka查看更新。如果您所做的只是抑制空行上的上下文菜單,那麼只需要在發生這些行時使用「請求上下文菜單」事件。修正了重寫最終方法的問題,並在最後一個選項中重新使用了這個想法。 –

+0

關於最後一個例子的快速註釋:我認爲你需要在開始時調用'setContextMenu(null)',否則'ContextMenu'對於整個表格來說都是一樣的。它也不能編譯,因爲你需要返回'rowFactory'中的行。無論如何,我想我會用這個例子,謝謝你的幫助! –