java.lang.IllegalStateException:使用石英时不在FX应用程序上

时间:2019-07-14 12:03:40

标签: javafx

我试图在石英任务计划中使用javafx警报:

public class ChecarJob implements Job{
    private Connection con;
    public ChecarJob() {
        this.con = new ConnectionFactory().getConnection();
    }
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Executou!");
                try {
                    String verStatus = "SELECT COUNT(*) FROM equipamento_requisicao";
                    PreparedStatement stmt = con.prepareStatement(verStatus);
                        ResultSet rsStatus = stmt.executeQuery();
                        if(rsStatus.next()){
                        Alerts a = new Alerts();
                        int Resultado = rsStatus.getInt(1);
                        if(Resultado>Sessao.getInstancia().getQtdRegistroBD()){
                        Sessao.getInstancia().setQtdRegistroBD(Resultado);
                                                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("SUCESS");
                        alert.setHeaderText("SUCESS");
                        alert.setContentText("SUCESS");
                        alert.showAndWait();
                        }
                        else if(Resultado<Sessao.getInstancia().getQtdRegistroBD()){
                        Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("FAIL");
                        alert.setHeaderText("FAIL");
                        alert.setContentText("FAIL");
                        alert.showAndWait();
                        Sessao.getInstancia().setQtdRegistroBD(Resultado);
                        } 
                        else{
                        //aq não irei fazer nada.
                        }
                        }
                    }catch (Exception e) {
            e.printStackTrace();
                    }
    }   

}

在我的主班上打电话:

public void start(Stage stage) throws Exception {
    JobDetail j = JobBuilder.newJob(ChecarJob.class).build();
    Trigger t = TriggerBuilder.newTrigger().withIdentity("CroneTrigger")
            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).build();
    Scheduler s = StdSchedulerFactory.getDefaultScheduler();
    s.start();
    s.scheduleJob(j,t);

msg执行错误:

  

java.lang.IllegalStateException:不在FX应用程序线程上;   currentThread = DefaultQuartzScheduler_Worker-2Executou!

1 个答案:

答案 0 :(得分:0)

JavaFX与大多数UI工具包一样,是单线程的,也不是线程安全的。场景图一旦显示在窗口中,就只能在 JavaFX Application Thread 上进行交互。并且必须在FX线程上实例化某些对象。否则,可能会导致错误(如您所遇到的那样),或者仅导致未定义的行为。如果您使用的是后台线程,并且需要安排FX线程的操作,则可以使用Platform.runLater(Runnable)(链接到Javadoc)。

您的代码不是一个最小且完整的示例,因此我不确定所有功能。但是,总的来说,我将从将与import React from "react"; import ReactDOM from "react-dom"; import TextField from "@material-ui/core/TextField"; function App() { const [state, setState] = React.useState({ cats: [{ name: "cat1", age: "2" }, { name: "cat2", age: "5" }], owner: "Owner's Name" }); const handleFormChange = e => { if (["name", "age"].includes(e.target.dataset.fieldType)) { const newCats = [...state.cats]; newCats[e.target.dataset.id][e.target.dataset.fieldType] = e.target.value; setState({ ...state, cats: newCats }); } else { setState({ ...state, [e.target.name]: e.target.value }); } }; return ( <form onChange={handleFormChange}> <TextField label="Owner" value={state.owner} name="owner" /> <br /> <br /> <TextField label="Name 1" value={state.cats[0].name} inputProps={{ "data-id": 0, "data-field-type": "name" }} /> <TextField label="Age 1" value={state.cats[0].age} inputProps={{ "data-id": 0, "data-field-type": "age" }} /> <br /> <br /> <TextField label="Name 2" value={state.cats[1].name} inputProps={{ "data-id": 1, "data-field-type": "name" }} /> <TextField label="Age 2" value={state.cats[1].age} inputProps={{ "data-id": 1, "data-field-type": "age" }} /> </form> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement); 实例相关的所有代码移到Alert调用开始。

runLater

一些注意事项:

  • 以上使用lambda expressions
  • 完成处理后,不要忘记关闭资源(例如public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("Executou!"); try { String verStatus = "SELECT COUNT(*) FROM equipamento_requisicao"; PreparedStatement stmt = con.prepareStatement(verStatus); ResultSet rsStatus = stmt.executeQuery(); if (rsStatus.next()) { Alerts a = new Alerts(); // what does this do? int Resultado = rsStatus.getInt(1); if (Resultado > Sessao.getInstancia().getQtdRegistroBD()) { Sessao.getInstancia().setQtdRegistroBD(Resultado); // unknown side-effects Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("SUCESS"); alert.setHeaderText("SUCESS"); alert.setContentText("SUCESS"); alert.showAndWait(); }); } else if (Resultado < Sessao.getInstancia().getQtdRegistroBD()) { Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("FAIL"); alert.setHeaderText("FAIL"); alert.setContentText("FAIL"); alert.showAndWait(); }); Sessao.getInstancia().setQtdRegistroBD(Resultado); // unknown side-effects } else { //aq não irei fazer nada. } } } catch (Exception e) { e.printStackTrace(); } } PreparedStatement)。使用try-with-resources
  • ResultSet的调用不会 等待runLater返回。
  • 这里有“未知的副作用”注释,因为我不知道这些方法调用是否修改了UI。我将它们排除在Runnable调用之外,以为他们没有。
  • 我找不到实际使用runLater的地方。
  • 名称Alerts a = new Alerts()不遵循本地变量的标准Java命名约定。
  • 请注意,正确缩进代码可以使阅读和跟踪发生的事情变得更加容易。

  

我是Java的新手,对线程了解不多

对Java并发性至少没有基本的了解会阻碍您创建除最琐碎的GUI应用程序之外的所有工作。我强烈建议您在继续之前研究此主题。作为开始,请阅读以下内容:

关于这一主题的一本好书是Brian Goetz等人的 Java Concurrency in Practice