Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
869 views
in Technique[技术] by (71.8m points)

java - Ghost items in javafx ListView with custom ListCell

I try to view a custom object in a ListView using a custom ListCell. As an example to demonstrate the problem I chose java.util.File. Also for demonstration purpose I disable the ListCell directly when rendered. The items are added by an external process simulated by the thread. Everything looks nice until I apply the CSS coloring the disabled ListCell. Now it seems that there are some ghost items which get disabled together with the ListCell they are created of.

How can I solve this?

App.java

public class App extends Application
{
    @Override
    public void start( Stage primaryStage )
    {   
        final ListView<File> listView = new ListView<>();
        listView.setCellFactory( column -> { 
            return new ListCell<File>()
            {
                protected void updateItem( File item, boolean empty )
                {   
                    super.updateItem( item, empty );

                    if( item == null || empty )
                    {
                        setGraphic( null );
                        return;
                    }

                    setDisable( true );                 
                    setGraphic( new TextField( item.getName() ) );
                }
            };
        });

        new Thread( () -> {
            for( int i=0 ; i<10 ; ++i )
            {
                try
                {
                    Thread.sleep( 1000 );
                }
                catch( Exception e )
                {
                    e.printStackTrace();
                }
                final int n = i;
                Platform.runLater( () -> {
                    listView.getItems().add( new File( Character.toString( (char)( (int) 'a' + n ) ) ) );
                });
            }       
        }).start();

        Scene scene = new Scene( listView );    
        scene.getStylesheets().add( "app.css" );

        primaryStage.setScene( scene );
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception
    {
        super.stop();
    }

    public static void main( String[] args ) throws Exception
    {       
        launch( args );     
    }
}

app.css

.list-cell:disabled {
    -fx-background-color: #ddd;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You never set the disable property back to false. You need to do this for empty cells. The following could happen to a Cell:

  1. a item is added to the Cell and the cell is disabled
  2. the item is removed from the Cell, the Cell becomes empty, but it remains disabled.

In general when a Cell becomes empty, any changes done to the Cell when an item was added should be undone.

Furthermore you should avoid recreating the TextFields every time a new item is assigned to a Cell.

listView.setCellFactory(column -> {
    return new ListCell<File>() {

        private final TextField textField = new TextField();

        protected void updateItem(File item, boolean empty) {
            super.updateItem(item, empty);

            if (item == null || empty) {
                setDisable(false);
                setGraphic(null);
            } else {
                setDisable(true);
                textField.setText(item.getName());
                setGraphic(textField);
            }
        }
    };
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...