从FXML Controller外部获取对Tab的引用

时间:2017-02-22 21:12:51

标签: javafx

我第一次在个人项目上玩JavaFX。

我希望能够更新Tab中的内容(添加PieChart),但是从FXML控制器外部,任何人都可以告诉我这是否可能?我如何获得相关标签的参考,是否有办法指定我添加的项目的位置?

更新:添加了一些示例代码。

希望这能清楚地说明我正在尝试做什么:

界面:

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

在我的控制器中,我正在读取一个用户选择的文件来解析生成图表的数据,例如。

 @FXML
 private void handleButtonAction(ActionEvent event) {

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

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

所以我最初的想法是我可以在实现中从DisplayChart函数中绘制图表,但似乎这不是一个好主意 - 任何人都可以在这里给出一些关于让它工作的最佳方法的建议吗?

1 个答案:

答案 0 :(得分:1)

我会稍微重构一下。

首先,让策略显示图表有点不灵活。您正在为策略赋予两个职责:首先决定如何直观地表示数据(选择图表),然后在某处实际显示它。这违反了单一责任原则。

所以我会这样做

interface ChartStrategy {

    public Chart generateChart(Info info)
}

当然,类似于实现。然后,策略的责任就是提供一个图表:上下文可以决定如何处理它。

(您还可以考虑在此处返回Chart是否过于严格:或许您只是希望它返回ParentNode。然后您的“图表”可能是,例如,一个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));    
}

也可以将控制器视为上下文(如果对于固定控制器,您只是创建一种图表,这取决于您如何拆分FXML文件及其相应的控制器):

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

}

请注意,此控制器没有no-arg构造函数,因此您无法在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的细节保持私有的视图控制器(这里它真的是一个演示者,但谁在计算...)对。换句话说,策略对视图的其余部分一无所知,这是应该的。