20

すべての ListView アイテムの後にイメージ ボタンを追加できるかどうかを知りたいです。例えば:サンプル

これらの赤い四角には代わりにボタンが必要です。可能であれば、アイテムのボタンのクリック イベントを処理するにはどうすればよいですか?

編集:それを行うことができる別のコントロールがある場合は、お知らせください。私はTableViewをテストしています。

前もって感謝します!

4

3 に答える 3

35

私は最近これをテストしていました。私の解決策:

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);
    }
}

セルは次のようになります。

ボタン付きのカスタム リスト セル

関連する部分はXCell.updateItemメソッドとsetGraphic呼び出しです。通常、アイコンはラベルにsetGraphic()設定されますが、複雑なノード (この場合はラベルとボタンを持つ HBox) を設定する場合も同様に機能します。

ボタンのイベント ハンドラーがリスト内の正しい項目を参照していることを確認する必要があります。以下の最初のリンクでは、現在選択されているアイテムで十分である可能性があることが言及されています。したがって、ボタンのイベントを処理するときに、リストで現在選択されているインデックスを取得します。

あなたはこれらを見たいかもしれません:

于 2013-03-28T20:02:53.813 に答える
3

カスタム HBox オブジェクトの List も使用できます。以下の例は、そのようなカスタム 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);
     }
}

この実装の結果は次のようになります。

ここに画像の説明を入力

ただし、Buttons イベントを効果的に管理するには、追加のカスタム Button オブジェクトを HBoxCustom コンストラクター メソッドに追加することを検討し、ボタンのクリック イベントを制御できる適切なメソッドを作成する必要があります。

于 2014-07-11T10:15:42.610 に答える
0

私のリストが大きくなく、ノードをより複雑にするコントロールを追加しなかった場合、以前のソリューションはうまく機能しました。さらにコントロールを追加すると、同時実行性の問題が見つかりました。これは、12000 を超えるオブジェクト (ラインとポリゴン) を含むマップを描画していることが原因かもしれません。問題 (私が見ることができたもの) は、ListView の一部の項目が内部的に繰り返されることで、cellfactory が 2 回作成されるか、作成されないことを意味します。「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<>();
        }
    });

fxexperience.com で推奨されているシンプルな DefaultListCell を使用しました

于 2013-07-31T17:26:23.507 に答える