首页 文章

如何使ListView可选但不可编辑

提问于
浏览
2

所以我正在编写一个javafx应用程序,我需要能够从列表视图中选择单元格(用于复制粘贴目的),但我不想让它可编辑,我的意思是,除非我想要,否则内容无法更改to(允许它通过按钮,例如) .

所以我有以下代码:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        List<String> contacts = new ArrayList<>(Arrays.asList("968787522","3424234234","2343234324"));
        ListView<String> contactsList = new ListView();
        contactsList.setItems(FXCollections.observableArrayList(contacts));
        //this gives me the ability to edit the row as text field but I want this text field to not be editable
        contactsList.setCellFactory(TextFieldListCell.forListView());
        StackPane pane = new StackPane();
        pane.getChildren().add(contactsList);
        primaryStage.setScene(new Scene(pane, 300, 275));
        primaryStage.show();    }


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

如果我设置' contactsList ' as not editable, I' m无法编辑,则不选择 .

如您所见(图像吼叫),我希望能够删除字符(文本可选但不可编辑) .
enter image description here

3 回答

  • 0

    所以在打破了我的脑袋,大量的研究和API阅读之后,我想出了一个解决方案 . 这完全是我想要做的 . 这是演示,如果有人需要它;)所以我的想法是,每当我们想要选择行的内容时,我们需要选择行,获取textField并将编辑设置为true或false(每次) . 因此,在我制作的演示中,我放置了一个按钮,以便您可以将编辑切换为true或false,以确保它正在工作,以及如何工作 .

    干杯 .

    我评论了一些代码以便更好地理解,如果您对此有任何疑问,请告诉我 .

    package sample;
    
    import com.sun.javafx.scene.control.skin.VirtualFlow;
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.collections.FXCollections;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.TextFieldListCell;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    
    public class Main extends Application {
    private boolean editable = false;
    
    public static  IndexedCell getCell(final Control control, final int index) {
        return getVirtualFlow(control).getCell(index);
    }
    
    public static VirtualFlow<?> getVirtualFlow(Control control) {
        Group group = new Group();
        Scene scene = new Scene(group);
        Stage stage = new Stage();
    
        if(control.getScene() == null) {
            group.getChildren().setAll(control);
            stage.setScene(scene);
            stage.show();
        }
    
        VirtualFlow<?>flow = (VirtualFlow<?>) control.lookup("#virtual-flow");
        return flow;
    }
    
    public void setEditable(ListView contactsList){
            //this needs to be done since we need to run our code after the text field was rendered
            //so we need to invoke our code after this happens, if not it will throw a null pointer...
            Platform.runLater(() -> {
                //this is one of the most important guys because javafx api says that
                //TextFieldListCell.forListView() allows editing of the cell content when the cell is double-clicked,
                // or when {@link ListView#edit(int)} is called.
                int rowIndex = contactsList.getSelectionModel().getSelectedIndex();
                contactsList.edit(rowIndex);
                ListCell rootCell = (ListCell) getCell(contactsList, rowIndex);
                TextField textField = (TextField) rootCell.getGraphic();
                textField.setEditable(editable);
            });
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception{
        List<String> contacts = new ArrayList<>(Arrays.asList("968787522","3424234234","2343234324"));
        ListView<String> contactsList = new ListView();
        contactsList.setItems(FXCollections.observableArrayList(contacts));
        contactsList.setEditable(true);
    
        //this gives me the ability to edit the row as text field but I want this text field to not be editable
        contactsList.setCellFactory(TextFieldListCell.forListView());
        contactsList.setOnEditStart(e -> {
            setEditable(contactsList);
        });
    
        StackPane pane = new StackPane();
        Button editBtn = new Button("Toggle edit");
        editBtn.setOnAction(event -> {
            editable = !editable;
            editBtn.setText("Editing = " + editable);
            //to cancel any editing that might be occuring
            contactsList.getSelectionModel().clearSelection();
        });
        pane.getChildren().addAll(contactsList,editBtn);
        primaryStage.setScene(new Scene(pane, 300, 275));
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
    }
    
  • 0

    如果我理解正确,则没有必要将列表视图设置为“不可编辑”,因为默认行为应该足以满足您的需要 . 看看这段代码,例如:

    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.ListView;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class NewFXMain extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            ListView listView = new ListView();
            listView.getItems().addAll("one","two","three","four");
    
            listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    System.out.println(listView.getSelectionModel().getSelectedItem());
                }
            });
    
            StackPane root = new StackPane();
            root.getChildren().add(listView);
            Scene scene = new Scene(root, 300, 250);
    
            primaryStage.setTitle("ListView Example");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    

    我没有改变ListView的可编辑属性,但我可以选择每个项目,而无法编辑它(从更改其值的意义上说) . 您可以轻松地将EventHandler添加到ListView以执行您要执行的任何操作 . 您还可以通过操作CellFactory将ListHandler添加到ListView的每个单元格,如下面的答案所示:How to handle ListView item clicked action?

  • 1

    这对我有用:

    TableView<DataBean> table = new TableView<>();
        table.setItems(...); // list of some DataBean objects with dataBeanField proprty
        table.setEditable(true);
    
        TableColumn<DataBean, String> column = new TableColumn<>("SomeData");
        column.setCellValueFactory(new PropertyValueFactory<DataBean, String>("dataBeanField"));
        column.setCellFactory(new Callback<TableColumn<DataBean, String>, TableCell<DataBean, String>>() {
            @Override
            public TableCell<DataBean, String> call(TableColumn<DataBean, String> param) {
                return new TextFieldTableCell<>(new DefaultStringConverter() {
                    private String defaultValue = "";
    
                    @Override
                    public String fromString(String newValue) {
                        return super.fromString(defaultValue);
                    }
    
                    @Override
                    public String toString(String value) {
                        return defaultValue = super.toString(value);
                    }
                });
            }
        });
    

相关问题