如何在JavaFX中获取ListView中项目的位置? [英] How to get position of an item in ListView in JavaFX?

查看:171
本文介绍了如何在JavaFX中获取ListView中项目的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在JavaFX中创建一个像这样的ListView:

If I create a ListView in JavaFX like this:

ObservableList<String> elements = FXCollections.observableArrayList("John", "Doe");
ListView<String> lView = new ListView<String>(elements);

我想要做的是从ListView的一行开始画一条线,比如说来自John

What I want to do is draw a line starting from the end of a row in the ListView, say from "John"

为此,我需要行John的位置(x,y)。是否有可能获得该位置?

To do this, I need the location(x,y) of the row "John". Is it possible to get the location?

更新

这是一个示例我使用Swing和Piccolo2D获得的界面。但是,使用该库很痛苦。我想知道我是否可以在JavaFX中做同样的事情

This is a sample interface that I got using Swing and Piccolo2D. However, using that library is painful. I am wondering if I can do the same in JavaFX

推荐答案

这是可能的,但它可能不像你希望的那样直截了当。为了确定 ListView 中的特定 Cell 的布局坐标(或 TableView / TreeView )您需要访问该特定的 Cell 对象。最好的方法(也许只有JavaFX 2.2中的方法)是为容器提供自定义的 Cell CellFactory 公开每个 Cell 。如何公开 Cell 取决于你的触发器用于绘制线的内容。

It is possible, but it may not be as straight forward as you hoped. In order to determine the layout coordinates for a particular Cell within a ListView (or TableView/TreeView) you need to have access to that particular Cell object. The best way (and maybe only way in JavaFX 2.2) is to provide the container with a custom Cell and CellFactory that exposes each Cell. How you expose the Cell depends on what your triggers are for drawing the line.

基于你的插图,你填充 ListView 后,将需要访问每个单元格。您可以使用 CellFactory 中的 List< ListCell< String>> 字段执行此操作。我将在这里提一个关于 ListCell 的警告。只要有可能, ListViewSkin 将重复使用 Cell 。这意味着如果您要尝试填充并连接最终滚动的列表,那么将线条保持在正确的位置将会困难得多。我建议您尝试确保所有列表项都适合屏幕。

Bases on your illustration, you'll need access to each cell once the ListViews are populated. You can do this with a List<ListCell<String>> field in the CellFactory. I'll mention one caveat here about ListCells. The ListViewSkin will reuse Cells whenever possible. That means that if you are going to try to populate and connect a list that ends up scrolling, then keeping your lines in the right place will be much more difficult. I'd recommend trying to ensure that all your list items fit on screen.

下面是一个示例,其中包含注释中的一些注释。请注意,获取绘制 Line 的正确坐标可能需要计算SceneGraph的偏移量,我在此示例中没有这样做。

Below is an example with some notes in the comments. Take note that getting the correct coordinates for drawing your Line will probably require calculating the offset of your SceneGraph which I didn't do in this example.

package listviewcellposition;

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ListViewCellPosition extends Application {

    // CustomCellFactory for creating CustomCells
    public class CustomCellFactory implements
            Callback<ListView<String>, ListCell<String>> {

        List<ListCell<String>> allCells = new ArrayList<>();

        @Override
        public ListCell<String> call(final ListView<String> p) {
            final CustomCell cell = new CustomCell();
            allCells.add(cell);
            return cell;
        }

        public List<ListCell<String>> getAllCells() {
            return allCells;
        }
    }

    // CustomCell is where the exposure occurs. Here, it's based on the
    // Cell being selected in the ListView. You could choose a different
    // trigger here but you'll need to explore.
    public class CustomCell extends ListCell<String> {
        // General display stuff
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                setText(item == null ? "" : item);
                setGraphic(null);
            }
        }
    }

    @Override
    public void start(Stage primaryStage) {
        // This pane will contain the lines after they are created.
        // I set it into an AnchorPane to avoid having to deal with 
        // resizing.
        Pane linePane = new Pane();
        AnchorPane pane = new AnchorPane();
        pane.setPrefSize(100, 250);
        AnchorPane.setBottomAnchor(linePane, 0.0);
        AnchorPane.setLeftAnchor(linePane, 0.0);
        AnchorPane.setRightAnchor(linePane, 0.0);
        AnchorPane.setTopAnchor(linePane, 0.0);
        pane.getChildren().add(linePane);

        ListView<String> lView = new ListView<>();
        lView.setPrefSize(100, 250);
        CustomCellFactory lCellFactory = new CustomCellFactory();
        lView.setCellFactory(lCellFactory);

        ListView<String> rView = new ListView<>();
        rView.setPrefSize(100, 250);
        CustomCellFactory rCellFactory = new CustomCellFactory();
        rView.setCellFactory(rCellFactory);

        lView.getItems().addAll("Bill", "Doctor", "Steve", "Joanne");
        rView.getItems().addAll("Seuss", "Rowling", "King", "Shakespeare");

        HBox root = new HBox();
        root.getChildren().addAll(lView, pane, rView);

        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();

        connectCells(lCellFactory, "Bill", rCellFactory, "Shakespeare", linePane);
        connectCells(lCellFactory, "Doctor", rCellFactory, "Seuss", linePane);
        connectCells(lCellFactory, "Steve", rCellFactory, "King", linePane);
        connectCells(lCellFactory, "Joanne", rCellFactory, "Rowling", linePane);
    }

    // Looks up the ListCell<> for each String and creates a Line
    // with the coordinates from each Cell. The calculation is very 
    // contrived because I know that all the components have the same 
    // x-coordinate. You'll need more complicated calculations if your
    // containers are not aligned this way.
    private void connectCells(CustomCellFactory lCellFactory, String lVal,
            CustomCellFactory rCellFactory, String rVal, Pane linePane) {

        List<ListCell<String>> lList = lCellFactory.getAllCells();
        ListCell<String> lCell = null;

        for (ListCell<String> lc : lList) {
            if (lc.getItem() != null && lc.getItem().equals(lVal)) {
                lCell = lc;
                break;
            }
        }

        List<ListCell<String>> rList = rCellFactory.getAllCells();
        ListCell<String> rCell = null;

        for (ListCell<String> rc : rList) {
            if (rc.getItem() != null && rc.getItem().equals(rVal)) {
                rCell = rc;
                break;
            }
        }

        if (lCell != null && rCell != null) {
            double startY = lCell.getLayoutY() +
                    (lCell.getBoundsInLocal().getHeight() / 2);
            double endY = rCell.getLayoutY() +
                    (rCell.getBoundsInLocal().getHeight() / 2);

            Line line = new Line(0, startY, 
                    linePane.getBoundsInParent().getWidth(), endY);
            line.setStrokeWidth(2);
            line.setStroke(Color.BLACK);

            linePane.getChildren().add(line);
        }
    }   

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

这篇关于如何在JavaFX中获取ListView中项目的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