2017-02-22 40 views
0

我在個人項目中首次使用JavaFX進行遊戲。從外部FXML控制器獲取對Tab的引用

我希望能夠更新Tab中的內容(添加PieChart),但是從FXML控制器外部,任何人都可以告訴我這是否可能?我如何獲得對相關選項卡的引用,並且是否有方法指定我添加的項目的位置?

UPDATE:增加了一些示例代碼。

希望這給的什麼,我試圖做一個清晰的思路:

接口:

interface ChartStrategy { 

    public void DisplayChart(Info info) 
} 

兩個實現:

public class BarChartStrategy extends ChartStrategy { 

    public void DisplayChart(Info info) 
    { 
     // Create bar charts on specific tabs in the UI 
    } 
} 


public class PieChartStrategy extends ChartStrategy { 

    public void DisplayChart(Info info) 
    { 
     // Create pie charts on specific tabs in the UI 
    } 
} 

上下文:

public class ChartContext { 
    private ChartStrategy strategy; 

    public void setChartStrategy(ChartStrategy strategy) { 
    this.strategy = strategy; 
    } 

    public void drawGraphs(Info info) { 
    strategy.DisplayChart(info); 
    } 
} 

在我的控制ler,我在用戶選擇的文件中讀取數據以生成圖表,解析,例如。

@FXML 
private void handleButtonAction(ActionEvent event) { 

    // Load the file and parse the data 
    ... 

    ChartContext charts = new ChartContext(); 
    charts.setChartStrategy(new PieChartStrategy()); 
} 

所以我最初的想法是,我可以借鑑在實施中DisplayChart功能的圖表,但似乎不是一個好主意 - 任何人都可以給我一些建議在這裏得到這個的最佳方式工作?

+2

請問爲什麼?這正是控制器應該做的事情。你可以在控制器中定義一個返回特定選項卡的方法,並從你需要的地方調用它,但我不建議在控制器之外暴露UI組件。 –

+0

我正嘗試使用策略模式來處理在UI中顯示不同的圖表類型,方法是直接從策略實施中在UI中創建圖表。餿主意?參加一個關於設計模式的課程,並試圖讓我的頭腦圍繞這一點。 –

+0

不是一個壞主意,不,但是您不需要公開控制器中的UI組件就可以做到這一點。在控制器級別定義策略:即您的控制器具有對類型爲策略(接口)的字段的引用。在代碼中創建控制器(而不是在FXML中),指定傳遞給控制器​​構造函數的策略實現。然後您的控制器可以調用策略並將圖表放在適當的選項卡中。 –

回答

1

我會重構這一點。

首先,讓策略顯示圖表有點不靈活。您正在賦予策略兩個職責:首先決定如何以可視方式表示數據(選擇圖表),然後將其實際顯示在某處。這違反了單一責任原則。

所以我會做

interface ChartStrategy { 

    public Chart generateChart(Info info) 
} 

,同樣的實現,當然。那麼策略的責任就是提供一個圖表:上下文可以決定如何處理它。

(您也可以考慮是否回到這裏Chart太死板:也許你只是希望它返回一個Parent,或Node然後你的「圖表」可能是,例如,一個TableView,例如。)

在戰略模式的理論描述中,至少在我的解釋中,「背景」只是表示「正在使用戰略的東西」。所以你的上下文可能是一個視圖或控制器(取決於你選擇的MVC變種......)。作爲一個簡單的例子,你可能有類似

public class ChartTab { 

    private ChartStrategy chartGenerator ; 

    public void setChartGenerator(ChartStrategy chartGenerator) { 
     this.chartGenerator = chartGenerator ; 
    } 

    public Tab createChartTab(Info info) { 
     Tab tab = new Tab(); 
     tab.setContent(chartGenerator.generateChart(info)); 
     return tab ; 
    } 
} 

,然後在你的控制器

@FXML 
private TabPane tabPane ; 

@FXML 
private void handleButtonAction(ActionEvent event) { 

    // Load the file and parse the data 
    ... 

    ChartTab chartTab = new ChartTab(); 
    chartTab.setChartGenerator(new PieChartStrategy()); 
    tabPane.getTabs().add(chartTab.getTab(info));  
} 

也有可能只是考慮控制器的情況下(如果固定控制器,你只是創造一種

public class MyController { 

    private ChartStrategy chartGenerator ; 

    @FXML 
    private TabPane tabPane ; 

    public MyController(ChartStrategy chartGenerator) { 
     this.chartGenerator = chartGenerator ; 
    } 

    @FXML 
    private void handleButtonAction(ActionEvent event) { 

     // Load the file and parse the data 
     ... 

     Tab tab = new Tab(); 
     tab.setContent(chartGenerator.generateChart(info)); 
     tabPane.getTabs().add(tab);  
    } 

} 

注意這個控制器沒有一個無參數的構造函數,所以喲:圖表,這取決於你如何分割的FXML文件及其相應的控制器)的你不能在FXML文件中使用fx:controller屬性(即從FXML文件中刪除該屬性)。相反,你會做

FXMLLoader loader = new FXMLLoader("/path/to/DataDisplay.fxml"); 
MyController controller = new MyController(new PieChartStrategy()); 
loader.setController(controller); 
Parent root = loader.load(); 

現在你有一個FXML和控制器的功能,生成圖表,並在標籤窗格中顯示它們(或其他),但會產生什麼樣的圖表的細節因素進入可插拔策略。你仍然有適當的MVC(或者MVP等等)封裝,其中UI的細節對於視圖控制器(在這裏它是一個真正的主持人,但是誰在數......)是私有的。換句話說,戰略對其餘的觀點一無所知,這是應該的。

+0

謝謝@James_D,這讓我有很多想法。 –