javalistviewjavafxscenebuilder

JavaFX - ListView, cannot add items


I'm trying to simply add a line of text to the listView. I've followed tutorials, asked AI, and followed it exactly to my knowledge. I know I'm doing something wrong.

in my class, my listview is properly connected to the fxml id in scenebuilder

@FXML
ListView<String> list = new ListView<>();

in the method:

public void addToList(){
        list.getItems().add("hi");
        list.getItems().add("hello");
}

it compiles and loads, and I see the listview pane. but none of the items are shown when i call addToList...

The Listview is inside of a scrollpane inside of an Hbox, inside of the main window which is a Vbox.

I know I'm missing something simple and it's frustrating the heck out me.

I'm trying to get anything to show in the listView. anything at all. Im actually trying to pass an array in a bigger program that I've proven is populated by printing the entire array, but I've simplified the code to just add 2 simple strings in an attempt to get anything to show.


Solution

  • Your code for adding items to the list backing the ListView:

    list.getItems().add("hi")
    

    … seems correct. So you must have other problems.

    As the Comments said, your layout seems suspect. ListView has its own scrolling, so no need to embed in a scroll pane.


    Below is a basic example app. This app starts with a ListView with a single value of “bonjour” set in the initialize method of the controller. A button then adds your two items "hi" & "hello" to the list, one every click.

    initialize method

    The initialize method is part of the JavaFX lifecycle. On a controller class, first the constructor runs. Then the @FXML fields are populated via injection by the JavaFX framework. Lastly the initialize method is automatically called by the JavaFX framework. So within the initialize method we can modify/manipulate the already-instantiated JavaFX controls. In this example app we designate our ObservableList with a single item ("bonjour") to be the backing data of our ListView control.

    You can annotate the initialize method with @FXML. Not necessary if the method is marked public. If marked private, the annotation is required. See documentation for @FXML.

    Button-click method

    The method assigned to react to each click of the button uses your code to retrieve the ObservableList we assigned during initialize, and add your "hi"/"hello" items to that list. Because the list is observable, the JavaFX framework automatically notices the change in our backing data model, and automatically updates the display of the ListView.

    Example code

    This code is using JavaFX/OpenJFX version 20.0.2, with Java 20.0.2, on macOS Ventura, modified from the JavaFX new-project template provided by IntelliJ 2023.2.1.

    A screenshot after having clicked the button three times.

    screenshot of example app with a button that adds two items to the ListView

    The FXML file:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.Insets?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.VBox?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.ListView?>
    <VBox alignment="CENTER"
          spacing="20.0"
          xmlns:fx="http://javafx.com/fxml"
          fx:controller="work.basil.example.fxlistview.HelloController">
        <padding>
            <Insets bottom="20.0"
                    left="20.0"
                    right="20.0"
                    top="20.0"/>
        </padding>
    
        <Label fx:id="welcomeText"/>
        <Button text="Add two more items to list"
                onAction="#onClickOfAddButton"/>
        <ListView fx:id="exampleListView"/>
    </VBox>
    

    The controller:

    package work.basil.example.fxlistview;
    
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.scene.control.Label;
    import javafx.scene.control.ListView;
    
    public class HelloController
    {
        @FXML
        private Label welcomeText;
    
        @FXML
        private ListView < String > exampleListView;
    
        @FXML
        protected void onClickOfAddButton ( )
        {
            this.addToList ( );
        }
    
        private final ObservableList < String > observableList = FXCollections.observableArrayList ( "bonjour" );
    
        public void addToList ( )
        {
            exampleListView.getItems ( ).add ( "hi" );
            exampleListView.getItems ( ).add ( "hello" );
        }
    
        @FXML
        private void initialize ( )
        {
            this.exampleListView.setItems ( this.observableList );
        }
    }
    

    The Application subclass:

    package work.basil.example.fxlistview;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    import java.io.IOException;
    
    public class HelloApplication extends Application
    {
        @Override
        public void start ( Stage stage ) throws IOException
        {
            FXMLLoader fxmlLoader = new FXMLLoader ( HelloApplication.class.getResource ( "hello-view.fxml" ) );
            Scene scene = new Scene ( fxmlLoader.load ( ) , 320 , 600 );
            stage.setTitle ( "Hello!" );
            stage.setScene ( scene );
            stage.show ( );
        }
    
        public static void main ( String[] args )
        {
            launch ( );
        }
    }
    

    These Questions helped me here: