【问题标题】:How to create a reorder-able TableView in JavaFx如何在 JavaFx 中创建可重新排序的 TableView
【发布时间】:2022-01-07 13:43:17
【问题描述】:

我有一个 JavaFx TableView。我想允许用户单击并拖动以重新排序表格行。我似乎找不到任何方法来做到这一点,但这在 GUI 中似乎很常见。

【问题讨论】:

  • 在我所有的 TableViews 中,您只需单击标题即可按该列重新排序。您可能需要为某些事情编写自定义比较器。如果您的意思是将列拖到新位置,那也可以。
  • @brian 我将其更新为更清晰。我的意思是拖动以重新排列表格 ROWS

标签: java user-interface javafx


【解决方案1】:

这是一些通过拖动行来重新排列 ListView 中的行的代码。

拖动小鸟重新排序。

TableView 的实现会有些相似。

import javafx.application.Application;
import javafx.collections.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.*;

public class ListOrganizer extends Application {
    private static final String PREFIX =
            "http://icons.iconarchive.com/icons/jozef89/origami-birds/72/bird";

    private static final String SUFFIX =
            "-icon.png";

    private static final ObservableList<String> birds = FXCollections.observableArrayList(
            "-black",
            "-blue",
            "-red",
            "-red-2",
            "-yellow",
            "s-green",
            "s-green-2"
    );

    private static final ObservableList<Image> birdImages = FXCollections.observableArrayList();

    @Override
    public void start(Stage stage) throws Exception {
        birds.forEach(bird -> birdImages.add(new Image(PREFIX + bird + SUFFIX)));

        ListView<String> birdList = new ListView<>(birds);
        birdList.setCellFactory(param -> new BirdCell());
        birdList.setPrefWidth(180);

        VBox layout = new VBox(birdList);
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.show();
    }

    public static void main(String[] args) {
        launch(ListOrganizer.class);
    }

    private class BirdCell extends ListCell<String> {
        private final ImageView imageView = new ImageView();

        public BirdCell() {
            ListCell thisCell = this;

            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            setAlignment(Pos.CENTER);

            setOnDragDetected(event -> {
                if (getItem() == null) {
                    return;
                }

                ObservableList<String> items = getListView().getItems();

                Dragboard dragboard = startDragAndDrop(TransferMode.MOVE);
                ClipboardContent content = new ClipboardContent();
                content.putString(getItem());
                dragboard.setDragView(
                    birdImages.get(
                        items.indexOf(
                            getItem()
                        )
                    )
                );
                dragboard.setContent(content);

                event.consume();
            });

            setOnDragOver(event -> {
                if (event.getGestureSource() != thisCell &&
                       event.getDragboard().hasString()) {
                    event.acceptTransferModes(TransferMode.MOVE);
                }

                event.consume();
            });

            setOnDragEntered(event -> {
                if (event.getGestureSource() != thisCell &&
                        event.getDragboard().hasString()) {
                    setOpacity(0.3);
                }
            });

            setOnDragExited(event -> {
                if (event.getGestureSource() != thisCell &&
                        event.getDragboard().hasString()) {
                    setOpacity(1);
                }
            });

            setOnDragDropped(event -> {
                if (getItem() == null) {
                    return;
                }

                Dragboard db = event.getDragboard();
                boolean success = false;

                if (db.hasString()) {
                    ObservableList<String> items = getListView().getItems();
                    int draggedIdx = items.indexOf(db.getString());
                    int thisIdx = items.indexOf(getItem());

                    Image temp = birdImages.get(draggedIdx);
                    birdImages.set(draggedIdx, birdImages.get(thisIdx));
                    birdImages.set(thisIdx, temp);

                    items.set(draggedIdx, getItem());
                    items.set(thisIdx, db.getString());

                    List<String> itemscopy = new ArrayList<>(getListView().getItems());
                    getListView().getItems().setAll(itemscopy);

                    success = true;
                }
                event.setDropCompleted(success);

                event.consume();
            });

            setOnDragDone(DragEvent::consume);
        }

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);

            if (empty || item == null) {
                setGraphic(null);
            } else {
                imageView.setImage(
                    birdImages.get(
                        getListView().getItems().indexOf(item)
                    )
                );
                setGraphic(imageView);
            }
        }
    }

    // Iconset Homepage: http://jozef89.deviantart.com/art/Origami-Birds-400642253
    // License: CC Attribution-Noncommercial-No Derivate 3.0
    // Commercial usage: Not allowed    

}

【讨论】:

  • 我能够通过使用行工厂而不是单元格将其移植到 TableView。
  • 只是一个提示,这不是一个很好的例子。它确实适合建议的场景,但无法在其他不使用 ListView 单元格内的图形的场景中复制您的代码。例如,我正在尝试使用节点(更具体地说是标签)代替 ImageView 来重现您的代码,但没有成功。
  • @FARS 如果您有新问题,请将其作为包含minimal reproducible example 的新问题提出。这个例子从来没有被设计为所有潜在的 ListView 重新排序用例的通用解决方案,它只是解决重新排序的一种潜在方法的演示,并且对许多其他用户很有用。如果您认为对此或其他相关用例有更好的解决方案或替代方案,请将其作为答案发布。
  • 我尝试这样做.. stackoverflow.com/questions/70176194/… 没有成功。如果您能提供一个通过拖动 ListView 的单元格来重新排序 ListView 的示例,我将不胜感激。就像您在此处所做的那样,但将 ImageView 和 Image 替换为任何类型的节点(逻辑上不使用图像)
  • @FARS 我不能。我现在没有时间这样做。
猜你喜欢
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
相关资源
最近更新 更多