对于我的应用程序,我设计了一个由ShopLogController.java
控制的简单日志窗口。
此窗口获取ShopLog
(不要与ShopLogController
)类混淆的日志信息并显示它。但是,ShopLog
本身可能会被存在的每个对象修改。因此,需要一种检查内容是否已更改的方法,以便使日志窗口的内容与ShopLog
类中的文本日志保持一致。
我探索的选项:
在update()
中实现一个公共ShopLogController
函数,只要日志发生变化就会调用该函数。
这很好,但IMO违反了GUI /逻辑/持久层的严格分离,因为逻辑层显式调用GUI以提示它更新。
(如果您认为这不违反分层,请解释原因)
实现某种在其自己的线程中运行的更新程序对象,并且每隔X毫秒从上面调用update()
。 JavaFX不允许这样生成java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-#
在相应的控制器内启动一个线程。这也可以正常 ish 。唯一的问题是更新将位于永不退出的while(true)
循环中。终止此循环需要一个可行的on-close
方法。我不知道单个窗口的这种解决方案,而不是整个应用程序。 (见stop()
)
如何更新我的日志(和其他)窗口而不明确地提示它从外部这样做;同时仍然使控制器仅在关闭窗口时终止?
根据要求提供相关对象的代码:
结构与此处一样基本。 String
中有一个ShopLog
,当它发生变化时,我希望调用update()
中的ShopLogController
。我还想避免从ShopLog显式调用任何控制器函数,因为不能保证存在任何控制器函数(例如,日志窗口尚未打开)。
PS:这不是关于找到any
可行的解决方案,而是找到一个优雅的解决方案。
答案 0 :(得分:0)
您可以像这样实现您的日志(模型):
public class ShopLog {
private final ReadOnlyStringWrapper logText = new ReadOnlyStringWrapper();
public ReadOnlyStringProperty textProperty() {
return logText.getReadOnlyProperty();
}
public final String getText() {
return textProperty().get();
}
// Implement as many methods like this as your API needs:
public void log(String logMessage) {
logText.set(logText.get() + "\n" + logMessage);
}
}
显然,这个类不了解视图(或视图的控制器/演示者),因此不会违反视图和模型的分离。
您的控制器可能如下所示:
public class ShopLogController {
private ShopLog log ;
@FXML
private TextArea logDisplay ;
public void setShopLog(ShopLog log) {
logDisplay.textProperty().bind(log.textProperty());
}
}
现在,当log(...)
上调用ShopLog
方法时,视图中的文本区域会自动通知(通过绑定),并将更新显示的文本。绑定是从控制器而不是模型进行管理的,这样可以保持适当的关注点分离。完全没有必要进行任何轮询(使用任意轮询间隔和线程进行管理)。
顺便说一下,这不是一个特别可扩展的解决方案,因为您将数据存储为一个整体字符串并通过字符串连接进行更新,显示使用文本区域。我展示了这个实现,因为它似乎是你正在使用的(基于你的评论和截图)。您可以考虑使用其他常规实现,例如使用ObservableList<String> logMessages
代替模型。