JavaFX-带有图像按钮的ListView项

JavaFX-带有图像按钮的ListView项,listview,javafx,Listview,Javafx,我想知道是否有可能在每个ListView项目之后添加一个图像按钮。例如: 这些红色方块应该有一个按钮。如果可能,我如何处理项目按钮的单击事件 编辑:如果有其他控件可以这样做,请告诉我。我正在测试TableView 提前谢谢 我最近在测试这个。我的解决方案: import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList;

我想知道是否有可能在每个ListView项目之后添加一个图像按钮。例如:

这些红色方块应该有一个按钮。如果可能,我如何处理项目按钮的单击事件

编辑:如果有其他控件可以这样做,请告诉我。我正在测试TableView


提前谢谢

我最近在测试这个。我的解决方案:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class SO extends Application {
    static class XCell extends ListCell<String> {
        HBox hbox = new HBox();
        Label label = new Label("(empty)");
        Pane pane = new Pane();
        Button button = new Button("(>)");
        String lastItem;

        public XCell() {
            super();
            hbox.getChildren().addAll(label, pane, button);
            HBox.setHgrow(pane, Priority.ALWAYS);
            button.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    System.out.println(lastItem + " : " + event);
                }
            });
        }

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            setText(null);  // No text in label of super class
            if (empty) {
                lastItem = null;
                setGraphic(null);
            } else {
                lastItem = item;
                label.setText(item!=null ? item : "<null>");
                setGraphic(hbox);
            }
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        StackPane pane = new StackPane();
        Scene scene = new Scene(pane, 300, 150);
        primaryStage.setScene(scene);
        ObservableList<String> list = FXCollections.observableArrayList(
                "Item 1", "Item 2", "Item 3", "Item 4");
        ListView<String> lv = new ListView<>(list);
        lv.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
            @Override
            public ListCell<String> call(ListView<String> param) {
                return new XCell();
            }
        });
        pane.getChildren().add(lv);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
