JavaFX:如何从不同的线程(Netty)将数据填充到 TableView
JavaFX: How to populate data to TableView from different Thread(Netty)
我有以下代码。 tableview 不显示 GUI 上的记录,为空。
我如何将值从 ServerHandler 线程传递到 JAVAFX UI 线程。
你能推荐一下吗?
谢谢
更新
主要class
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);
}
服务器 class 使用 Netty 4
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的模型class
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 bytes.you 可以在下面的图像中找到错误。
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());
}
};
UI 没有显示任何内容,因为您填充的 table 与您正在显示的不同,而不是因为线程(尽管您也有线程问题,或者一旦您会这样做解决最初的问题)。
在您的 start()
方法中,您加载 FXML,它创建一个 TableView
及其列,并创建一个控制器实例。您的 ServerHandler
class 创建了一个新的控制器实例,它又创建了一个 TableView
的新实例(总是 初始化错误注释的变量 @FXML
)。 TableView
实例永远不会显示。因此,当您的 ServerHandler
填充 table 时,它填充的 table 实际上不是 UI 的一部分,您什么也看不到。
将 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
class 应该依次将控制器传递给 ServerHandler
个实例。由于 ServerHandler
方法是在后台线程上调用的,因此它们需要使用 Platform.runLater(...)
来更新 UI:
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);
});
}
}
最后,不要初始化应该由 FXMLLoader
初始化的字段。这只会产生抑制任何表明您的控制器-FXML 绑定未正确设置的 NullPointerException
的效果:
public class SampleController {
private ObservableList<Model> tableData = FXCollections.observableArrayList();
@FXML
private TableView<RowModel> 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().getProgress());
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(rowModel);
}
}
我有以下代码。 tableview 不显示 GUI 上的记录,为空。 我如何将值从 ServerHandler 线程传递到 JAVAFX UI 线程。
你能推荐一下吗? 谢谢
更新
主要class
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);
}
服务器 class 使用 Netty 4
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的模型class
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 bytes.you 可以在下面的图像中找到错误。
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());
}
};
UI 没有显示任何内容,因为您填充的 table 与您正在显示的不同,而不是因为线程(尽管您也有线程问题,或者一旦您会这样做解决最初的问题)。
在您的 start()
方法中,您加载 FXML,它创建一个 TableView
及其列,并创建一个控制器实例。您的 ServerHandler
class 创建了一个新的控制器实例,它又创建了一个 TableView
的新实例(总是 初始化错误注释的变量 @FXML
)。 TableView
实例永远不会显示。因此,当您的 ServerHandler
填充 table 时,它填充的 table 实际上不是 UI 的一部分,您什么也看不到。
将 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
class 应该依次将控制器传递给 ServerHandler
个实例。由于 ServerHandler
方法是在后台线程上调用的,因此它们需要使用 Platform.runLater(...)
来更新 UI:
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);
});
}
}
最后,不要初始化应该由 FXMLLoader
初始化的字段。这只会产生抑制任何表明您的控制器-FXML 绑定未正确设置的 NullPointerException
的效果:
public class SampleController {
private ObservableList<Model> tableData = FXCollections.observableArrayList();
@FXML
private TableView<RowModel> 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().getProgress());
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(rowModel);
}
}