【问题标题】:JavaFx how to avoid creating one huge controllerJavaFx 如何避免创建一个巨大的控制器
【发布时间】:2017-02-06 23:52:59
【问题描述】:

我在 JavaFX 中有一个应用程序,它具有带有菜单和工具栏的主场景,以及在按下菜单按钮之一后注入到该主场景中的较小场景。

现在,HomeCntroller 负责任一场景组件:主场景(带有工具栏和菜单)和注入场景。如果注入的场景数量超过一个,这将导致我创建庞大、庞大且非常不专业的控制器。

如何拆分控制器职责?

现在我的控制器看起来像这样: changeDashboardPane 方法将较小的窗格注入到我的主 HomePane 中。

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
public class HomeController extends AbstractController {
    private static final Logger LOG = Logger.getLogger(HomeController.class);

    private final BudgetProfileService budgetProfileService;

    @FXML
    private Label usernameLabel;

    @FXML
    private ComboBox<String> budgetProfilesComboBox; 

    @FXML
    private AnchorPane dashBoardPane;

    @FXML
    public void initialize() {
        refreshUsernameLabel();
        getAllBudgetProfiles();
        changeDashboardPane(PaneFactoryKeys.FINANCES_PANE);
    }

    private void refreshUsernameLabel() {
        String username = UserAccountProvider.getLoggedUser().getUsername();
        usernameLabel.setText(username);
    }

    private void getAllBudgetProfiles() {
        List<String> budgetProfileNames = budgetProfileService.getAllBudgetProfileNames();
        if (!budgetProfileNames.isEmpty()) {
            budgetProfilesComboBox.getItems().clear();
            budgetProfilesComboBox.getItems().addAll(budgetProfileNames);
        }
    }

    @FXML
    public void handleFinancesButtonAction() {
        changeDashboardPane(PaneFactoryKeys.FINANCES_PANE);
    }

    @FXML
    public void handlePeriodButtonAction() {
        changeDashboardPane(PaneFactoryKeys.PERIOD_PANE);
    }

    @FXML
    public void handleStatisticsButtonAction() {
        changeDashboardPane(PaneFactoryKeys.STATISTICS_PANE);
    }

    @FXML
    public void handleSettingsButtonAction() {
        changeDashboardPane(PaneFactoryKeys.SETTINGS_PANE);
    }

    private final void changeDashboardPane(String paneFactoryKey) {
        double injectedPanePosition = 0.0;
        Pane paneToChange = getPaneFromFactory(paneFactoryKey);
        dashBoardPane.getChildren().clear();
        AnchorPane.setTopAnchor(paneToChange, injectedPanePosition);
        dashBoardPane.getChildren().add(paneToChange);
    }

}

为了更清楚,屏幕:

without injected second pane with injected second pane

有什么想法吗?

【问题讨论】:

  • 拥有一个将控制权传递给为每个窗格指定的控制器的全局控制器是我的第一个想法。虽然这对我来说看起来不错。
  • 您可以将其他 FXML 元素插入您的主 fxml 并保持控制器分开。我想这可能是你想要做的。你看过stackoverflow.com/questions/19342259/…吗?
  • 每个 FXML 文件都应该有一个控制器类。因此,如果您需要将其拆分为更小的组件,请将视图拆分为更小的 FXML 文件并为每个文件创建一个控制器类。使用&lt;fx:include&gt;
  • 好的,我发现,我可以从 FXML 加载的任何窗格都可以有自己的控制器,即使该窗格被注入另一个窗格。这解决了我的问题:) 谢谢大家的回答! :)
  • 必须有自己的控制器

标签: java design-patterns javafx


【解决方案1】:

我建议您将主要场景划分为较小的场景,例如您可以有一个工具场景、一个标题场景、一个内容场景等。那么每个场景都应该有一个控制器。

之后我会使用发布者-订阅者模式来处理行为,例如当您在设置场景中按下按钮时,它会触发其他场景侦听的事件,然后它们会相应地更改其状态。

我希望它很清楚并且可以提供帮助!

【讨论】:

  • 是的,我有 HomeScene,有空的仪表板空间和注入 HomeScene 的更小的窗格。现在每个窗格都有自己的控制器,一切都很好:)
【解决方案2】:

创建多个控制器,多个 FXML 文件 - 继续我之前提供给您的答案,JavaFX how to inject new FXML content to current Scene 每个具有单独 fxml 文件的视图也有

fx:controller="appplication.ExampleViewController"

附加到它。所以你要做的是创建前面提到的主控制器,这基本上是封装控件以更改动态容器的 FRAME CONTAINER。如果你的应用程序真的 ui 丰富并且在一个控制器中有很多功能,你可以进一步分解你的观点:

例如取出菜单并将其放入单独的控制器中,然后使用主控制器将其插入主视图中

/和setView()方法一样/

,您所做的只是将其拿走以保持控制器代码更小,您不会通过这种方式减少/增加场景图,没有缺点,这只是个人喜好。

你最终会得到更多的 fxml 文件和控制器。它和你之前的问题一样,不需要额外的代码,你实际上可以重用已经提供的东西。

控制器之间的数据通过 MODEL 传递。 - 更多地研究 MVC 不使用控制器中的应用程序数据只关心视图或将它们从/传递到模型

【讨论】:

    【解决方案3】:

    为了避免庞大的控制器类,因为我使用多个选项卡,我将选项卡拆分为单个 java 文件。

    我的解决方案是创建一个级联的类:

    • 基础:包含 FX 类型的所有定义
    • Tab1 扩展 Base:Tab 一个实现
    • Tab2 扩展 Tab1:Tab 两个实现
    • 控制器扩展 Tab2 实现 Initializable:实现初始化(URL url,ResourceBundle resourceBundle)

    重要: 任何访问的对象都必须在当前选项卡或之前定义。 Base 中的任何对象都可以在 Controller 中使用,而 Controller 的对象在 Base、Tab1 或 Tab2 中都无法访问。

    随时添加您的意见作为评论或提交改进。

    【讨论】:

      猜你喜欢
      • 2012-09-05
      • 2022-07-22
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 2011-01-05
      相关资源
      最近更新 更多