【问题标题】:JavaFX Listview bind button to the index of the cellJavaFX Listview 将按钮绑定到单元格的索引
【发布时间】:2014-04-05 17:35:04
【问题描述】:

我正在尝试使用 JavaFX 构建一个自定义视图,该视图允许在单元格中放置 2 个按钮“编辑用户”和“查看用户”。

我已经构建了适配器,但是在创建单元格时无法将索引分配给按钮,这是一个问题,因为当我单击单元格中的按钮时,我得到空指针异常。

编辑 07/04/2014 :我已经稍微更新了我的程序逻辑,但我仍在努力寻找解决问题的方法 - 分配的索引有时是正确的,但大多是不正确的(我设置了一个日志来给出我当前的索引并且它波动很大,这导致我得出结论我的单元构造函数不可靠)

我现在使用以下代码:populateListView():

public void populateListView() {

    // Zero the index each time the list view is repopulated to 
    // bind to the correct button
    index = 0;

    // Refresh the lists contents to null
    lstNotes.setItems(null);

    // Observable list containing items to add
    ObservableList notes = populateObservable(thisTenant.getNotes());

    // Set the items returned by populateObservable(T);
    lstNotes.setItems(notes);
    lstNotes.setFixedCellSize(50);

    // Use a cell factory for custom styling
    lstNotes.setCellFactory(new Callback<ListView, ListCell>() {
        @Override
        public ListCell call(ListView listView) {
            NoteCell nCell = new NoteCell(index, controller);
            index++;
            nCell.getStyleClass().add("border-bottom");
            return nCell;
        }
    });
}

这里的 cmets 是相当不言自明的 - 通过此方法填充可观察的项目列表 - populateObservable(NoteList n):

public ObservableList populateObservable(ArrayList<Note> notesArray) {

    ObservableList notes = FXCollections.observableArrayList();

    // Loop through the users Notes array and create a listview item
    for(int i = 0; i < notesArray.size(); i++) {
        Note thisNote = notesArray.get(i);
        notes.add(thisNote.getMessage());
    }

    return notes;
}

最后自定义视图是在我的单元工厂中构建的(样式与问题无关),应该注意的是对我的 Controller 的引用被传递给它,因此我可以访问方法 - 在 NoteCell 类中我有一个删除给定索引处的行的方法(这是产生倾斜结果的原因)

 cross.setOnMouseClicked(new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent mouseEvent) {
          ScreensFramework.logGeneral.writeToFile("I am removing from index " + String.valueOf(thisIndex));
          if(thisTenant.removeNoteAt(thisIndex, true)){
              controller.populateListView();
          } else {
              controller.populateListView();
          }
      }
  });

对 populateListView() 的调用只是为了刷新列表视图的内容并根据租户更新的 Note 数组重建它。

RemoveNoteAt() 方法将删除查询发送到我的数据库,并从给定索引处的租户注释数组中删除注释(但我并不总是得到如上所述的正确索引,因为我找不到有效的索引将按钮绑定到该 ListViews 单元格的方法,而我尝试传递索引的微弱尝试似乎不起作用)。

我希望此更新为我的问题提供更清晰的范围,如果您需要更多信息以更清楚地理解这一点,请提出请求。

编辑:NoteCell 代码:

public class NoteCell extends ListCell<String> {
HBox hbox = new HBox();
HBox c = new HBox();
Pane b = new HBox();
Pane pane = new Pane();
Label msg = new Label();
Label date = new Label();
Button cross = new Button();
Tenant thisTenant;
int thisIndex;

String lastItem;


public NoteCell(int index, UserInfoController controller) {
    super();

    try{
        thisTenant = controller.getTenant();
        Note currNote = thisTenant.getNoteAt(index);
        date = new Label(currNote.getDate());
        System.out.println(thisTenant.getNotes());
        thisIndex = index;

        date.setStyle("-fx-text-fill: #fff !important; -fx-font-family: Helvetica; -fx-font-weight: bold; -fx-font-size: 12px; -fx-background-color: #f9246b; -fx-border-color: #FE246C; -fx-padding: 8 8 6 8; -fx-border-radius: 6; -fx-background-radius: 6");
        b.setStyle("-fx-padding: 10px 5px 10px 5px");
        msg.setStyle("-fx-text-fill: #fafafa; -fx-font-size: 14px; -fx-font-family: 'Open Sans Light'; -fx-label-padding: 10px");
        cross.getStyleClass().add("button_close");
        cross.setTranslateY(20);
        msg.setAlignment(Pos.CENTER_LEFT);

        pane.setTranslateY(20);
        b.getChildren().add(date);
        c.getChildren().add(cross);
        hbox.getChildren().addAll(b, msg, pane, cross);
        HBox.setHgrow(pane, Priority.ALWAYS);


        // Deletes the note
        cross.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                ScreensFramework.logGeneral.writeToFile("I am removing from index " + String.valueOf(thisIndex));
                if(thisTenant.removeNoteAt(thisIndex, true)){
                    controller.populateListView();
                } else {
                    controller.populateListView();
                }
            }
        });

    } catch (Exception e) {
        ScreensFramework.logError.writeToFile(e.getMessage());
    }
}



@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;
        msg.setText(item!=null ? item : "<null>");
        setGraphic(hbox);
    }
}

}

编辑:在创建 ListView 单元格时,有什么方法可以将该单元格的当前索引传递给“CellFactory”吗?

问候, 亚历克斯

【问题讨论】:

    标签: java listview javafx custom-cell


    【解决方案1】:

    每个单元格都知道它的索引:

    public class Demo extends Application {
    
        ListView<String> list = new ListView<String>();
    
        ObservableList<String> data = FXCollections.observableArrayList(
                "chocolate", "salmon", "gold", "coral", "darkorchid",
                "darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
                "blueviolet", "brown");
    
        @Override
        public void start(Stage stage) {
            VBox box = new VBox();
            Scene scene = new Scene(box, 200, 200);
            stage.setScene(scene);
            box.getChildren().addAll(list);
            VBox.setVgrow(list, Priority.ALWAYS);
    
            list.setItems(data);
    
            list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
                @Override
                public ListCell<String> call(ListView<String> list) {
                    return new ButtonCell();
                }
            });
            stage.show();
        }
    
        static class ButtonCell extends ListCell<String> {
            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (item != null) {
                    final Button btn = new Button(item + " with index " + getIndex());
                    btn.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            System.out.println("I am a " + getItem() + " with index " + getIndex());
                        }
                    });
                    setGraphic(btn);
                } else {
                    setGraphic(null);
                }
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    【讨论】:

    • 我知道单元格知道它的索引,但是我放在该单元格内的按钮没有分配给它的索引(为什么要它,毕竟它是一个按钮)。
    • 我正在处理按钮单击的操作,用户从不单击列表项本身,而是单击该单元格内的按钮,这就是我需要通过 CellFactory 调用传递索引的原因。
    • @AlexSims。列表单元格和按钮都应该有相同的索引,对吧?在上面的代码中,当按钮被点击时,它也知道它的索引。
    • 已更新以显示我的 NoteCell 类代码 - 每次单击按钮时都会得到 -1
    • 在使用您的代码并进行一些修改后,我已经解决了这个问题 - 感谢 Uluk 的启发,您已经解决了一个令人头疼的问题! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多