简体   繁体   English

javaFX:如何创建实时ListView并向其中添加ChangeListener

[英]javaFX: How to create a Live ListView and add a ChangeListener to it

I wrote a JavaFX user interface (fxml) and bind a controller class to it, everything worked fine until I added an ObservableList and a ChangeListener for the ListView in my application. 我写了一个JavaFX用户界面(fxml)并将一个控制器类绑定到它,一切正常,直到在应用程序中为ListView添加了ObservableList和ChangeListener为止。 the ListView looks fine and shows the right values when I run the application, but when I click some buttons, Exceptions happen and buttons won't work. 当我运行应用程序时,ListView看起来很好并显示正确的值,但是当我单击某些按钮时,会发生异常,并且按钮将不起作用。 These are buttons that supposed to show the other layouts when clicked. 这些按钮应该在单击时显示其他布局。 the exception says that the layout (eg AddUser.fxml) not found, but it exists and worked correctly till now! 异常表明未找到布局(例如AddUser.fxml),但该布局已经存在并且可以正常工作!

some lines of the controller class: 控制器类的一些行:

public class FileSharingController implements Initializable {

private ObservableList<User> UsersListData=FXCollections.observableArrayList();
@FXML
private ListView<User> UsersList;

public FileSharingController(){
    DatabaseManager DB=new DatabaseManager();
    try {
        UsersListData.addAll(DB.returnUsers());
    } catch (SQLException e) {e.printStackTrace();}
}

@Override
public void initialize(URL location, ResourceBundle resources) {
        UsersList.setItems(UsersListData);
        UsersListData.addListener(new ListChangeListener<User>(){
            @Override
            public void onChanged(Change<? extends User> c) {
                System.out.println(c.getList());

            }
        });
}

@FXML
public void showAddUserLayout(){
    try {Stage stage=new Stage();
    AnchorPane  rootPane=FXMLLoader.load(getClass().getResource("AddUser.fxml"));
    Scene scene = new Scene(rootPane);
    stage.setScene(scene);
    stage.setTitle("Add User");
    stage.show();
} catch (IOException e) {e.printStackTrace();}
}
}

the User class (Model): 用户类(模型):

package Model;

public class User {
private String Username;
private String Password;

public User(String Username,String Password){
    this.Username=Username;
    this.Password=Password;
}
public void Set(String Username,String Password){
    this.Username=Username;
    this.Password=Password;
}
public String toString(){
    return Username+"   "+Password;
}
}

when I click the "Add" button, the showAddUserLayout() called and I got the following Exceptions: 当我单击“添加”按钮时,调用showAddUserLayout()并得到以下异常:

java.lang.NullPointerException
/D:/workspace_FileSharing%20Serverside/FileSharing_ServerSide/bin/com/Shayan/FileSharing/Server/AddUser.fxml
  at com.Shayan.FileSharing.Server.FileSharingController.updateUsersList(FileSharingController.java:144)
at com.Shayan.FileSharing.Server.FileSharingController.initialize(FileSharingController.java:50)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2152)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2742)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2721)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2694)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2683)
at com.Shayan.FileSharing.Server.FileSharingController.showAddUserLayout(FileSharingController.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1437)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3113)
at javafx.scene.Scene$ClickGenerator.access$8600(Scene.java:3051)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3333)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3164)
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
at com.sun.glass.ui.View.notifyMouse(View.java:922)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:722)

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
      at     javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440)
      at  com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
     at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)

Please help! 请帮忙! I don't know What's happening... thanks in advance! 我不知道发生了什么事...预先感谢!

Your posted code is incomplete. 您发布的代码不完整。 The FXMLLoader is loading the "AddUser.fxml" file. FXMLLoader正在加载“ AddUser.fxml”文件。 It also calling the initialize method of the controller. 它还调用控制器的initialize方法。 But the nullpointerexception appears at a line number 144 in updateUsersList() method. 但是nullpointerexception出现在updateUsersList()方法的行号144处。 Check that line. 检查那条线。 And you may want to change the controller class of "AddUser.fxml" to other one than FileSharingController. 并且您可能想要将“ AddUser.fxml”的控制器类更改为FileSharingController以外的其他类。

As per comment, 根据评论,
Does each Layout need a seperate controller?

Technically no, but semantically yes. 从技术上讲不,但从语义上讲是。 If you set the same fx:controller in different FXML files then you will end up with multiple instances of that controller for every FXML file being loaded. 如果在不同的FXML文件中设置相同的fx:controller ,那么对于每个要加载的FXML文件,最终都会有该控制器的多个实例。 If you use FXMLLoader.setController() among with FXMLLoader.setRoot() where the FXML files include fx:root instead of fx:controller then you will end up with only one instance of the controller which its initialize() method will be called separately for every FXML file being loaded. 如果在FXML文件包括fx:root而不是fx:controller FXMLLoader.setController()中使用FXMLLoader.setRoot() ,则最终只会得到控制器的一个实例,它将单独调用其initialize()方法对于正在加载的每个FXML文件。 In both cases, however, each FXML file will semantically deal with only some part of the controller, ie init, inject, set, manipulate the parts it is interested in. IMO the FXML files should have no mutual domain, and if have then they must use normal java messaging mechanism through their own controllers. 但是,在这两种情况下,每个FXML文件在语义上仅处理控制器的一部分,即初始化,注入,设置,操作它感兴趣的部分。IMOFXML文件应该没有相互的域,如果有,则它们必须通过自己的控制器使用常规的Java消息传递机制。 So having another AddUserController class will be more modular, maintainable and less headaches. 因此,拥有另一个AddUserController类将具有更高的模块化,可维护性,并减少了麻烦。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM