Can't Get Clicked Item in List
newtingz opened this issue · 27 comments
If you want to know which item/row was clicked in the list you can try:
flow.setOnMouseClicked( ME ->
{
VirtualFlowHit<Cell<AudioParser,?>> hit = flow.hit( ME.getX(), ME.getY() );
int row = hit.getCellIndex();
} );
If you want to know which item/row was clicked in the list you can try:
flow.setOnMouseClicked( ME -> { VirtualFlowHit<Cell<AudioParser,?>> hit = flow.hit( ME.getX(), ME.getY() ); int row = hit.getCellIndex(); } );
Thanks, Btw
Solved The Problem, expect More
Lol
If you want to know which item/row was clicked in the list you can try:
flow.setOnMouseClicked( ME -> { VirtualFlowHit<Cell<AudioParser,?>> hit = flow.hit( ME.getX(), ME.getY() ); int row = hit.getCellIndex(); } );
Hey, didn't want to open a new issue
however,I'm trying to access Data from a From a cell so i Put the Data into a Node(as I
cant access the cell and its class like a listview,Idk how to do it in virtual listview), since I'm failing to reproduce the listview effect of getselecteditem.(custom class function e.g getter or setter)
How do I achieve that effect ?
You could use the row
value to access the list of items passed to the VirtualFlow, like:
AudioParser ap = list.get( row );
You could use the
row
value to access the list of items passed to the VirtualFlow, like:AudioParser ap = list.get( row );
Thanks that worked too, I found a way,
I'm Getting Through Via the Cells' contents through Node, ->getCell(row).getNode(),
However Now I'm trying to get rid of the Horizontal Scroll Bar, I tried checking out the Previous Issues.
And also Having the List start from the Top when Displaying content, in My case it takes me to the bottom of the ListView
Thank You
If you are using org.fxmisc.flowless.VirtualizedScrollPane
then:
VirtualizedScrollPane vsp = new VirtualizedScrollPane<>( flow );
vsp.setHbarPolicy( ScrollBarPolicy.NEVER );
You can also get the node directly from VirtualFlowHit
:
flow.setOnMouseClicked( ME ->
{
VirtualFlowHit<Cell<AudioParser,?>> hit = flow.hit( ME.getX(), ME.getY() );
Node n = hit.getCell().getNode();
} );
Awesome, it all works, when I click on A cell I Access a Hidden Node with Data I need not the User To see.
Now I wanted To tryout, reUsable cell to see If performance is matched, better Or not, how do I Do That ?
Instead of using return Cell.wrapNode( grid );
you need to create your own subclass of org.fxmisc.flowless.Cell and implement:
Node getNode()
boolean isReusable()
void updateItem( T item )
void reset()
void dispose()
See an example here in RichTextFX.
If you do this you can also add another method to your Cell class to get the item passed to it back again later, instead of having to embed it in a Node as you are doing now. So add:
T getItem()
then you should be able to do:
AudioParser ap = hit.getCell().getItem(); // might need to cast hit.getCell() first ?
Nah, you've just copied the code from the Cell interface.
Whereas you need to do a full implementation of it, something like in the RichTextFX example.
You also asked (but removed from the post) "How Would I Be Able To stop Loading any Cell once they are out of the viewport".
The answer is that you would do that in the reset()
method of your Cell class.
The VirtualFlow program logic goes something like this:
- If a cell is NOT available for reuse "VirtualFlow" will call the Cell factory that you passed to it when creating it. For example if you did:
VirtualFlow.createVertical( list, this::myCellFactory );
then "VirtualFlow" will use myCellFactory to get a new Cell. - If a cell is already available then "VirtualFlow" will call
updateItem( T item )
on it. (This is where you update your nodes to show data from a new item, in your case AudioParser.) - When a cell goes out of view "VirtualFlow" will call
reset()
on it.
An example of what a myCellFactory method may look like for your case:
private Cell audioParserCellFactory( AudioParser item )
{
Cell newCell = new AudioParserCell();
newCell.updateItem( item );
return newCell;
}
Of course this can be condensed into VirtualFlow.createVertical( list, audioparser -> new AudioParserCell( audioparser ) );
but then your AudioParserCell constructor should call updateItem( audioparser )
once it has finished building the node that'll be returned by getNode()
.
Hope this helps.
Hey, Man Your Helping Tonnes,
I'm trying to get this one done with, however, The scroll pane shows One Item, then all of out Of heap errors,
If You Mind,where am I going Wrong, been struggling
thanks too for the other post I edited
here's is how I set it up, I chose the AudioParserCell Route am not sure if its best,(as Later on I would Implennt the getItem)
I suspect my error is all on the Update call and getNode I'm confused on how to set them up, Then I went to the richTextFlow again,(understand it better now) but, which item am I supposed to be getting with getNode()?, is it Supposed to Be Cell then,I wrap it then return it and Which Item am I updating?
getNode()
returning grid is right, but it should just be:
public Node getNode() { return grid; }
You build the grid only once in the constructor.
updateItem()
returns void and not Cell. The method should look something like:
public void updateItem( AudioParser parser )
{
SonfName.setText( parser.nameGet() +"\n"+ parser.albumGet() );
executor.submit( () -> icon.setImage( new Image( parser.imageGet(), true ) ) );
}
- I didn't see it, so I'm just making sure you also have:
boolean isReusable() { return true; }
- The grid and EVERYTHING inside it should ONLY be built and configured in the constructor. So no controls should be created inside
updateItem
. - In
updateItem
only change whatever needs to be changed for each AudioParser, like SonfName text and icon image. - You forgot to assign parser to audiop in
updateItem
before using audiop. - Remove the getNode() call in your constructor, it doesn't do anything ?
- The call to updateItem in the constructor should only happen after ALL the GUI controls have been created.
Ohh, great all this time it has been the Cell reusable, checked some comments it mentions its buggy on java 1.8 and up something like that,
Man thanks for your patience,let me try implement get item now.
also is that set up ,in the shots fine ?
Yeah, it's fine. You can move the SonfName.setStyle()
into the constructor as well, unless it's going to change.
Remember the reason you are doing this is for performance !!! So do as little as possible in updateItem
, only stuff that changes.
For the "the cells are stacked on each other" problem, try sizing the grid with grid.setPrefSize( w, h )
and see if that helps.
I did that but, that still happens, getting an error saying Cell. unsupported.......
However I've set The grid height to be consistent throughout,
Ive been getting an Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException
So I think it's related to setting up the Image in the grid pane after serious scrolling, so I'm trying to implement a blocking queue that if a certain number of executors submitted it dumps the later ones and deals with Something Like the Latest 10,
Hey ,
How can i wrap a TilePane in the virtualized Scrolpane, or functionality of a TilePane within vscrollpane as currently, it takes much ram and performance, in normal scroll pane
You would need to extend TilePane and implement the Virtualized interface.
Oh , I'll work on that
Meanwhile ,if I started using the Virtualized GridView From Controls Fx,
But The Update Item Is costly, its Creating New objects all the Time, it behaves like Normal Listview
How Can I Create An Update Item or modify it in a way that it doesn't create those items again but re-use them, and update those like Images,
Hey @newtingz, you'll have to show your current GridCell
implementation for the GridView for me to be able to give any advice.
Actually you should maybe post that on ControlsFX issues. (Put a link here though to your post, and I'll have a look.)
Cannot infer type arguments for GridView<>
-the Error I get
Ok,
Listview Uses, Viewport, is it possible to have The GridView Use Our Own ViewPort
class GridCellr implements Cell{
Albums audiop;
GridPane grid4 = new GridPane();
Label l ;
ImageView icod =new ImageView();
Rectangle clip=new Rectangle();
HBox iconAndName = new HBox(2);
{
// HBox iconAndName = new HBox();
//GridPane grid4 = new GridPane();
//L l = new Label(item.albumGet());
icod.setFitHeight(75);
icod.setFitWidth(75);
grid4.getStyleClass().add("grid4");
grid4.setPadding(new Insets(0,0,5,0));
//grid4.setCache(true);
//grid4.setCacheHint(CacheHint.SPEED);
//grid4.setHgap(10);
// grid4.setVgap(5);
grid4.setPrefSize(75, 75);
grid4.maxHeight(75);
grid4.maxWidth(75);
iconAndName.getChildren().add(icod);
iconAndName.setAlignment(Pos.CENTER);
iconAndName.setPadding(new Insets(0,0,3,0));
grid4.add(iconAndName, 0, 0);
grid4.setOnMouseClicked(e -> {
albumOnClikc(grid4,l);
});
}
public GridCellr(Albums audioparser ) {//,String artist,String album) {
this.audiop=audioparser;
//queue.add(0, new Image(new File(audioparser.ImageGet()).toURI().toString(),true));
updateItem(audioparser);
}
public void updateItem( Albums item )
{
l= new Label(item.albumGet());
l.setTextFill(Color.WHITE);
l.setPadding(new Insets(2,5,0,5));
grid4.add(l, 0, 1);
clip.setArcWidth(10);
clip.setArcHeight(10);
clip.widthProperty().bind(grid4.widthProperty());
clip.heightProperty().bind(grid4.heightProperty());
grid4.setClip(clip);
icod = new ImageView(new Image(new File(item.ImageGet()).toURI().toString(),true));
}
@Override
public Node getNode() {return grid4; };
@Override
public boolean isReusable() { return false; }
}`
The Update Item that I'm using
gridView2.setCellFactory(new Callback<GridView<Artists>, GridCell<Artists>>() {
public GridCell<Artists> call(GridView<Artists> gridView) {
return new GridCell<Artists>() {
@Override
protected void updateItem(Artists item, boolean empty) {
// TODO Auto-generated method stub
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
GridPane grid4 = new GridPane();
Label l = new Label(item.artistGet());
HBox iconAndName = new HBox();
l.setTextFill(Color.WHITE);
l.setPadding(new Insets(2,5,0,5));
ImageView icod = new ImageView(new Image(new File(item.ImageGet()).toURI().toString(),true));
iconAndName.getChildren().add(icod);
iconAndName.setAlignment(Pos.CENTER);
iconAndName.setPadding(new Insets(0,0,3,0));
icod.setFitHeight(75);
icod.setFitWidth(75);
setGraphic(grid4);
});
}
}
};
}
});
I Tried Making A Gridcell Implementation and an error saying the GridCell is not generic so cannot be parameterized
It is was like this class GridCellr extends GridCell
The Body is the same as GridCellr Cell previously mentioned, without getNode and reUsable