在javafx中如何用单个模型操作多个tableview?

问题描述 投票:0回答:1

不是我的问题,只是要澄清一下: 我正在尝试开发一个包含多个表格视图的应用程序。这些表格视图是在运行时单击按钮时创建的。我设法使用选项卡和选项卡完成此任务,并且还设法向这些选项卡添加不同的表格视图。通过该用户可以根据自己的需要创建表。选项卡在这里可以关闭,并可以通过单击按钮创建任意数量的用户想要的选项卡。一个选项卡包含一个表格视图。

我的问题: 所以在这里我只用一种模型处理太多的表格视图。这些表格视图包含每个列和单元格上的文本字段和按钮。它还具有在表视图中添加和删除行的功能。 所以这是我的主要问题,当用户单击按钮在特定表视图中添加行时,该行会自动添加到另一个选项卡中的另一个表视图(我不想要)中。当未选择表视图或用户不想添加行时,我不想在表视图中添加行。删除行时也会发生同样的情况。 那么,如何在多个表视图上添加和删除行而不出现任何这些问题?

这是我尝试过但失败的代码。给出大量代码块的目的是为了明确我是否走在正确的道路上。如果没有,请显示执行此操作的正确路径。

public static ObservableList<myModel> list = FXCollections.observableArrayList();

// in @override initialize method

tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
            @Override
            public void changed(ObservableValue<? extends Tab> observableValue, Tab oldValue, Tab newValue) {
                System.out.println("Tab selected: " + newValue.getText());

                if (newValue.getContent() == null) {
                    System.out.println("New table created");
                    TableView<myModel> tableView = new TableView<>();
                    TableColumn<myModel, String> columnA = new TableColumn<>("A");
                    TableColumn<myModel, String> ColumnB = new TableColumn<>("B");
                    TableColumn<myModel, String> ColumnC = new TableColumn<>("C");
                    TableColumn<myModel, String> ColumnD = new TableColumn<>("D");
                    TableColumn<myModel, String> ColumnE = new TableColumn<>("E");
                    TableColumn<myModel, Button> ColumnF = new TableColumn<>("F");

                    Callback<TableColumn<myModel, Button>, TableCell<myModel, Button>> btncellFactory =
                            new Callback<TableColumn<myModel, Button>, TableCell<myModel, Button>>() {
                                @Override
                                public TableCell<myModel, Button> call(TableColumn<myModel, Button> elementsStringTableColumn) {
                                    final TableCell<myModel, Button> cell = new TableCell<myModel, Button>() {
                                        private final Button button = new Button("Delete");
                                        {
                                            button.setFocusTraversable(false);
                                            button.setOnAction((ActionEvent event) -> {
                                                System.out.println("Deleting rows");
                                                TableRow row = this.getTableRow();
                                                row.updateSelected(true);
                                                System.out.println("row item: " + row.getItem() +" Index: "+ (row.getIndex()+1) + row.isSelected());
                                                getTableView().getItems().remove(row.getIndex()); //remove rows but not specific with tableviews thats why remove rows from all tableview
                                            });
                                        }
                                        @Override
                                        public void updateItem(Button item, boolean empty) {
                                            super.updateItem(item, empty);
                                            if (empty) {
                                                setGraphic(null);
                                            } else {
                                                setGraphic(button);
                                            }
                                        }
                                    };

                                    return cell;
                                }
                            };

                    columnA.setCellFactory(ACellFactory.cell());
                    ColumnB.setCellFactory(BCellFactory.cell());
                    ColumnC.setCellFactory(CCellFactory.cell());
                    ColumnD.setCellFactory(DCellFactory.cell());
                    ColumnE.setCellFactory(ECellFactory.cell());
                    ColumnF.setCellFactory(btncellFactory);

                    addRowBtn.setOnMouseClicked(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent mouseEvent) {
                            list.add(new mymodel(myModel.getA(), myModel.getB(), myModel.getC(), myModel.getD(), myModel.getE()));  // on button click create a row
                        }
                    });

                    // I tried to do this to be specific on tableview which is on selected tab but failed
                    if (newValue.getText().equals(newValue.getText())) tableView.setItems(list);
                    tableView.getColumns().setAll(columnA, ColumnB, ColumnC, ColumnD, ColumnE, ColumnF);
                    newValue.setContent(tableView);

                } else System.out.println("Containing table: " + newValue.getContent());

            }

        });                       
  

