Javafx UI 在运行任务后没有响应
Javafx UI not responding after it runs Task
我正在开发 javafx 应用程序。因为我需要显示我的数据库中的一些数据,所以我开始了解在 Javafx 中使用 Task
。在 SO 上看到 后,我尝试实施它。为了检查它是否有效,我只是打印了一个团队列表,这些列表是我从哈希表中的数据库中获得的。
当我第一次启动应用程序时,数据已成功获取并显示在我的控制台上,但是当我切换场景并尝试切换回主页(正在获取数据的地方)时,UI完全卡住,甚至不显示场景。
Home.java
public class Home implements Initializable {
private Executor executor;
private TeamsDAO teamsDAO;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try{
teamsDAO = new TeamsDAO();
}catch (SQLException e){
e.printStackTrace();}
executor = Executors.newCachedThreadPool(runnable -> {
Thread th = new Thread(runnable);
th.setDaemon(true);
return th;
});
printTeams();
}
public void printTeams() {
Task<Hashtable<Integer, String>> displayTask = new Task<Hashtable<Integer, String>>() {
@Override
protected Hashtable<Integer, String> call() throws Exception {
return teamsDAO.getTeams();
}
};
displayTask.setOnFailed(e -> {
displayTask.getException().printStackTrace();
});
displayTask.setOnSucceeded(e -> {
cricProTitle.setText(displayTask.getValue().get(2));
});
executor.execute(displayTask);
}
}
我将 HikariCP 用于 postgresql 的数据库连接池。
TeamsDAO.java
public class TeamsDAO {
private Connection conn;
public TeamsDAO() throws SQLException {
this.conn = DataSource.getConnection();
}
public Hashtable<Integer, String> getTeams() throws SQLException {
try (PreparedStatement pst = conn.prepareStatement("SELECT * FROM TEAMS")) {
ResultSet rs = pst.executeQuery();
Hashtable<Integer, String> teams = new Hashtable<>();
while (rs.next()) {
teams.put(rs.getInt("team_id"), rs.getString("name"));
}
return teams;
}
}
}
UI 冻结时不显示错误堆栈跟踪。我希望这些团队显示在主页上(在线程成功运行后)。请指出我哪里出错了?
当我在 initialize
方法中启动 TeamsDAO
对象时,每次我切换回主控制器时它都会创建一个新的数据库连接,因此会填满连接池。为了解决这个问题,我在 Home.java 中创建了一个静态块,并只获取了一次我需要的数据。
已更新Home.java:
public class Home implements Initializable {
private static TeamsDAO teamsDAO;
@FXML
private BorderPane borderPane;
@FXML
private Label cricProTitle;
@FXML
private Label homepageLabel;
@FXML
private Label banner;
@FXML
private GridPane buttonContainer;
static {
try {
teamsDAO = new TeamsDAO();
} catch (SQLException e) {
e.printStackTrace();
}
Task<Hashtable<Integer, String>> task = new Task<>() {
@Override
protected Hashtable<Integer, String> call() throws Exception {
return teamsDAO.getTeams();
}
};
task.setOnSucceeded(e -> {
System.out.println(task.getValue());
});
Thread x = new Thread(task);
x.setDaemon(true);
x.start();
System.out.println(x.getState());
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
//setting UI properties here..
}
}
我正在开发 javafx 应用程序。因为我需要显示我的数据库中的一些数据,所以我开始了解在 Javafx 中使用 Task
。在 SO 上看到
当我第一次启动应用程序时,数据已成功获取并显示在我的控制台上,但是当我切换场景并尝试切换回主页(正在获取数据的地方)时,UI完全卡住,甚至不显示场景。
Home.java
public class Home implements Initializable {
private Executor executor;
private TeamsDAO teamsDAO;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try{
teamsDAO = new TeamsDAO();
}catch (SQLException e){
e.printStackTrace();}
executor = Executors.newCachedThreadPool(runnable -> {
Thread th = new Thread(runnable);
th.setDaemon(true);
return th;
});
printTeams();
}
public void printTeams() {
Task<Hashtable<Integer, String>> displayTask = new Task<Hashtable<Integer, String>>() {
@Override
protected Hashtable<Integer, String> call() throws Exception {
return teamsDAO.getTeams();
}
};
displayTask.setOnFailed(e -> {
displayTask.getException().printStackTrace();
});
displayTask.setOnSucceeded(e -> {
cricProTitle.setText(displayTask.getValue().get(2));
});
executor.execute(displayTask);
}
}
我将 HikariCP 用于 postgresql 的数据库连接池。
TeamsDAO.java
public class TeamsDAO {
private Connection conn;
public TeamsDAO() throws SQLException {
this.conn = DataSource.getConnection();
}
public Hashtable<Integer, String> getTeams() throws SQLException {
try (PreparedStatement pst = conn.prepareStatement("SELECT * FROM TEAMS")) {
ResultSet rs = pst.executeQuery();
Hashtable<Integer, String> teams = new Hashtable<>();
while (rs.next()) {
teams.put(rs.getInt("team_id"), rs.getString("name"));
}
return teams;
}
}
}
UI 冻结时不显示错误堆栈跟踪。我希望这些团队显示在主页上(在线程成功运行后)。请指出我哪里出错了?
当我在 initialize
方法中启动 TeamsDAO
对象时,每次我切换回主控制器时它都会创建一个新的数据库连接,因此会填满连接池。为了解决这个问题,我在 Home.java 中创建了一个静态块,并只获取了一次我需要的数据。
已更新Home.java:
public class Home implements Initializable {
private static TeamsDAO teamsDAO;
@FXML
private BorderPane borderPane;
@FXML
private Label cricProTitle;
@FXML
private Label homepageLabel;
@FXML
private Label banner;
@FXML
private GridPane buttonContainer;
static {
try {
teamsDAO = new TeamsDAO();
} catch (SQLException e) {
e.printStackTrace();
}
Task<Hashtable<Integer, String>> task = new Task<>() {
@Override
protected Hashtable<Integer, String> call() throws Exception {
return teamsDAO.getTeams();
}
};
task.setOnSucceeded(e -> {
System.out.println(task.getValue());
});
Thread x = new Thread(task);
x.setDaemon(true);
x.start();
System.out.println(x.getState());
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
//setting UI properties here..
}
}