使用javafx更新UI的方法
使用javafx更新UI
JavaFx如果在子線程中更新UI,不論是task還是runable都會(huì)報(bào)錯(cuò)
java.lang.IllegalStateException: Not on FX application thread; currentThread =
這種情況可以使用下面的方法
1,Platform.runLater()
這個(gè)辦法在當(dāng)前線程不是javafx的線程中,比如runnable,thread這些的,直接調(diào)用即可,runLater()不是線程阻塞型的,在javafx的主線程完全清空或者說(shuō)空閑的時(shí)候,它才會(huì)執(zhí)行,
Platform.runLater(new Runnable() {
@Override
public void run() {
//更新JavaFX的主線程的代碼放在此處
p.cancelProgressBar();
}
});
但是如果必須先執(zhí)行這段代碼怎么辦呢,也有方法
1,future是個(gè)工作線程
他允許阻塞當(dāng)前線程,執(zhí)行線程中的代碼,在拿到返回值后,才會(huì)順序執(zhí)行
// 定義一個(gè)FutureTask,然后 Plateform.runLater() 這個(gè)futuretask
final FutureTask<String> query = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
// 新建一個(gè)窗口(方法中將創(chuàng)建stage)
VcodeController vc = new VcodeController();
return vc.show(url4vcode);
}
});
Platform.runLater(query); // 重點(diǎn)
String vcode = query.get(); // 這樣就能獲取返回值
System.out.println(vcode);
2,利用 CountDownLatch,直接阻塞當(dāng)前的主線程,執(zhí)行相關(guān)代碼業(yè)務(wù)
/**
* Runs the specified {@link Runnable} on the
* JavaFX application thread and waits for completion.
*
* @param action the {@link Runnable} to run
* @throws NullPointerException if {@code action} is {@code null}
*/
public static void runAndWait(Runnable action) {
if (action == null)
throw new NullPointerException("action");
// run synchronously on JavaFX thread
if (Platform.isFxApplicationThread()) {
action.run();
return;
}
// queue on JavaFX thread and wait for completion
final CountDownLatch doneLatch = new CountDownLatch(1);
Platform.runLater(() -> {
try {
action.run();
} finally {
doneLatch.countDown();
}
});
try {
doneLatch.await();
} catch (InterruptedException e) {
// ignore exception
}
}
3.使用task線程的返回值
task是javafx實(shí)現(xiàn)的ui線程,他實(shí)現(xiàn)了futureTask和worlker線程,所以它既可以當(dāng)普通線程來(lái)使用,也可以重寫返回值方法,實(shí)現(xiàn)ui界面的刷新
不過(guò)要說(shuō)明的是,task的call方法,仍然是一個(gè)普通線程的方法,如果要實(shí)現(xiàn)在task中刷新ui界面,要在
scheduled(),succeeded(),running()任意一個(gè)方法中執(zhí)行,就可以了,這樣就實(shí)現(xiàn)了再task的線程中,刷新界面的功能
package com.yz.readismqtest1;
import javafx.concurrent.Task;
public class deda {
public static void main(String[] args) {
Task task = new Task() {
@Override
protected Object call() throws Exception {
//執(zhí)行普通方法
return null;
}
@Override
protected void scheduled() {
//更新JavaFX的主線程的代碼放在此處
super.scheduled();
}
@Override
protected void succeeded() {
//更新JavaFX的主線程的代碼放在此處
super.succeeded();
}
@Override
protected void running() {
//更新JavaFX的主線程的代碼放在此處
super.running();
}
};
}
}
JavaFX的并發(fā)編程與UI更新
JavaFX并發(fā)編程與UI更新
項(xiàng)目需求
根據(jù)項(xiàng)目需要,進(jìn)行設(shè)備的并發(fā)測(cè)試,同時(shí)需要在界面上實(shí)時(shí)展示測(cè)試的結(jié)果
涉及到的技術(shù)
1、使用Observer的方式實(shí)現(xiàn)多個(gè)對(duì)象之間的通信(觀察者模式)
2、因?yàn)閁I只有一個(gè),需要在較短時(shí)間內(nèi)接收并顯示大量的數(shù)據(jù),所以使用了javafx.concurrent
3、線程池pool,減少對(duì)象的資源占用
上述技術(shù)的使用參考了大量的網(wǎng)絡(luò)資源和書籍內(nèi)容,再次不進(jìn)行一一列舉,感謝各位作者。
核心代碼
// 1、從線程池中獲取對(duì)象
ObjectPoolDrawUIService objPool = ObjectPoolDrawUIService.getInstance();
DrawUIService obj = (DrawUIService)objPool.getObject();
// 2、對(duì)象的初始化 produceCaseResult是需要更新的數(shù)據(jù)內(nèi)容 ,i是行號(hào)信息,放在Object[]中進(jìn)行傳遞
obj.init(new Object[]{produceCaseResult,i}, new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent t) {
Object[] objArray = (Object[])t.getSource().getValue();
testDetailList.set((int) objArray[1], (ProduceCaseResult)objArray[0]);
// 4、因?yàn)槭窃诰€程中執(zhí)行,所以 returnObject代碼不能跟在obj.restart后面,會(huì)導(dǎo)致被很快的restart
objPool.returnObject(obj);
}
});
// 3、執(zhí)行
obj.restart(); // 因?yàn)槭菑膒ool中獲取,可能已經(jīng)執(zhí)行完畢,所以restart
以上代碼中需要特別注意,代碼4的位置,以下代碼為javafx.concurrent的核心代碼
public class DrawUIService extends Service<Object[]>{
Object[] showData = {null,null};
public void init(Object[] showData, EventHandler<WorkerStateEvent> eventHandler) {
this.showData = showData;
setOnSucceeded(eventHandler);
}
@Override
protected Task<Object[]> createTask() {
return new Task<Object[]>() {
@Override
protected Object[] call() throws Exception {
return showData;
}
};
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java驗(yàn)證用戶是否已經(jīng)登錄 java實(shí)現(xiàn)自動(dòng)登錄
這篇文章主要介紹了java驗(yàn)證用戶是否已經(jīng)登錄,java實(shí)現(xiàn)自動(dòng)登錄,感興趣的小伙伴們可以參考一下2016-04-04
mybatis 多表關(guān)聯(lián)mapper文件寫法操作
這篇文章主要介紹了mybatis 多表關(guān)聯(lián)mapper文件寫法操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
SpringBoot中@Scheduled實(shí)現(xiàn)服務(wù)啟動(dòng)時(shí)執(zhí)行一次
本文主要介紹了SpringBoot中@Scheduled實(shí)現(xiàn)服務(wù)啟動(dòng)時(shí)執(zhí)行一次,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08
Spring循環(huán)依賴正確性及Bean注入的順序關(guān)系詳解
這篇文章主要給大家介紹了關(guān)于Spring循環(huán)依賴的正確性,以及Bean注入的順序關(guān)系的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
Java連接postgresql數(shù)據(jù)庫(kù)的示例代碼
本篇文章主要介紹了Java連接postgresql數(shù)據(jù)庫(kù)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
java實(shí)現(xiàn)識(shí)別二維碼圖片功能方法詳解與實(shí)例源碼
這篇文章主要介紹了java實(shí)現(xiàn)識(shí)別二維碼圖片,java無(wú)法識(shí)別二維碼情況下對(duì)二維碼圖片調(diào)優(yōu)功能方法與實(shí)例源碼,需要的朋友可以參考下2022-12-12
SpringBoot中優(yōu)化if-else語(yǔ)句的七種方法
if-else語(yǔ)句是控制流程的基本工具,但過(guò)度使用會(huì)使代碼變得復(fù)雜且難以維護(hù),在SpringBoot , SpringCloud項(xiàng)目中,優(yōu)化if-else結(jié)構(gòu)變得尤為重要,本文將深入探討七種策略,旨在減少SpringBoot , SpringCloud項(xiàng)目中 if-else的使用,需要的朋友可以參考下2024-07-07
java返回的List進(jìn)行add操作報(bào)錯(cuò)
本文主要介紹了java返回的List進(jìn)行add操作報(bào)錯(cuò),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
Spring零基礎(chǔ)入門WebFlux響應(yīng)式編程
Spring 提供了兩個(gè)并行堆棧,一種是基于帶有 Spring MVC 和 Spring Data 結(jié)構(gòu)的 Servlet API,另一個(gè)是完全反應(yīng)式堆棧,它利用了 Spring WebFlux 和 Spring Data 的反應(yīng)式存儲(chǔ)庫(kù),這篇文章主要介紹了Spring-webflux 響應(yīng)式編程,需要的朋友可以參考下2022-10-10
Java應(yīng)用開源框架實(shí)現(xiàn)簡(jiǎn)易web搜索引擎
本篇文章主要介紹了Java應(yīng)用開源框架實(shí)現(xiàn)簡(jiǎn)易web搜索引擎,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11

