JavaFx监听serversocket并根据输入更新UI遇到了问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaFx监听serversocket并根据输入更新UI遇到了问题相关的知识,希望对你有一定的参考价值。

我有一个fx应用程序作为客户端 想通过socket和一个服务端连接 服务端每隔x秒就会向客户端发送某种数据 客户端根据数据改变UI上的内容 要实现这么一个功能我一开始直接在fx程序的start方法里面建立和服务器的socket连接 然后new一个线程 在线程里while(true)死循环监听服务端的信息 如果输入流读到东西了 就对ui做出一些操作 但是报了not on FX application thread的异常 查了之后发现了Platform.runlater这个东西 这次倒是不报错了 但是我发现还是无法实现我想要的功能 因为在while循环里的ui操作并不生效 只有break;之后才会生效 有没有大神知道怎么实现 我对线程和fx基本没什么理解 很多东西都是会用不知道为什么 所以遇到这种问题就很迷茫start方法大概就是这样 开启服务器并运行客户端 程序会陷入无响应 并且changeUI(n)的改变不生效 如果在最后加个break退出while循环的话就可以正常运行 对UI的更改也会生效 我不理解 对UI的更改明明在当次循环内发生 为什么会和是否退出循环有关系?是否是因为runlater机制的原因?望解惑
我试验了之后发现即使不在runLater中 直接在javafx的主线程里建立socke连接并在所有东西初始化完毕后用while(true)监听服务端 在这个while中对ui的操作也会出现不生效的问题 为什么?

参考技术A

    import java.util.Timer;  

    import java.util.TimerTask;  

    public class MainController   

    /**  

    * 自动更新的下拉框,触发的事件  

    * @param event  

    * @throws IOException  

    */  

    @FXML protected void handleautoRunUpdateCombox(ActionEvent event) throws IOException  

    Timer timer = new Timer();  

    timer.schedule(new TimerTask()   

    public void run()   

    Platform.runLater(new Runnable()   

    @Override  

    public void run()   

    roleOneEvent();  //更新ui代码  

      

    );  

      

    , 1000, 5000); //定时器的延迟时间及间隔时间  

      

    原理就是创建一个Timer,并创建一个任务TimerTask,在任务的run方法里面执行:  

    Platform.runLater(new Runnable()   

    @Override  

    public void run()   

    roleOneEvent();  //更新ui代码  

      

    );  

    这样子就可以达到更新UI界面上控件的显示内容了,显示如下:  

JAVAFX-5事件总结

事件监听

在RIA 或者说 桌面客户端gui android 开发中,事件的机制是必须的要学习了解的,

分类处理类型

在Java GUI 和swing中,事件通常通过实现listener的接口函数,并通过addXXXListener 或者 setOnXXXListener的形式来设置接口函数来实现事件的执行。

-因此JavaFX的监听分为两种:

  • 控件级别监听 ----->setonxxxxxxx()
  • 属性级别监听 ----->onxxxxxxProperty().addxxxxxxx()
    然而在JavaFX中,只有极少数的事件是遵循Java GUI和Android的模式即控件级别的监听,例如,按钮的点击事件 。还增加了 触摸事件 onTouch() 事件

  • 这里要特别说一下: 如果要一个类实现监听所有的鼠标事件,一般的方法是传参数类值过去,然后判断操作,但是这样不能实现操作

package application;

import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;

public class myHandlert implements EventHandler<MouseEvent> {

    @Override
    public void handle(MouseEvent event) {
        System.out.println(event.getSource());
        if (event.getSource()=="Button[id=btnEraser, styleClass=button]'橡皮擦'") {
            System.out.println(1);
        }
        if (event.getSource().equals("Button[id=btnBrush, styleClass=button]'画笔'")) {
            System.out.println(2);
        }
    }

}
  • 控件级别监听(代码量少可以使用):
Button btn = new Button();
btn.setOnAction(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        doing codeing
    }
});
  • 2.实现EventHandler接口,单独类创建事件代码,与主代码分离,我更青睐这种方式,可以统一管理事件,UI与具体事件分离:
Button btn = new Button();
button.addEventHandler(MouseEvent.MOUSE_EXITED, new ShadowEvent(button,false));

public class ShadowEvent implements EventHandler<MouseEvent> {

    Button button;
    DropShadow dropShadow;
    boolean select;

    public ShadowEvent(Button button,DropShadow dropShadow,boolean select){
        this.button = button;
        this.dropShadow = dropShadow;
        this.select = select;
    }

    public ShadowEvent(Button button,boolean select){
        this.button = button;
        this.select = select;
    }

    public void handle(MouseEvent event) {
        if (select){
            button.setEffect(dropShadow);
        } else {
            button.setEffect(null);
        }

    }
}
  • 属性级别监听:
    [] 比如监听checkbox是否选中,这是对selectedProperty这个属性进行监听,因此需要实现ChangeListener接口。
// CatalogCheckPage.java代码片段
checkBox.selectedProperty().addListener(new MyCheckBoxListener(checkBox,buttonOfPreEditionDataPath,textInputOfPreEditionDataPath));

// MyCheckBoxListener.java代码片段
public class MyCheckBoxListener implements ChangeListener<Boolean> {

    TextField textfield = new TextField();
    Button button = new Button();
    CheckBox checkBox;

    public MyCheckBoxListener(CheckBox checkBox,Button button,TextField textfield){
        this.checkBox = checkBox;
        this.button = button;
        this.textfield = textfield;
    }

    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue){
        boolean select = checkBox.isSelected();
        // logger.info("checkbox newValue:" + newValue +",oldValue:"+oldValue);
        if (!select) {
            textfield.setDisable(true);
            button.setDisable(true);
        } else {
            textfield.setDisable(false);
            button.setDisable(false);
        }
    }
}
  • 比如监听窗口大小的改变,这是对Stage类的widthProperty这个属性进行监听,因此需要实现ChangeListener接口,同时ChangeListener里会回调一个“属性改变前的值”和“属性改变后的值
/ MainPage.java代码片段
primaryStage.widthProperty().addListener(new StageChangeListener(primaryStage));

// StageChangeListener.java窗体变化监听,当前用来设置图标
public class StageChangeListener implements ChangeListener<Number> {

    Stage stage;

    public StageChangeListener(Stage stage){
        this.stage = stage;
    }

    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {

        stage.getIcons().add(ImageUtil.getImage("/image/tools.png"));
    }
}

所以在JavaFX中,所有跟属性改变相关的事件,都可以根据 XXX.xxxxProperty().addListener 的形式来进行事件监听。理解这种方式将极大提升我们的开发效率。这样的属性还有很多,根据需要来操作.

以上是关于JavaFx监听serversocket并根据输入更新UI遇到了问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaFx 监听系统剪贴板

简单Java Socket编程

JAVAFX-5事件总结

JavaFX实战:几种事件监听实现,键盘按键事件监听,鼠标滚轮事件监听,鼠标按键事件监听,鼠标移动事件监听

JavaFX实战:几种事件监听实现,键盘按键事件监听,鼠标滚轮事件监听,鼠标按键事件监听,鼠标移动事件监听

JavaFX实战:几种事件监听实现,键盘按键事件监听,鼠标滚轮事件监听,鼠标按键事件监听,鼠标移动事件监听