How to handle ListView item clicked action?

前端 未结 4 1878
再見小時候
再見小時候 2021-01-01 11:04

I have my JavaFX 2.0 application, where i need to make some action, after user clicked an item in ListView element. To construct user GUI i\'m using FXML, in which i have so

相关标签:
4条回答
  • 2021-01-01 11:43

    You can also consume unwanted events on blank space.

    in call() of cell factory add:

    cell.setOnMousePressed((MouseEvent event) -> {
        if (cell.isEmpty()) {
           event.consume();
        }
    });
    

    This will disable click & dragStart too.

    Whole cellFactory example from my project:

    public static Callback<ListView<BlockFactory>, ListCell<BlockFactory>> getCellFactory() {
        return new Callback<ListView<BlockFactory>, ListCell<BlockFactory>>() {
    
            @Override
            public ListCell<BlockFactory> call(ListView<BlockFactory> param) {
                ListCell<BlockFactory> cell = new ListCell<BlockFactory>() {
    
                    @Override
                    protected void updateItem(BlockFactory item, boolean empty) {
                        super.updateItem(item, empty);
                        if (item != null) {
                            ImageView img = new ImageView(item.img);
                            Label label = new Label(item.desc);
                            HBox bar = new HBox(img, label);
                            bar.setSpacing(15);
                            bar.setAlignment(Pos.CENTER_LEFT);
                            setGraphic(bar);
                        }
                    }
                };
                cell.setOnMousePressed((MouseEvent event) -> {
                    if (cell.isEmpty()) {
                        event.consume();
                    }
                });
                return cell;
            }
        };
    }
    
    0 讨论(0)
  • 2021-01-01 11:54

    A simple fix to Sergey's answer, without having to create a whole new listCell (in your case you do, but we don't have to in a regular text case).

    all you need to simply do is create a temp variable that is equal to the first list item at first, and that gets changed to each new clicked item. Once you try to click the item again, the temp variable knows it's the same, and with an if statement you can get around that.

    temp Item is a global that you put up top String tempItem = "admin";

    for me I knew my first field is always going to be labeled "admin" so I set it as such. you would have to get the first entry and set it outside of the method you are going to use for list selecting.

    private void selUser() throws IOException
        {
        String item = userList.getSelectionModel().getSelectedItem().toString();
    
            if(item != tempItem)
            {
               //click, do something
            }
    
            tempItem = item;    
    }
    

    As for me I used an FXML document that called my method

    @FXML 
    public void userSel(MouseEvent mouse) throws IOException
    {
    selUser();
    

    }

    In this case you could just take the entire contents of the selUser() method and put it into the userSel mouse click.

    0 讨论(0)
  • 2021-01-01 11:58

    FXML attributes and values are directly mapped to FX API. So to find out how to write handler you can first create required entities by API.

    It seems you want to add action on ListView element on mouse click, so you need to add mouse click handler. In API it looks next way:

        final ListView lv = new ListView(FXCollections.observableList(Arrays.asList("one", "2", "3")));
        lv.setOnMouseClicked(new EventHandler<MouseEvent>() {
    
            @Override
            public void handle(MouseEvent event) {
                System.out.println("clicked on " + lv.getSelectionModel().getSelectedItem());
            }
        });
    

    Looking at that code you can find out what in FXML you need to overrided attribute onMouseClicked:

    <ListView fx:id="listView" onMouseClicked="#handleMouseClick"/>
    

    And in controller you need to provide handler with MouseEvent parameter:

    @FXML
    private ListView listView;
    
    @FXML public void handleMouseClick(MouseEvent arg0) {
        System.out.println("clicked on " + listView.getSelectionModel().getSelectedItem());
    }
    
    0 讨论(0)
  • 2021-01-01 12:01

    answer from @Sergey Grinev may have an issue. if your ListView is filled not enough full, in other words may have some blank space. then you cliked blank space will not tigger selection changing. enter image description here

    the solution: Use custom ListCell.

    1. define a custom class extends ListCell.
    2. in the updateItem function you can set item click event handler to cell root node.

    If you don't know how many items you have. you will not ever only do so. you should use time for space.

    Demostrate:

    in the ListView code segment:

    listView.setCellFactory(new AppListCellFactory());
    

    AppListCellFactory.java:

    public class AppListCellFactory implements Callback, ListCell> {

    // only one global event handler private EventHandler<MouseEvent> oneClickHandler; public AppListCellFactory(){ oneClickHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { Parent p = (Parent) event.getSource(); // do what you want to do with data. AppClickHandler.onAppBeanClicked((AppBean) p.getUserData()); } }; } @Override public ListCell<AppBean> call(ListView<AppBean> param) { return new DemoListCell(oneClickHandler); } public static final class DemoListCell extends ListCell<AppBean> { private EventHandler<MouseEvent> clickHandler; /** * This is ListView item root node. */ private Parent itemRoot; private Label label_AppName; private ImageView imgv_AppIcon; DemoListCell(EventHandler<MouseEvent> clickHandler) { this.clickHandler = clickHandler; } @Override protected void updateItem(AppBean app, boolean empty) { super.updateItem(app, empty); if (app == null) { setText(null); setGraphic(null); return; } if (null == itemRoot) { try { itemRoot = FXMLLoader.load(getClass().getResource(("fxml/appList_item.fxml"))); } catch (IOException e) { throw new RuntimeException(e); } label_AppName = (Label) itemRoot.lookup("#item_Label_AppName"); imgv_AppIcon = (ImageView) itemRoot.lookup("#item_ImageView_AppIcon"); itemRoot.setOnMouseClicked(clickHandler); } // set user data. like android's setTag(Object). itemRoot.setUserData(app); label_AppName.setText(app.name); imgv_AppIcon.setImage(new Image(getClass().getResource("img/icon_64.png").toExternalForm())); setGraphic(itemRoot); } }

    }

    0 讨论(0)
提交回复
热议问题