我正在使用intellij想法在javafx中填充表格视图。我只有一个表格视图和一个文本字段,每次我键入内容时,它都会运行一段更新表格的代码。它可以工作一段时间,但是在某个时候会生成NullPointerException,该异常会阻止表继续更新。我想捕获此异常,但是它是由不在我的主程序包中的一些代码生成的。问题是:表已成功填充,但是经过多次更新后才生成NPE。
这是我的控制器代码
Controller.java
package MainPackage;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import java.net.URL;
import java.sql.*;
import java.util.ResourceBundle;
public class Controller implements Initializable
{
@FXML
public TextField textField;
@FXML
public TableView tableViewPazienti;
Connection connection;
// DATA INSIDE THE TABLE
public ObservableList<Paziente> data;
TableViewTools tableViewTools;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
SqliteConnection conn = new SqliteConnection();
connection = conn.connector();
tableViewTools = new TableViewTools(connection);
textField.textProperty().addListener(e -> updateP());
tableViewPazienti.getColumns().addAll(tableViewTools.buildColumns("P"));
tableViewPazienti.setItems(tableViewTools.buildData("P"));
}
private void updateP() {
tableViewPazienti.getItems().clear();
tableViewPazienti.getColumns().clear();
tableViewPazienti.getColumns().addAll(tableViewTools.buildColumns("P"));
tableViewPazienti.setItems(tableViewTools.buildData("P", textField.getText()));
}
}
这是我的TableViewTools类,在其中生成数据和列
TableViewTools.java
package MainPackage;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TableViewTools
{
Connection connection;
public TableViewTools(Connection connection){
this.connection = connection;
}
// THIS METHOD RETURNS ALL THE COLUMNS OF THE CHOSEN TABLE FROM THE DATABASE
public ObservableList<TableColumn> buildColumns(String tableName) {
ObservableList<TableColumn> observableList = FXCollections.observableArrayList();
String SQL = "select * from " + tableName;
PreparedStatement preparedStatement = null;
ResultSet rs = null;
try {
preparedStatement = connection.prepareStatement(SQL);
}
catch (Exception e) {
e.printStackTrace();
}
try {
rs = preparedStatement.executeQuery();
// FOR EVERY COLUMNS EXTRACTED FROM THE DATABASE...
for(int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
// ...I GET THE COLUMN NAME...
String columnName = rs.getMetaData().getColumnName(i);
// ...I CREATE A NEW TABLE COLUMN...
TableColumn tempColumn = new TableColumn(columnName);
// ...AND IF THE TABLE NAME EQUALS TO "P"... (in future it can be something different)
if(tableName.equals("P")){
// ...I SET THE CELL VALUE FACTORY TO STORE THE DATA...
tempColumn.setCellValueFactory(
new PropertyValueFactory<Paziente,String>(columnName)
);
}
// ...AND FINALLY I ADD THE COLUMN TO THE TABLE.
observableList.add(tempColumn);
}
}
catch (SQLException e) {
e.printStackTrace();
}
return observableList;
}
// THIS METHOD EXTRACTS ALL THE ROWS FROM THE DATABASE AND CREATE A Paziente OBJECT
// FOR EVERY ROW EXTRACTED
@SuppressWarnings("Duplicates")
public ObservableList buildData(String tableName){
ObservableList data = FXCollections.observableArrayList();
String SQL = "select * from " + tableName;
PreparedStatement preparedStatement = null;
ResultSet rs = null;
try {
preparedStatement = connection.prepareStatement(SQL);
}
catch (Exception e) {
e.printStackTrace();
}
try {
rs = preparedStatement.executeQuery();
while(rs.next()) {
if(tableName == "P"){
data.add(new Paziente(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6), rs.getString(7), rs.getString(8)));
}
}
}
catch (SQLException e){
e.printStackTrace();
}
return data;
}
// SAME THING AS BEFORE BUT WITH A DIFFERENT QUERY
@SuppressWarnings("Duplicates")
public ObservableList buildData(String tableName, String textFieldContent){
ObservableList data = FXCollections.observableArrayList();
String[] nameSurname = this.makeNameAndSurname(textFieldContent);
String SQL = "SELECT * FROM " + tableName +" WHERE Nome LIKE ? AND Cognome LIKE ? OR Nome LIKE ? AND Cognome LIKE ?";
PreparedStatement preparedStatement = null;
ResultSet rs = null;
try {
preparedStatement = connection.prepareStatement(SQL);
preparedStatement.setString(1, nameSurname[0]);
preparedStatement.setString(2, nameSurname[1]);
preparedStatement.setString(3, nameSurname[1]);
preparedStatement.setString(4, nameSurname[0]);
}
catch (Exception e) {
e.printStackTrace();
}
try {
rs = preparedStatement.executeQuery();
while(rs.next()) {
if(tableName == "P"){
data.add(new Paziente(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6), rs.getString(7), rs.getString(8)));
}
}
}
catch (SQLException e){
e.printStackTrace();
}
return data;
}
// THIS METHOD GET A STRING LIKE "Name Surname", DO STRANGE THINGS TO MAKE IT LIKE "%N%a%m%e% %S%u%r%n%a%m%e%"
// THEN RETURNS AN ARRAY OF STRING MADE OF String[0] = %N%a%m%e% and String[1] = %S%u%r%n%a%m%e%
// IT SHOULDN'T BE RELEVANT TO THE RESOLUTION OF THE PROBLEM
public String[] makeNameAndSurname(String textFieldContent){
String nome, cognome;
String textField = textFieldContent;
textField = textField.trim();
textField = textField.replaceAll("\\s+", " ");
String[] nameAndSurname = textField.split("");
String newTextField = "%";
for(int i = 0; i < nameAndSurname.length; i++) {
newTextField += nameAndSurname[i];
newTextField += "%";
}
String arr[] = newTextField.split(" ");
if(arr.length >= 2){
nome = arr[0];
cognome = arr[1];
}
else{
nome = arr[0];
cognome = "%";
}
String[] tmp = new String[2];
tmp[0] = nome;
tmp[1] = cognome;
return tmp;
}
}
最后,这是我的Paziente课
Paziente.java
package MainPackage;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Paziente {
private StringProperty ID;
private StringProperty Nome;
private StringProperty Cognome;
private StringProperty Eta;
private StringProperty Indirizzo;
private StringProperty Referente;
private StringProperty Telefono;
private StringProperty DataIngresso;
public Paziente(String ID, String Nome, String Cognome, String Eta, String Indirizzo, String Referente, String Telefono, String DataIngresso){
this.ID = new SimpleStringProperty(ID);
this.Nome = new SimpleStringProperty(Nome);
this.Cognome = new SimpleStringProperty(Cognome);
this.Eta = new SimpleStringProperty(Eta);
this.Indirizzo = new SimpleStringProperty(Indirizzo);
this.Referente = new SimpleStringProperty(Referente);
this.Telefono = new SimpleStringProperty(Telefono);
this.DataIngresso = new SimpleStringProperty(DataIngresso);
}
public String getID() {
return ID.get();
}
public StringProperty IDProperty() {
return ID;
}
public void setID(String ID) {
this.ID.set(ID);
}
public String getNome() {
return Nome.get();
}
public StringProperty nomeProperty() {
return Nome;
}
public void setNome(String nome) {
this.Nome.set(nome);
}
public String getCognome() {
return Cognome.get();
}
public StringProperty cognomeProperty() {
return Cognome;
}
public void setCognome(String cognome) {
this.Cognome.set(cognome);
}
public String getEta() {
return Eta.get();
}
public StringProperty etaProperty() {
return Eta;
}
public void setEta(String eta) {
this.Eta.set(eta);
}
public String getIndirizzo() {
return Indirizzo.get();
}
public StringProperty indirizzoProperty() {
return Indirizzo;
}
public void setIndirizzo(String indirizzo) {
this.Indirizzo.set(indirizzo);
}
public String getReferente() {
return Referente.get();
}
public StringProperty referenteProperty() {
return Referente;
}
public void setReferente(String referente) {
this.Referente.set(referente);
}
public String getTelefono() {
return Telefono.get();
}
public StringProperty telefonoProperty() {
return Telefono;
}
public void setTelefono(String telefono) {
this.Telefono.set(telefono);
}
public String getDataIngresso() {
return DataIngresso.get();
}
public StringProperty dataIngressoProperty() {
return DataIngresso;
}
public void setDataIngresso(String dataIngresso) {
this.DataIngresso.set(dataIngresso);
}
}
这是我的fxml
MainUI.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainPackage.Controller">
<children>
<MenuBar layoutX="137.0" layoutY="30.0" AnchorPane.bottomAnchor="675.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<TextField fx:id="textField" layoutX="14.0" layoutY="56.0" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="56.0" />
<TableView fx:id="tableViewPazienti" layoutX="14.0" layoutY="105.0" prefHeight="577.0" prefWidth="1172.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="109.0" />
</children>
</AnchorPane>
这是完整的堆栈跟踪
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.controls/javafx.scene.control.skin.TableCellSkin.tableColumnProperty(TableCellSkin.java:97)
at javafx.controls/javafx.scene.control.skin.TableCellSkinBase.getTableColumn(TableCellSkinBase.java:123)
at javafx.controls/javafx.scene.control.skin.TableCellSkinBase.dispose(TableCellSkinBase.java:136)
at javafx.controls/javafx.scene.control.skin.TableCellSkin.dispose(TableCellSkin.java:88)
at javafx.controls/javafx.scene.control.Control$2.invalidated(Control.java:267)
at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
at javafx.graphics/javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82)
at javafx.controls/javafx.scene.control.Control$2.set(Control.java:250)
at javafx.controls/javafx.scene.control.Control$2.set(Control.java:233)
at javafx.controls/javafx.scene.control.Control.setSkin(Control.java:230)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:715)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:505)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.checkState(TableRowSkinBase.java:649)
at javafx.controls/javafx.scene.control.skin.TableRowSkinBase.computePrefHeight(TableRowSkinBase.java:588)
at javafx.controls/javafx.scene.control.Control.computePrefHeight(Control.java:570)
at javafx.graphics/javafx.scene.Parent.prefHeight(Parent.java:1044)
at javafx.graphics/javafx.scene.layout.Region.prefHeight(Region.java:1561)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.resizeCellSize(VirtualFlow.java:1863)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:1948)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1250)
at javafx.controls/javafx.scene.control.skin.VirtualFlow$5.invalidated(VirtualFlow.java:837)
at javafx.base/javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)
at javafx.base/javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:148)
at javafx.controls/javafx.scene.control.skin.VirtualFlow.setCellCount(VirtualFlow.java:855)
at javafx.controls/javafx.scene.control.skin.TableViewSkinBase.updateItemCount(TableViewSkinBase.java:549)
at javafx.controls/javafx.scene.control.skin.VirtualContainerBase.checkState(VirtualContainerBase.java:170)
at javafx.controls/javafx.scene.control.skin.VirtualContainerBase.layoutChildren(VirtualContainerBase.java:145)
at javafx.controls/javafx.scene.control.skin.TableViewSkinBase.layoutChildren(TableViewSkinBase.java:407)
at javafx.controls/javafx.scene.control.Control.layoutChildren(Control.java:601)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1211)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1218)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:590)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2507)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
at java.base/java.lang.Thread.run(Thread.java:844)