java - 当输入事件仅影响View时,有关Controller及其角色(如果有)的MVC设计帮助

标签 java model-view-controller design-patterns javafx

我承认对使用设计模式不熟悉,我不确定如何进行设计。我正在JavaFX中构建自定义图形符号。我只是扩展Parent并将矩形和圆形添加到我的符号类中,然后在场景中显示该符号对象。

该符号类还注册事件处理程序,如setOnMouseEntered和许多其他事件处理程序,以响应鼠标事件来更改符号。我想问的是,将所有这些事件处理程序存储在哪里最有意义?我不确定它们是否应该进入Controller类,或者因为它们仅影响该符号的视图,也许我应该将它们保留在符号的类中,并只保留Controller以用于必须从View进行通信的内容到模型,反之亦然。感谢任何可以对此有所了解的人(或可以将我引向好的资源)!

最佳答案

一般建议

我建议不要研究直接用抽象概念工作的方法,而建议看一下用现有代码在JavaFX中实现的这些模式的示例,并查看它们在其中的编码方式。找到喜欢的模式后,可以在代码中模拟它们。

在大型程序中,您要在整个应用程序或场景中应用MVC模式,而在小型程序中,则要在特定控件类型上应用模式,这是有区别的。您的问题似乎与后一种情况更为相关,因此在此答案中,我将主要考虑这一点。



JavaFX控件-外观,行为和公共API

看一下现有的controls code for JavaFX。对于Button,您将具有:


javafx.scene.control.Button-用于操纵控件的公共API。
javafx.scene.control.skin.ButtonSkin-控件的可视视图。
javafx.scene.control.behavior.ButtonBehavior-事件绑定(键/鼠标事件等)。


ButtonBehavior提供了一个抽象api,因此可以将按钮绑定到不同的平台和特定于用户的事件映射,以实现键,鼠标和​​触摸的组合。

ButtonSkin允许控件的可视化实现完全换入和换出,而无需修改公共API或行为。

Button公共API提供了一个稳定的API,按钮的用户可以对其进行编程,以独立于控件实现的任何视觉或行为更改。



删除抽象

尽管外观和行为API非常适合抽象出行为和外观的实现细节,但它们确实增加了控件实现者的复杂性和开销。您应该考虑所创建的控件是否真的需要这种复杂性,并评估其他更简单的方法。

最简单的方法就是扩展现有的Pane并将所有逻辑放在单个扩展类中(甚至只是提供构造控制节点的工厂方法)。您失去了抽象,它具有简单的实现可互换性和关注点分离的好处,但是您有一个非常简单的实现。这种简单的扩展机制的一个示例是Custom Control example in the Oracle Mastering FXML tutorial

我使用的稍微复杂一点的方法是拥有一个封装公共API和控件状态信息的类,以及一个单独的皮肤类来处理事件或UI呈现。我喜欢这种方法,因为它清楚地将JavaFX特定的逻辑和代码与底层控件状态和公共API分离开来,而没有像标准JavaFX控件的行为/外观/公共api方法那样增加概念上的开销。 Tic-Tac-Toe game中使用这种方法的一些示例代码。



外观/行为与公共API之间的通信

在包含控件的公共API的类中使用JavaFX property mechanisms。这些属性可以定义控件的公共API并通过ReadOnlyWrappers之类的类型封装内部控件状态。

外观可以将绑定和监听器应用于属性,以便在触发监听器时,外观可以触发自身的自动更新以反映新的控件状态。控件的用户可以侦听或绑定到控件的内部状态,以便在状态更改时采取措施。此方法的一个示例是selected property of a ToggleButton,其中皮肤根据是否已选择按钮来更改切换按钮的外观。

创建外观时,请使用对包含控件的公共api的向后引用(例如SymbolSkinSymbolBehaviour引用Symbol)来初始化外观和行为。鼠标单击可能会被mouseclickhandler in the SymbolSkin or SymbolBehavior拦截,并将公共api上的选定属性切换到Symbol,然后侦听符​​号上选定属性的更改的用户代码可以生效,而无需将该用户代码紧密耦合到符号的皮肤或行为。

Symbol的公共API仅需要公开一个方法getSkin(),该方法将皮肤返回为可以在场景图中使用的简单节点。这样,就可以通过使用Symbol公共API在调用类中隐藏外观和行为的实现。



扩展区域并使用CSS

通过使控件外观扩展Region,控件可以通过CSS设置样式。我强烈推荐这种方法,因为这意味着可以在JavaFX's rich css style language中操纵控件的许多视觉方面(例如颜色填充,背景,边框,形状等)。

这样做时,请尝试使用单独的CSS样式类对控件外观中的所有节点进行检测。这提供了到控件的可视组件的钩子,您可以使用它们来设置这些组件的样式。 Oracle tutorial on Styling Charts with CSS是这种样式复杂组件样式的示例。

要在问题中定义不同的符号,可以创建单个Symbol控件。定义用于处理用户事件的SymbolBehaviour和仅扩展SymbolSkinRegion。每个符号实例都可以分配自己的样式类,而公共的Symbol API可以提供一个构造函数或工厂方法,以在符号皮肤的区域上设置此样式类。使用-fx-shape css说明符可基于svg路径字符串设置符号形状的样式。

CSS样式类名称本身可以硬编码到您的SymbolSkin实现中,并作为公共API的一部分进行记录(如CSS reference guide for standard controls中所做的那样)。

随您的控件一起提供一个默认的css模板,该模板定义了该控件的默认样式。



FXML注意事项

当您有一个较大的应用程序或场景,它由许多需要协调的子控件组成时,则可以使用诸如FXML之类的方式以声明的方式定义场景。这使您可以将UI设计与命令式编程代码库分开,并确保您不会在视图中开始编写命令式代码。

对于具有FXML的真正MVC架构,您可能不仅需要FXML文件和后台控制器来实现场景,还需要更高级别的控制机制来交换场景,以及更复杂的事件处理方法,例如作为事件总线,但这超出了这个问题的范围。



有关

有一个稍微不同但相关的问题,应该可以帮助您更好地了解问题域(JavaFX 2.0 - style / template existing control)。

关于java - 当输入事件仅影响View时,有关Controller及其角色(如果有)的MVC设计帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15802625/

相关文章:

java - 在 UntypedActor Play 2.5 java 中注入(inject)变量 null

java - JAXB 2.0 验证不起作用

java - 如何从一组对象生成组合?

java - MVC Web 应用程序的样板代码?

c++ - 单例实现和对::GetInstance 的 undefined reference

java - 在 Java 应用程序上使用 XDG 目录规范

android - Android UI 开发是否适合特定的设计模式?

java - MVC架构中如何使用线程?

java - 如何使用带有构造函数参数的 Spring Prototype Beans?

c# - 我的单例实现是否正确? C#