如果有人提供解决此问题的代码,请添加有关您的代码块实际用途的评论。

java javafx javafx-tableview
1个回答
0
投票

所以在这里我只用一个模型处理太多的表格视图。

假设我正确理解你的问题,解决方案就是显而易见的:为每个表使用不同的模型(即不同的

ObservableList
)。

如果您只是以正常方式进行设置,也就是说,只需创建一个带有添加和删除按钮的表视图以及表视图的模型,然后每次向选项卡式窗格添加一个新模型,那么默认情况下基本上会发生这种情况你需要。

这是一个简单的例子。首先,表项的模型类:

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Item {
    private final StringProperty name = new SimpleStringProperty();
    public Item(String name) {
        setName(name);
    }
    public StringProperty nameProperty(){
        return name;
    }

    public final String getName() {
        return nameProperty().get();
    }

    public final void setName(String name) {
        nameProperty().set(name);
    }
}

带有表视图的 FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<BorderPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="org.jamesd.examples.tabbedtables.ItemTableController">

    <center>
        <TableView fx:id="table">
            <columns>
                <TableColumn fx:id="nameCol"/>
            </columns>
        </TableView>
    </center>
    <bottom>
        <HBox spacing="5">
            <padding><Insets topRightBottomLeft="5"/></padding>
            <TextField fx:id="nameField" onAction="#addItem"/>
            <Button text="Add" onAction="#addItem"/>
            <Button fx:id="removeButton" text="Remove" onAction="#deleteSelected" />
        </HBox>
    </bottom>

</BorderPane>

及其控制器,它在这里创建项目列表(您可以按照您需要的任何方式重构它,只要您为控制器的每个实例都有一个新列表):


import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;

public class ItemTableController {

    private final ObservableList<Item> itemList = FXCollections.observableArrayList();
    @FXML
    private Button removeButton;

    @FXML
    private TableView<Item> table;
    @FXML
    private TextField nameField;
    @FXML
    private TableColumn<Item, String> nameCol;

    @FXML
    private void initialize() {
        table.setItems(itemList);
        nameCol.setCellValueFactory(data -> data.getValue().nameProperty());
        removeButton.disableProperty().bind(Bindings.isEmpty(table.getSelectionModel().getSelectedItems()));
    }

    @FXML
    private void addItem() {
        Item item = new Item(nameField.getText());
        itemList.add(item);
        nameField.clear();
    }

    public void deleteSelected(ActionEvent actionEvent) {
        itemList.remove(table.getSelectionModel().getSelectedItem());
    }
}

这是“主”视图,带有选项卡窗格和用于添加新选项卡的按钮(每个选项卡中都有表格):

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<BorderPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="org.jamesd.examples.tabbedtables.TabbedTablesController">
    <center>
        <TabPane fx:id="tabPane"/>
    </center>
    <bottom>
        <HBox alignment="CENTER">
            <padding><Insets topRightBottomLeft="10"/></padding>
            <Button text="New Table" onAction="#newTable"/>
        </HBox>
    </bottom>

</BorderPane>

及其控制器,该控制器加载第一个 FXML 并将其包装在选项卡中添加到选项卡窗格中:

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;

import java.io.IOException;

public class TabbedTablesController {
    @FXML
    private TabPane tabPane;

    @FXML
    private void newTable() throws IOException {
        Tab tab = new Tab(STR."Table \{tabPane.getTabs().size() + 1}");
        tab.setContent(FXMLLoader.load(getClass().getResource("ItemTable.fxml")));
        tabPane.getTabs().add(tab);
        tabPane.getSelectionModel().select(tab);
    }
}

最后是应用类:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class TabbedTableApp extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(TabbedTableApp.class.getResource("TabbedTables.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 800, 500);
        stage.setScene(scene);
        stage.show();
    }

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

由于表的每个控制器创建不同的后备列表,因此表的数据是独立的。这是添加两个新表(向第一个表添加两个项目,向第二个表添加一个项目)后的屏幕截图:

© www.soinside.com 2019 - 2024. All rights reserved.