我一直在研究这个问题,但至少我还是非常困惑.
谁能给我一个何时使用Task和何时使用的具体例子Platform.runLater(Runnable);?究竟有什么区别?什么时候使用其中任何一个是否有黄金法则?
如果我错了也不纠正我,但这两个"对象"不是在GUI中用于更新GUI的主线程内创建另一个线程的方法吗?
我想知道是否有人可以帮助我解决在JavaFX中创建后台线程的相当烦人的问题!我目前有几个SQL查询将数据添加到当前在JavaFX应用程序线程上运行的UI(参见下面的示例).但是,当每个查询执行时,它会冻结UI,因为它不在后台线程上运行.我已经查看了使用Task的各种示例,并了解它们,但是在进行数据库查询时我无法使它们工作,其中一些需要几秒钟才能运行.
以下是执行查询的方法之一:
public void getTopOrders() {
customerOrders.clear();
try {
Connection con = DriverManager.getConnection(connectionUrl);
//Get all records from table
String SQL = "EXEC dbo.Get_Top_5_Customers_week";
ResultSet rs;
try (Statement stmt = con.createStatement();) {
rs = stmt.executeQuery(SQL);
while (rs.next()) {
double orderValue = Double.parseDouble(rs.getString(3));
customerOrders.add(new CustomerOrders(rs.getString(1),
rs.getString(2), "£" + formatter.format(orderValue),
rs.getString(4).substring(6, 8) + "/" +
rs.getString(4).substring(4, 6) + "/" +
rs.getString(4).substring(0, 4)));
}
}
} catch (SQLException | NumberFormatException e) {
}
}
Run Code Online (Sandbox Code Playgroud)
每个已处理的记录都会添加到ObservableList中,该ObservableList链接到TableView或图表,或者只是在标签上设置文本(取决于查询).如何在后台线程上执行查询,仍然可以自由使用接口并从查询中更新
提前致谢
奇怪的是,我无法弄清楚如何解决这个问题.我有一个tableview,当一个可观察列表的监听器发现有变化时,它会被填充.所以这是代码:
userController.getAuthImpl().listOfMessages.addListener(new ListChangeListener<Message>() {
@Override
public void onChanged(ListChangeListener.Change<? extends Message> c) {
addMessageToTableView(tblvwBottomAdminNotifications, c.getList());
}
});
public void addMessageToTableView(TableView<Message> tblvw, ObservableList<? extends Message> observableList){
tblvw.getItems().clear();
for(Message msg: observableList)
tblvw.getItems().add(msg);
}
public ObservableList<Message> listOfMessages = FXCollections.observableArrayList(_listOfMessages);
Run Code Online (Sandbox Code Playgroud)
这样工作正常,一旦将项添加到listOfMessages,表就会自动更新.我现在要做的一点是,在更新时将列表视图滚动到底部.我尝试将以下行添加到addMessageToTableView方法:
tblvw.scrollTo(tblvw.getItems().size()-1);
Run Code Online (Sandbox Code Playgroud)
并且还尝试向tableview本身添加一个更改侦听器,如下所示:
tblvwBottomAdminNotifications.getItems().addListener(new ListChangeListener<Message>(){
@Override
public void onChanged(javafx.collections.ListChangeListener.Change<? extends Message> c) {
tblvwBottomAdminNotifications.scrollTo(c.getList().size()-1);
}
});
Run Code Online (Sandbox Code Playgroud)
但是两个错误都以同样的方式出现以下消息:
线程"RMI TCP连接(1)-192.168.56.1"中的异常java.lang.IllegalStateException:不在FX应用程序线程上; currentThread = RMI TCP连接(1)-192.168.56.1
我的谷歌技能是JavaFX抱怨我从一个单独的线程访问tableview.我可以理解,但是如何以这样的方式访问它:当tableview确实添加了一个新项目时,它会向下滚动到它?
如果您需要更多信息,请与我们联系.
所以我正在将我的 Swing Java 数据库应用程序移植到 Java FX(这里仍然是初学者,我最近刚刚学习了 FXML 和 MVC 模式的基础知识,所以请耐心等待)。
我打算将现有数据库中的数据加载到“学生”ObservableList 中,以便我可以在 TableView 上显示它,但是在我的原始 Swing 代码中,我有一个搜索 TextField,当用户单击按钮或按 Enter 时,该程序:
然而,Java FX 是一个完全不同的野兽(或者至少在我看来是这样——不要误会我的意思,我喜欢 Java FX :D)所以我不知道该怎么做。
所以,我的问题是,我是否必须加载数据库中的所有学生,然后使用一些 Java 代码过滤掉不符合搜索条件的学生(并在搜索文本为空白时显示所有学生),或者执行我仍然使用 SQLite 来过滤和检索记录(这意味着我需要清除列表然后在每次执行搜索时添加学生,也许它也会弄乱绑定?也许这种方法也会有速度损失? 除此之外,它还将重置当前选择的记录,因为我清除了列表——基本上,糟糕的 UI 设计会对可用性产生负面影响)
根据正确的方法,还有一个后续问题(抱歉,即使在谷歌搜索之后我也真的找不到这些问题的答案):
我也有将选定的表项设置为与搜索字符串匹配的第一条记录的想法,但我认为这将很难使用,因为每次搜索只能突出显示一条记录。即使我们突出显示多行,也很难浏览所有选定的项目。
请给我正确的方法,而不是“简单”的方法。这是我第一次实现模式(MVC 还是我真的在做 MVP,我不知道),我意识到我以前的程序是多么难以维护和丑陋,因为我使用了自己的风格。这是一个相对较大的项目,我需要几年来支持和改进,因此拥有干净的代码和以正确的方式做事应该有助于维护该程序的功能。
非常感谢您的帮助,我希望我在问这些问题时不会被认为是“甚至不会谷歌的愚蠢人”。请多多包涵。
我目前正在创建一个Java应用程序,其中包含使用Java FX创建的UI.我的应用程序界面分为三个单独的选项卡.在第一个选项卡上,我有很多按钮可以启动其他应用程序.我的目标是让用户按特定顺序启动这些应用程序,因此在上一个应用程序的进程完成之前,后续按钮被禁用,然后启用它们.我通过使用线条完成了这一点
Process p = Runtime.getRuntime().exec(application);
p.waitFor();
Run Code Online (Sandbox Code Playgroud)
然后控制器启用界面中的下一个按钮.启动的应用程序运行时出现问题.由于我的应用程序等待进程结束,任务管理器显示我的Java应用程序没有响应,并且您无法导航到其他选项卡.当然,当启动的应用程序完成后,我的应用程序正常运行.
我认为这是由于主线程被阻塞,因为它正在等待一个进程完成.最好的解决方案是在单独的线程上运行此进程,以便在等待已启动的进程完成时,应用程序的其余部分是否可用?
我只是尝试在我的代码中访问ERP时显示加载动画,如下所示:
protected void submit()
{
messageField.getStyleClass().add("smallLoading");
submitImpl();
messageField.getStyleClass().remove("smallLoading");
}
Run Code Online (Sandbox Code Playgroud)
遗憾的是,动画从未显示过……只是以前的结果。我尝试使用Platform.runLater,产生了相同的结果。我还传输了工作线程中的最后两行,该行有效(显示了动画),但是当提交者尝试写入我的消息字段时,导致错误“不在FX应用程序线程上”。当我将Thread传递给Platform.runLater它时,它没有显示动画……我用Google搜索了一下,但找不到解决方案。也许我错过了一些重要的事情...
感谢您的帮助。谢谢!
我正在与Javafx和线程同时工作,我一直遇到这个问题,我做了一个按钮然后当点击按钮时(使用事件处理程序)我做了一个for循环,将按钮更改为1,2,3,4 ,5然后在每个中间延迟一秒钟.倒计时!
但是发生的事情是延迟5秒并将按钮文本更改为5.
问题是我希望看到它在1到5之间变化,但我看到的只有在5秒延迟结束时为5.我会认为它改变了按钮文本,但我没有看到它.我可能不得不.show()在Javafx课堂上使用该方法.
public class HewoWorld extends Application implements EventHandler<ActionEvent>
{
Thread t = new Thread();
Button butt;
boolean buttWasClicked = false;
Circle circ1 = new Circle(40, 40, 30, Color.RED);
Circle circ2 = new Circle(100, 100, 30, Color.BLUE);
Group root;
Scene scene;
Stage disStage = new Stage();
int i = 1;
public static void main(String[] args)
{
launch(args);
}
public void start(Stage stage) throws Exception
{
disStage.setTitle("tests stuffs");
Screen screen = Screen.getPrimary();
Rectangle2D bounds = …Run Code Online (Sandbox Code Playgroud)