JavaFX桌面应用未响应问题解决方案

日常使用软件的过程中,偶尔会遇到软件突然卡住,再点击几次就变成“未响应”的情况。

在JavaFX应用中同样也会出现这种情况,在开发过程中应该尽量避免这种情况的出现。

1. “未响应”重现

应用程序出现“未响应”这种情况往往是因为在UI线程中处理一些耗时的业务,当UI线程在处理耗时的业务时,UI就会卡住。
下面通过一个示例(获取Google页面title信息)来演示一下“未响应”这种情况。

这里使用 jsoup 来抓取Google页面的title信息,需要引入jsoup的maven依赖:

<dependency>
 <groupId>org.jsoup</groupId>
 <artifactId>jsoup</artifactId>
 <version>1.13.1</version>
</dependency>

编译AppService,实现抓取Google页面的title信息。

public class AppService {
  public static final AppService INSTANCE = new AppService();
  private AppService() {
  }
  public String visitGoogle() {
    try {
      Document document = Jsoup.parse(new URL("https://www.google.com"), 10_000);
      return document.head().getElementsByTag("title").get(0).text();
    } catch (Exception e) {
      return e.getMessage();
    }
  }
}

因为没有F墙,这里访问Google肯定是超时的,这里设置了超时10秒。

接着改造AppUI,当点击Go按钮的时候,调用visitGoogle并将结果显示在界面上。

public class AppUI implements Initializable {
  public Label text;
  private AppService appService = AppService.INSTANCE;
  private AppModel model = new AppModel();
  @Override
  public void initialize(URL location, ResourceBundle resources) {
    text.textProperty().bindBidirectional(model.textProperty());
    model.setText("Hello JavaFX.");
  }
  public void click(ActionEvent event) {
    model.setText(appService.visitGoogle());
  }
}

运行JavaFX应用,当点击第一个Go按钮之后,再点击其他按钮界面就会卡住,出现“未响应”的现象。

2. UI线程、业务线程分离

前面有提到,出现“未响应”这种情况是因为在UI线程中处理一些耗时的业务,当UI线程在处理耗时的业务时,UI就会卡住。
所以如果能将UI线程和业务线程分开来,这样就能解决界面卡住的问题了。

改造一下AppUI,将调用visitGoogle的代码放到新线程去执行。

public void click(ActionEvent event) {
  new Thread(() -> model.setText(appService.visitGoogle())).start();
}

这里直接采用new的方式创建线程,实际应用中最好是使用线程池。

虽然将业务代码放在新线程中处理解决了界面卡住的问题,但是上面的代码中,通过model.setText()来改变标签(Label)的文字。
实际上会发现程序运行后会出现异常,一旦我们在非UI线程中尝试改变UI效果,程序就会抛出下面的异常。

界面卡住的问题虽然解决了,但又出现了新的问题。

3. 在UI线程更新UI

在UI线程处理业务会导致界面卡住,在业务线程更新UI会出现异常,为了能在业务线程中更新UI,JavaFX为开发者提供了一个Platform类。
只需要在业务线程中,将更新UI的代码放在这个类的runLater方法中执行即可。

下面再次改造AppUI

public void click(ActionEvent event) {
  new Thread(() -> {
    String title = appService.visitGoogle();
    Platform.runLater(() -> model.setText(title));
  }).start();
}

这里还是将业务代码放在新线程中执行,但是涉及UI更新的代码model.setText()则放在Platform.runLater()里面执行。
这样,就解决了界面卡住以及非UI线程更新UI出现异常的问题了。

通过改造,虽然请求Google超时了,但是UI并没有卡住,同时界面也得到了更新。

所以特别注意,在开发过程中应该尽量避免:

