如何在javafx中向ListView的单元格添加鼠标双击事件监听器?

问题描述 投票:0回答:3

我在 ListView 中有一个链接列表。我想向列表的每个单元格添加一个 mouseEventListener,以便每当用户双击时都会打开列表项链接。我可以自己编写打开链接的功能,但我无法为列表中的每个单元格添加双击事件。请帮忙...

listview javafx mouseevent
3个回答
39
投票

让我们将您的

ListView
视为播放列表。现在,您可以使用每个单元格上的双击功能来实现鼠标侦听器

playList.setOnMouseClicked(new EventHandler<MouseEvent>() {

    @Override
    public void handle(MouseEvent click) {

        if (click.getClickCount() == 2) {
           //Use ListView's getSelected Item
           currentItemSelected = playList.getSelectionModel()
                                                    .getSelectedItem();
           //use this to do whatever you want to. Open Link etc.
        }
    }
});

12
投票

我必须解决同样的问题,我的 ListView 包含一个网格窗格和标记文本,因此您必须将“instanceof”和“or”的另一侧更改为您所拥有的。

(假设你的ListView名为listView):

listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {
        if(event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2 &&
           (event.getTarget() instanceof LabeledText || ((GridPane) event.getTarget()).getChildren().size() > 0)) {

           //your code here        
         }    
    }
});

如果用户单击项目的最边缘和 ListView 的边框附近,则可能不会通过 if 循环,但听起来用户在您的情况下不会这样做。

希望这有帮助。


0
投票

答案可能很长,因为我试图准确提供用户所要求的内容。我正在考虑使用 fxml,但如果不使用 fxml,答案也是适用的。我还使用自定义

CellFactory
来渲染各个列表项。

这个答案遵循 MVC 模式。另外,我跳过了代码中的所有导入语句。

所以,我们需要这些文件。每个文件的名称都是不言自明的。

  • ItemModel.java
  • PrimaryScene.fxml
  • PrimarySceneController.java
  • ListItem.fxml
  • ListItemController.java
  • ListItemCellFactory.java
  • ListItemCell.java
  • OnItemDoubleClickListener.java

ItemModel.java

public class ItemModel{
    private String name;
    private String description;
    
    // All Getters, and Setters here ....
}

OnItemDoubleClickListener.java

public interface OnItemDoubleClickListener{
    public void handleDoubleClick(MouseEvent event, ItemModel model);
}

PrimaryScene.fxml

<AnchorPane xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="PrimarySceneController">
   <ListView fx:id="listView" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</AnchorPane>

PrimarySceneController.java

public class PrimarySceneController implements Initializable, OnItemDoubleClickListener{
    
    @FXML
    public ListView<ItemModel> listView;

    private final ObservableList<ItemModel> items = FXCollections.observableArrayList();

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        listView.setCellFactory(new ListItemCellFactory(this));
        listView.setItems(items);

        // TODO: populate items here ...
    }

    @Override
    public void handleDoubleClick(MouseEvent event, ItemModel model){
        // TODO: Item was double clicked. Do you thing.
    }
}

ListItem.fxml

<AnchorPane xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:id="root">
   <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <Label fx:id="labelName" text="Label"/>
      <Label fx:id="labelDescription" text="Label/>
   </VBox>
</AnchorPane>

ListItemController.java

private static class ListItemController implements Initializable{
    @FXML
    private AnchorPane root;

    @FXML
    private Label labelName;

    @FXML
    private Label labelDescription;
    
    private final OnItemDoubleClickListener listener;

    public ListItemController(OnItemDoubleClickListener listener){
        this.listener = listener;
    }

    public void draw(ItemModel model) {
        labelName.setText(model.getName());
        labelDescription.setText(model.getDescription());
        
        // Magic happens here
        root.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if(event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2){
                    this.listener.handleDoubleClick(event, model);
                }                    
            }
        });
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }
}

ListItemCellFactory.java

public class ListItemCellFactory implements Callback<ListView<ItemModel>, ListCell<ItemModel>> {
    
    
    private final OnItemDoubleClickListener listener;

    public ListItemCellFactory(OnItemDoubleClickListener listener){
        this.listener = listener;
    }

    @Override
    public ListCell<ItemModel> call(ListView<ItemModel> listView) {
        FXMLLoader fxmlLoader = new FXMLLoader();
        ListItemController controller = new ListItemController(this.listener);
        fxmlLoader.setController(controller);
        Node graphic = fxmlLoader.load(Home2Controller.class.getResourceAsStream("/ListItem.fxml"));
        return new ListItemCell(graphic, controller);
    }
}

ListItemCell.java

private static class ListItemCell extends ListCell<ItemModel> {

    private final Node graphic;
    private final ListItemController controller;

    public ListItemCell(Node graphic, ListItemController controller) {
        this.graphic = graphic;
        this.controller = controller;
    }

    @Override
    protected void updateItem(ItemModel item, boolean empty) {
        super.updateItem(item, empty);
        if (empty){
            setText(null);
            setGraphic(null);
            return;
        }

        setText(null);
        setGraphic(graphic);
        controller.draw(item);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.