JavaFX:如何从不同的线程(Netty)填充数据到TableView

时间:2017-08-09 06:50:07

标签: java multithreading tableview javafx-8 netty

我有以下代码。 tableview不显示GUI上的记录,为空。 我如何将值从ServerHandler线程传递给JAVAFX UI线程。

你能建议吗? 感谢

更新

主要课程

public class Main extends Application {
private static Stage stage;
@Override
public void start(Stage primaryStage){
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("mainpane.fxml"));
    fxmlLoader.load();
    setStage(primaryStage);
    Parent root = fxmlLoader.getRoot(); 
    Scene scene = new Scene(root,800,800);
    primaryStage.setScene(scene);
    primaryStage.show();
}
public static void main(String[] args) {
    new Thread(() -> launch(Main.class, args)).start();
    new MyServer().startDownload();
}

控制器

public class SampleController {
private ObservableList<Model> tableData = FXCollections.observableArrayList();
@FXML
private TableView<Model> table;
@FXML
private TableColumn<Model, String> firstCol;
@FXML
private TableColumn<Model, String> secondCol;   
@FXML
public void initialize() {
    table.setEditable(false);
    firstCol.setCellValueFactory(cellData -> cellData.getValue().getName());
    secondCol.setCellValueFactory(cellData -> cellData.getValue().getCurrent());
    table.setItems(tableData);
}
public void addModel(ChannelFuture sendFileFeture,Model model){
    table.getItems().add(Model);
    System.out.println("row model= "+model.getName().get());// it works fine;
    sendFileFeture.addListener(model);
}

带有Netty 4的Server类

public class ServerHandler extends SimpleChannelInboundHandler<FullHttpRequest>{
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
    //some codes
    Model model=new Model(file.getName(),fileLength+"");
    SampleController sc=new SampleController();
    sc.addModel(sendFileFeture, model);
}

具有Netty的ChannelProgressiveFutureListener的Model类

public class Model implements ChannelProgressiveFutureListener{
private SimpleStringProperty name=null;
private SimpleStringProperty current=null;

public Model(String name,String current){
    this.name=new SimpleStringProperty(name);
    this.current=new SimpleStringProperty(current);
}

@Override
public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) throws Exception {
    System.out.println("current: "+current+",progress: "+progress); //it works fine
    current.set(progress+""); // can not update the TableView
}
@Override
public void operationComplete(ChannelProgressiveFuture future) throws Exception {
}

public void setName(String name) {
    this.name.set(name);
}
public SimpleStringProperty getName() {
    return name;
}
public void setCurrent(String current) {
    this.current.set(current);
}
public SimpleStringProperty getCurrent() {
    return current;
}

更新

tableview没有以正确的大小更新,我加载的图像是2,407,257字节。你可以在下面的图像中找到错误。

image1 image2

secondCol.setCellValueFactory(cellData -> cellData.getValue().getCurrent());
secondCol.setCellFactory(column -> {return new TableCell<Model, String>() {
            @Override
            protected void updateItem(String item, boolean empty) {
                System.out.println(item); //UPDATING NOT CURRECT
                super.updateItem(item, empty);
                setText(empty ? "" : getItem().toString());
            }
        };

1 个答案:

答案 0 :(得分:1)

UI没有显示任何内容,因为您正在为正在显示的表填充不同的表,而不是因为线程(虽然您也有线程问题,或者一旦解决了初始问题就会执行)。

start()方法中,加载FXML,创建TableView及其列,并创建控制器实例。您的ServerHandler类创建了一个控制器的新实例,该实例又创建了一个新的TableView实例(总是错误地初始化带注释的变量{{1 }})。永远不会显示@FXML实例。因此,当您的TableView填充表时,它会填充一个实际上不属于UI的表,并且您看不到任何内容。

ServerHandler的创建移动到MyServer方法,并将其传递给现有的控制器实例:

start()

您的public class Main extends Application { private Stage stage; @Override public void start(Stage primaryStage){ FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("mainpane.fxml")); fxmlLoader.load(); setStage(primaryStage); Parent root = fxmlLoader.getRoot(); Scene scene = new Scene(root,800,800); primaryStage.setScene(scene); primaryStage.show(); SampleController controller = loader.getController(); new Thread(() -> new MyServer(controller).startDownload()).start(); } public static void main(String[] args) { launch(args); } } 类应该将控制器传递给MyServer实例。由于在后台线程上调用ServerHandler方法,因此需要使用ServerHandler来更新UI:

Platform.runLater(...)

最后,不要初始化应该由public class ServerHandler extends SimpleChannelInboundHandler<FullHttpRequest>{ private final SampleController sc ; public ServerHandler(SampleController sc) { this.sc = sc ; } @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { //some codes Model model=new Model(file.getName(),fileLength+""); Platform.runLater(() -> { sc.addModel(sendFileFeture, model); sc.addRowModel(sendFileFeture, rowModel); }); } } 初始化的字段。这只会产生抑制任何表明你的控制器-FXML绑定没有正确设置的FXMLLoader的效果:

NullPointerException