【问题标题】:User inputs data to tableview using a button用户使用按钮向 tableview 输入数据
【发布时间】:2021-10-21 13:55:10
【问题描述】:

我需要制作一个 JavaFX 程序,其中用户在使用 FXML 构建组件时使用文本字段输入名称并使用切换按钮输入速度。我已经为此工作了几天,但没有任何运气。

<TableView fx:id="table" layoutX="200.0" prefHeight="420.0" prefWidth="461.0">
        <columns>
          <TableColumn fx:id="firstn" prefWidth="75.0" text="First Name" />
          <TableColumn fx:id="lastn" prefWidth="75.0" text="Last Name" />
            <TableColumn fx:id="addresss" prefWidth="75.0" text="Address" />
            <TableColumn fx:id="speeed" prefWidth="84.0" text="Speed(mb/s)" />
            <TableColumn fx:id="bwidth" prefWidth="75.0" text="Bandwidth" />
            <TableColumn fx:id="durationn" prefWidth="75.0" text="Duration" />
        </columns>
      </TableView>
      <TextField fx:id="fname" layoutX="14.0" layoutY="46.0" promptText="First Name" />
      <TextField fx:id="lname" layoutX="14.0" layoutY="71.0" promptText="Last Name" />
      <TextField fx:id="address" layoutX="14.0" layoutY="96.0" promptText="Address" />
      <Button layoutX="31.0" layoutY="339.0" mnemonicParsing="false" onAction="#save1" text="Save Package" />
<ToggleButton fx:id="sp1" layoutX="11.0" layoutY="169.0" mnemonicParsing="false" text="2">
         <toggleGroup>
            <ToggleGroup fx:id="speed" />
         </toggleGroup>
      </ToggleButton>
      <ToggleButton fx:id="sp2" layoutX="34.0" layoutY="169.0" mnemonicParsing="false" text="5" toggleGroup="$speed" />
      <ToggleButton fx:id="sp3" layoutX="57.0" layoutY="169.0" mnemonicParsing="false" text="10" toggleGroup="$speed" />
      <ToggleButton fx:id="sp4" layoutX="85.0" layoutY="169.0" mnemonicParsing="false" text="20" toggleGroup="$speed" />
      <ToggleButton fx:id="sp5" layoutX="114.0" layoutY="169.0" mnemonicParsing="false" text="50" toggleGroup="$speed" />
      <ToggleButton fx:id="sp6" layoutX="143.0" layoutY="169.0" mnemonicParsing="false" text="100" toggleGroup="$speed" />
      <ToggleButton fx:id="ba1" layoutX="13.0" layoutY="237.0" mnemonicParsing="false" text="1">
         <toggleGroup>
            <ToggleGroup fx:id="bandw" />
         </toggleGroup>
      </ToggleButton>
      <ToggleButton fx:id="ba2" layoutX="37.0" layoutY="237.0" mnemonicParsing="false" text="5" toggleGroup="$bandw" />
      <ToggleButton fx:id="ba3" layoutX="61.0" layoutY="237.0" mnemonicParsing="false" text="10" toggleGroup="$bandw" />
      <ToggleButton fx:id="ba4" layoutX="89.0" layoutY="237.0" mnemonicParsing="false" text="100" toggleGroup="$bandw" />
      <ToggleButton fx:id="ba5" layoutX="125.0" layoutY="237.0" mnemonicParsing="false" text="Flat" toggleGroup="$bandw" />
      <ToggleButton fx:id="du1" layoutX="13.0" layoutY="295.0" mnemonicParsing="false" text="1 year">
         <toggleGroup>
            <ToggleGroup fx:id="duration" />
         </toggleGroup>
      </ToggleButton>
      <ToggleButton fx:id="du2" layoutX="70.0" layoutY="295.0" mnemonicParsing="false" text="2 years" toggleGroup="$duration" />

    @FXML
    private TextField fname;
    @FXML
    private TextField lname;
    @FXML
    private TextField address;
    @FXML
    private ToggleGroup speed;
    @FXML
    private ToggleGroup bandw;
    @FXML
    private ToggleGroup duration;
    @FXML
    private TableView<Person> table = new TableView<Person>();
public void save1(ActionEvent e){
        ObservableList<Person> data = table.getItems();
        data.add(new Person(fname.getText(),lname.getText(),address.getText(),
               speed.getSelectedToggle(),bandw.getSelectedToggle(),duration.getSelectedToggle()));
table.setItems(data);
    }

基本上,我的程序应该是这样的,但是我无法将保存按钮添加到 tableview。

【问题讨论】:

  • 从不将通过 @FXML 初始化的变量设置为 new 值。
  • 你能把它扩展成minimal reproducible example吗?
  • 要添加到TableView,只需将一个新对象添加到您在其中显示的List&lt;Person&gt;。您无需多次致电table.setItems()。一个简单的table.getItems().add(new Person()) 就足够了。话虽如此,没有minimal reproducible example,我们无法确定您的问题是什么。
  • 无关:最好学习 Java 命名约定并坚持下去。这将帮助您避免使用诸如“速度”、“持续时间”和“地址”等令人困惑的 fx:id 值。