在UI线程中处理业务在业务线程中更新UI

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • javafx tableview鼠标触发更新属性详解

    本文实例为大家分享了javafx tableview鼠标触发更新属性,供大家参考,具体内容如下 public class HoverCell extends TableCell<Person, String> { public HoverCell(StringProperty hoverProperty) { setOnMouseEntered(e -> hoverProperty.set(getItem())); setOnMouseExited(e -> hoverProper

  • Javafx实现国际象棋游戏

    本文实例为大家分享了Javafx实现国际象棋游戏的具体代码,供大家参考,具体内容如下 基本规则 棋子马设计"日"的移动方式 兵设计只能向前直走,每次只能走一格.但走第一步时,可以走一格或两格的移动方式 请为后设计横.直.斜都可以走,步数不受限制,但不能越子的移动方式. 车只能横向或者竖向行走 国王是在以自己为中心的九宫格内行走 骑士只能走对角线 项目目录结构 UML类图关系 以骑士为例 实现基本功能 吃子 不能越子 游戏结束提示 基本移动策略 背景音乐 效果 控制器 PressedAc

  • JavaFX Application应用实例

    下面代码演示的是JavaFX进程命令行参数的实例.大家可以参阅一下. import java.util.List; import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.effect.SepiaTone; import javafx.scene.image.Imag

  • JavaFX 监听窗口关闭事件实例详解

    1.写在前面 在JavaFX的程序开发的时候,在使用多线程的时候,默认情况下在程序退出的时候,新开的线程依然在后台运行. 在这种情况下,可以监听窗口关闭事件,在里面关闭子线程. 2.具体实现的样例 package sample; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import java

  • javafx实现五子棋游戏

    需求描述 一个五子棋游戏,能实现双方黑白对决,当一方获胜时给出提示信息,利用GUI界面实现 项目结构如下图 一.实体 FiveChess类 提供五子棋实体包含的所有信息 判断游戏是否结束 play方法改变chess[][]棋盘中的数据 package entity; import javafx.scene.control.Alert; public class FiveChess{ public double getWidth() { return width; } public void se

  • JavaFX实现UI美观效果代码实例

    相对于Swing来说,JavaFX在UI上改善了很多,不仅可以通过FXML来排版布局界面,同时也可以通过CSS样式表来美化UI. 其实在开发JavaFX应用的时候,可以将FXML看做是HTML,这样跟CSS结合起来就跟开发WEB应用差不多,只不过两者之间的语法有点差异. 1. JavaFX CSS语法 JavaFX CSS样式跟HTML中的CSS样式很大程度上是相似的,比如class选择器.组合选择符.伪元素等. .root { -fx-body-color : #F5F5F5; -fx-out

  • 详解JavaFX桌面应用开发-Group(容器组)

    1:Group的功能 Group可以管理一组节点 Group可以对管理的节点进行增删改查的操作 Group可以管理节点的属性 1.2:看看JDKSE1.9的API Group类有下列可以调用的方法 2:Group的使用 代码如下: package application; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.

  • JavaFX实现石头剪刀布小游戏

    用JavaFX写一个石头剪刀布的小游戏,供大家参考,具体内容如下 课程上布置的作业,其实java很少用来写这种程序的 - GUI界面部分 - 石头剪刀布的逻辑部分 书上教的是JavaFX,其实还有很多方法,书上说AWT和Swing基本上淘汰了,但事实上- 代码 MyJavaFX.java package cn.homework; import javafx.application.Application; import javafx.event.ActionEvent; import javaf

  • JavaFX桌面应用未响应问题解决方案

    日常使用软件的过程中,偶尔会遇到软件突然卡住,再点击几次就变成"未响应"的情况. 在JavaFX应用中同样也会出现这种情况,在开发过程中应该尽量避免这种情况的出现. 1. "未响应"重现 应用程序出现"未响应"这种情况往往是因为在UI线程中处理一些耗时的业务,当UI线程在处理耗时的业务时,UI就会卡住. 下面通过一个示例(获取Google页面title信息)来演示一下"未响应"这种情况. 这里使用 jsoup 来抓取Googl

  • opencv python 图片读取与显示图片窗口未响应问题的解决

    显示图像是 Opencv最基本的操作之一, imshow()函数可以实现该操作.如果使用过其他GUI框架背景,就会很自然地调用 imshow来显示一幅图像.但这个观点并不完全正确,因为图像确实会显示出来,但随即会消失. 例如下面代码: import cv2 import numpy as np img = cv2.imread('C://Users/yefci/Pictures/0.2.jpg') cv2.imshow('C://Users/yefci/Pictures/0.2.jpg',img

  • 详解SpringBoot统一响应体解决方案

    前言 最近在优化自己之前基于Spring AOP的统一响应体的实现方案. 什么是统一响应体呢?在目前的前后端分离架构下,后端主要是一个RESTful API的数据接口. 但是HTTP的状态码数量有限,而随着业务的增长,HTTP状态码无法很好地表示业务中遇到的异常情况. 那么可以通过修改响应返回的JSON数据,让其带上一些固有的字段,例如以下这样的 { "code": 10000, "msg": "success", "data"

  • nodejs发送http请求时遇到404长时间未响应的解决方法

    通常,我们在使用nodejs发送http请求时,一旦遇到404响应,nodejs内部会一直请求下去,直到超出它自己设定的响应时长(最让人恶心的地方就是这个时长还是没法修改的.)很多人在这里碰到了麻烦. 我是在做arcgis地图项目的时候,客户提出需要使用天地图提供的底图服务,当时我直接使用silverlight客户端的Arcgis API进行http请求(同样是内部请求,不开源的东西就是这么让人郁闷),同样碰到了一个进度条一直卡在那的问题.经过调试发现,是由于底图加载请求超时的缘故,和nodej

  • 微信小程序授权登录解决方案的代码实例(含未通过授权解决方案)

    本文实例为大家分享了微信小程序授权登录解决方案的具体代码,供大家参考,具体内容如下 getUserInfoF:function(){ var that = this; wx.getSetting({ success: (res) => { console.info(res.authSetting); wx.getUserInfo({ success: res => { this.globalData.userInfo = res.userInfo console.info("一开始同

  • iOS开发之事件传递响应链

    当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图.在我们点击屏幕的时候,iphone OS获取到了用户进行了"单击"这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UIEvent形式的实例,然后找到当前运行的程序,逐级寻找能够响应这个事件的对象,直到没有响应者响应.这一寻找的过程,被称作事件的响应链,如下图所示,不用的响应者以链式的方式寻找 事件响应链 一.响应者 在iOS中,能够响应事件的对象都是UIResponder的子类对象.UIResponder提供了

  • Python爬虫headers处理及网络超时问题解决方案

    1.请求headers处理 我们有时请求服务器时,无论get或post请求,会出现403错误,这是因为服务器拒绝了你的访问,这时我们可以通过模拟浏览器的头部信息进行访问,这样就可以解决反爬设置的问题. import requests # 创建需要爬取网页的地址 url = 'https://www.baidu.com/' # 创建头部信息 headers = {'User-Agent':'OW64; rv:59.0) Gecko/20100101 Firefox/59.0'} # 发送网络请求

  • 深度解析 Vue3 的响应式机制

    目录 什么是响应式 响应式原理 定制响应式数据 Vueuse 工具包 什么是响应式 响应式一直都是 Vue 的特色功能之一:与之相比,JavaScript 里面的变量,是没有响应式这个概念的:你在学习 JavaScript 的时候首先被灌输的概念,就是代码是自上而下执行的: 我们看下面的代码,代码在执行后,打印输出的两次 double 的结果也都是 2:即使 我们修改了代码中 count 的值后,double 的值也不会有任何改变 let count = 1 let double = count

  • AJAX 简介及入门实例

    对于一个像我一样刚刚接触Web开发且无多少实际项目经验的新手而言,AJAX技术显得复杂而又深奥.经过两天的baidu.google,我对AJAX的基本原理有了一个大致的认识,在此总结一下. 1. 什么是AJAX? AJAX全称是异步的JavaScript和XML,是Asynchronous JavaScript and XML的缩写.AJAX技术用于创建交互式网页应用的网站开发,至于何为异步,后文会有解释. 1.1 桌面应用程序和Web应用程序 在详细讨论AJAX技术之前,需要先知道AJAX技术

随机推荐