导入javafx.application.application;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.Label;
导入javafx.scene.control.ListCell;
导入javafx.scene.control.ListView;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.Priority;
导入javafx.scene.layout.StackPane;
导入javafx.stage.stage;
导入javafx.util.Callback;
公共类因此扩展了应用程序{
静态类XCell扩展了ListCell{
HBox HBox=新的HBox();
标签标签=新标签(“(空)”);
窗格=新窗格();
按钮按钮=新按钮(“(>)”);
字符串最后一项;
公共XCell(){
超级();
hbox.getChildren().addAll(标签、窗格、按钮);
HBox.setHgrow(窗格,Priority.ALWAYS);
setOnAction(新的EventHandler

  • 当我的列表不大时,上一个解决方案运行良好,我没有添加更多控件使节点更复杂。当我添加更多控件时,我发现并发性存在问题,可能也是因为我正在绘制包含12000多个对象(直线和多边形)的地图。问题(我所看到的)ListView中的某些项将在内部重复,这意味着cellfactory将被创建两次和/或不被创建。似乎“updateItem”是线程队列中的最后一个。 因此,为了解决这个问题,我必须在创建ListView之前创建节点。类似如下:

        ObservableList<Node> list = FXCollections.observableArrayList();
        for (AisaLayer layer : listLayers) {
            mapLayers.put(layer.getLayerName(), layer);
            list.add(new AisaNode(layer));
            System.out.println("Ordered:" + layer.getLayerName());
        }
        lv.setItems(list);
        lv.setCellFactory(new Callback<ListView<Node>, ListCell<Node>>() {
            @Override
            public ListCell<Node> call(ListView<Node> param) {
                return new DefaultListCell<>();
            }
        });
    
    observeList=FXCollections.observearraylist();
    对于(AisLayer图层:listLayers){
    放置(layer.getLayerName(),layer);
    增加(新阳极(层));
    System.out.println(“有序:“+layer.getLayerName());
    }
    lv.设置项目(列表);
    lv.setCellFactory(新回调(){
    @凌驾
    公共ListCell调用(ListView参数){
    返回新的DefaultListCell();
    }
    });
    

    我使用了fxexperience.com中推荐的简单DefaultListCell,您也可以使用自定义HBox对象列表。下面的示例显示了此类自定义HBox内部类的使用以及将此类对象列表嵌套到ListView控件中的过程

    import java.util.ArrayList;
    import java.util.List;
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.control.ListView;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.Priority;
    import javafx.stage.Stage;
    
    
    public class ListViewDemo extends Application {
    
         public static class HBoxCell extends HBox {
              Label label = new Label();
              Button button = new Button();
    
              HBoxCell(String labelText, String buttonText) {
                   super();
    
                   label.setText(labelText);
                   label.setMaxWidth(Double.MAX_VALUE);
                   HBox.setHgrow(label, Priority.ALWAYS);
    
                   button.setText(buttonText);
    
                   this.getChildren().addAll(label, button);
              }
         }
    
         public Parent createContent() {
              BorderPane layout = new BorderPane();
    
              List<HBoxCell> list = new ArrayList<>();
              for (int i = 0; i < 12; i++) {
                   list.add(new HBoxCell("Item " + i, "Button " + i));
              }
    
              ListView<HBoxCell> listView = new ListView<HBoxCell>();
              ObservableList<HBoxCell> myObservableList = FXCollections.observableList(list);
              listView.setItems(myObservableList);
    
              layout.setCenter(listView);
    
              return layout;
         }
    
         @Override
         public void start(Stage stage) throws Exception {
              stage.setScene(new Scene(createContent()));
              stage.setWidth(300);
              stage.setHeight(200);
              stage.show();
         }
    
         public static void main(String args[]) {
              launch(args);
         }
    }
    
    import java.util.ArrayList;
    导入java.util.List;
    导入javafx.application.application;
    导入javafx.collections.FXCollections;
    导入javafx.collections.ObservableList;
    导入javafx.scene.Parent;
    导入javafx.scene.scene;
    导入javafx.scene.control.Button;
    导入javafx.scene.control.Label;
    导入javafx.scene.control.ListView;
    导入javafx.scene.layout.BorderPane;
    导入javafx.scene.layout.HBox;
    导入javafx.scene.layout.Priority;
    导入javafx.stage.stage;
    公共类ListViewDemo扩展了应用程序{
    公共静态类HBoxCell扩展HBox{
    标签=新标签();
    按钮按钮=新按钮();
    HBoxCell(字符串标签文本、字符串按钮文本){
    超级();
    label.setText(labelText);
    label.setMaxWidth(双倍最大值);
    HBox.setHgrow(标签、优先级、始终);
    button.setText(buttonText);
    this.getChildren().addAll(标签、按钮);
    }
    }
    公共父级createContent(){
    BorderPane布局=新建BorderPane();
    列表=新的ArrayList();
    对于(int i=0;i<12;i++){
    添加(新的HBoxCell(“项目”+i,“按钮”+i));
    }
    ListView ListView=新建ListView();
    ObservableList myObservableList=FXCollections.ObservableList(列表);
    setItems(myObservableList);
    布局。设置中心(listView);
    返回布局;
    }
    @凌驾
    public void start(Stage)引发异常{
    stage.setScene(新场景(createContent());
    舞台设置宽度(300);
    舞台设置高度(200);
    stage.show();
    }
    公共静态void main(字符串参数[]){
    发射(args);
    }
    }
    
    此实施的结果如下所示:

        ObservableList<Node> list = FXCollections.observableArrayList();
        for (AisaLayer layer : listLayers) {
            mapLayers.put(layer.getLayerName(), layer);
            list.add(new AisaNode(layer));
            System.out.println("Ordered:" + layer.getLayerName());
        }
        lv.setItems(list);
        lv.setCellFactory(new Callback<ListView<Node>, ListCell<Node>>() {
            @Override
            public ListCell<Node> call(ListView<Node> param) {
                return new DefaultListCell<>();
            }
        });
    


    但是,为了有效地管理按钮事件,您应该考虑在HBOXXECUTE构造器方法中添加附加自定义按钮对象,并创建一个适当的方法,这将允许您控制按钮单击事件。

    极好!非常感谢编码!工作得很好!不需要将当前项存储在<代码> L中。astItem
    字段。您可以直接在按钮处理程序中调用
    getItem()
    。它不适用于@FXML初始化的ListView:(@CarlosLópezMarí这确实适用于FXML初始化的ListView我没有深入研究过这一点,但表面上看,这似乎是一个糟糕的想法。