标签: java javafx fxml


【解决方案1】:

您已经走在正确的轨道上,但也有一些事情是您做错和遗漏的。在发布工作代码 sn-p 之前,我将强调几点。

  1. @FXML 用于将FXML 文档中定义的组件注入到控制器中。因此,您不应将新组件分配给注入的属性。 因此,
@FXML
    private TableView<Person> table = new TableView<Person>();

应该改为

@FXML
    private TableView<Person> table;
  1. 由于您在FXML 文档中定义了表格列,因此您需要将它们注入控制器,但不推荐。

  2. 您需要为每个表格列配置单元格值工厂。这有助于 JavaFx 知道哪个 Person 属性属于哪个表列。

  3. speed.getSelectedToggle() 正在返回一个 Toggle 对象,这可能不是您想要的行为。

以下是我编辑的一些类。

Controller class

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;

import java.net.URL;
import java.util.ResourceBundle;

public class TableViewController implements Initializable {
    @FXML private TextField fname;
    @FXML private TextField lname;
    @FXML private TextField address;
    @FXML private ToggleGroup speed;
    @FXML private ToggleGroup bandw;
    @FXML private ToggleGroup duration;

    //INject both table and column from the fxml file
    @FXML private TableView<Person> table;
    @FXML private TableColumn<Person,String> firstn;
    @FXML private TableColumn<Person,String> lastn;
    @FXML private TableColumn<Person,String> addresss;
    @FXML private TableColumn<Person,String> speeed;
    @FXML private TableColumn<Person,String> bwidth;
    @FXML private TableColumn<Person,String> durationn;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

        //Configure which property of the Person object belongs to which table column by
        //setting cell value factor for each column
        firstn.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
        lastn.setCellValueFactory(new PropertyValueFactory<Person,String>("lastName"));
        addresss.setCellValueFactory(new PropertyValueFactory<Person,String>("address"));
        speeed.setCellValueFactory(new PropertyValueFactory<Person,String>("speed"));
        bwidth.setCellValueFactory(new PropertyValueFactory<Person,String>("bandWidth"));
        durationn.setCellValueFactory(new PropertyValueFactory<Person,String>("duration"));
    }
    public void save1(ActionEvent e){
        //Get selected Toggle buttons
        ToggleButton selectedSpeed = (ToggleButton) speed.getSelectedToggle();
        ToggleButton selectedDuration = (ToggleButton) duration.getSelectedToggle();
        ToggleButton selectedBandwidth = (ToggleButton) bandw.getSelectedToggle();

        //Create a person from the input data
        Person person  = new Person(fname.getText(), lname.getText(), address.getText(),
                selectedSpeed.getText(), selectedBandwidth.getText(), selectedDuration.getText());

        //Add the person to the table data source
        table.getItems().add(person);
    }
}

Person class

public class Person {
    private String firstName;
    private String lastName;
    private String address;
    private String speed;
    private String bandWidth;
    private String duration;

    public Person(String firstName, String lastName, String address, String speed, String bandWidth, String duration) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
        this.speed = speed;
        this.bandWidth = bandWidth;
        this.duration = duration;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getSpeed() {
        return speed;
    }

    public void setSpeed(String speed) {
        this.speed = speed;
    }

    public String getBandWidth() {
        return bandWidth;
    }

    public void setBandWidth(String bandWidth) {
        this.bandWidth = bandWidth;
    }

    public String getDuration() {
        return duration;
    }

    public void setDuration(String duration) {
        this.duration = duration;
    }
}

【讨论】:

  • 我认为您需要更新您的 JavaFX 知识。控制器类不需要实现接口Initializable,只需要定义方法public void initialize()即可。请参阅 Java 文档中的 Introduction to FXML。另外,建议不要使用PropertyValueFactory类,而是简单地实现Callback接口。
  • @Abra 感谢您提出这些观点。但是,我认为这些都不是过时的知识。您删除的链接还在给定的一些示例中实现了initializable 接口。我还认为,如果需要访问其他资源(如URLResourceBundle),应该实现initializable 接口。对于Callback,我明白了。我在生产代码上使用Callback。我只使用了PropertyValueFactory,因为问题已经在fxml 文档中定义了表格列。无论如何感谢您的积分。
  • 仅供参考 - initialize() 方法不需要是 public
  • ”这可能不是问题,因为会调用 ToggletoString() 方法”。这不是真的。在这种情况下,如果 Person 构造函数参数是 String,则会出现编译错误。
  • 谢谢@James_D,我已经更正了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 2022-12-06
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 2012-09-12
  • 1970-01-01
相关资源
最近更新 更多