Hallo, dies ist meine erste Frage als Neuling in Java und GUI-Design. Ich bin auf eine merkwürdige Situation gestoßen, die ich gerade sehe. Ich habe TableView mit einigen Informationen, die auch mit der Schaltfläche Hinzufügen hinzugefügt werden können. Die Löschen-Schaltfläche funktionierte vor dem Hinzufügen eines FilterList-Konstruktors, sodass ich die Suchergebnisse nach ID filtern konnte. Sobald ich die Funktion hinzugefügt habe, funktioniert die Schaltfläche Löschen nicht mehr. Ich persönlich denke, dass die deleteButtonClicked-Klasse die Tabelle aufgrund der Änderung durch Hinzufügen der Filter-Funktionalität nicht mehr richtig erkennt. Aber so sehr ich versuche, beides zu behalten, hört der eine oder andere normalerweise auf zu arbeiten. Ich versuche derzeit, es ohne eine Delete Button-Klasse funktionieren zu lassen, vielleicht indem ich das Produkt einfach null mache.JavaFX GUI - Warum funktioniert die Delete Button Funktion nicht mit dem TableView?
Die TableView-Funktionen befinden sich oben im Code, während die Löschschaltfläche und die Funktionen nach unten zeigen.
package application;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
public class MainApp extends Application {
TableView<Product> table = new TableView<>();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
BorderPane leftPane = new BorderPane();
FilteredList<Product> filterList = new FilteredList<>(productData);
table.setEditable(true);
//table.setItems(productData); // DELETE BUTTON WORKS WHEN THIS ONE IS ONLY SET
table.setItems(filterList); // DELETE BUTTON DOESN'T WORK WHEN
// THIS IS SET BUT, IS NEEDED TO FILTER SEARCH FUNCTIONS
TableColumn<Product, String> idNumberCol = new TableColumn<>("ID Number");
idNumberCol.setMinWidth(50);
idNumberCol.setCellValueFactory(new PropertyValueFactory<>("idNumber"));
idNumberCol.setCellFactory(TextFieldTableCell.<Product>forTableColumn());
idNumberCol.setOnEditCommit(
(CellEditEvent<Product, String> t) -> {
((Product) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setIdNumber(t.getNewValue());
});
TableColumn<Product, String> desCol = new TableColumn<>("Description");
desCol.setMinWidth(150);
desCol.setCellValueFactory(new PropertyValueFactory<>("description"));
desCol.setCellFactory(TextFieldTableCell.<Product>forTableColumn());
desCol.setOnEditCommit(
(CellEditEvent<Product, String> t) -> {
((Product) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setDescription(t.getNewValue());
});
TableColumn<Product, String> expCol = new TableColumn<>("Expiration");
expCol.setMinWidth(100);
expCol.setCellValueFactory(new PropertyValueFactory<>("expiration"));
expCol.setCellFactory(TextFieldTableCell.<Product>forTableColumn());
expCol.setOnEditCommit(
(CellEditEvent<Product, String> t) -> {
((Product) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setExpiration(t.getNewValue());
});
table.getColumns().addAll(idNumberCol, desCol, expCol);
VBox leftVbox = new VBox();
leftVbox.setPadding(new Insets(10, 20, 20, 20));
leftVbox.setSpacing(10);
leftVbox.getChildren().addAll(table);
BorderPane topPane = new BorderPane();
HBox topHbox = new HBox(); //Create HBox
topHbox.setPadding(new Insets(20, 20, 10, 20)); // Set padding and spacing for the hbox
topHbox.setSpacing(10); // The hbox will appropriately space out more
Text txtSearch = new Text("Search: ");
topHbox.getChildren().add(txtSearch);
txtSearch.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
TextField txt = new TextField(""); // Create new TextField
txt.setPrefWidth(250);
txt.setPromptText("Search A Product ID"); // Sets up hint text inside the TextField
topHbox.getChildren().add(txt); // Add the TextField to the second hbox
HBox rightHbox = new HBox(); //Create HBox
rightHbox.setPadding(new Insets(20, 20, 10, 20)); // Set padding and spacing for the hbox
rightHbox.setSpacing(10); // The hbox will appropriately space out more
Text txtDetails = new Text("Product Details");
rightHbox.getChildren().add(txtDetails);
txtDetails.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
txt.textProperty().addListener((obsVal, oldValue, newValue) -> {
filterList.setPredicate(product -> product.getIdNumber().contains(newValue));
});
BorderPane rightPane = new BorderPane();
VBox rightVbox = new VBox();
rightVbox.setPadding(new Insets(20, 10, 10, 20));
rightVbox.setSpacing(30);
rightVbox.setAlignment(Pos.TOP_LEFT);
Text txtId = new Text("ID: ");
rightVbox.getChildren().add(txtId);
txtId.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
Text txtDes = new Text("Description: ");
rightVbox.getChildren().add(txtDes);
txtDes.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
Text txtExp = new Text("Expiration: ");
rightVbox.getChildren().add(txtExp);
txtExp.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
Text txtStatus = new Text("Status: ");
rightVbox.getChildren().add(txtStatus);
txtStatus.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
Text txtEnter = new Text("Entered By: ");
rightVbox.getChildren().add(txtEnter);
txtEnter.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
//EMPTY PLACE HOLDER INFORMATION TO POPULATE THE DATA
Label lblId;
Label lblDes;
Label lblExp;
Label lblStatus;
Label lblEnter;
HBox bottomHbox2 = new HBox();
bottomHbox2.setPadding(new Insets(20, 20, 20, 20));
bottomHbox2.setSpacing(10);
bottomHbox2.setAlignment(Pos.BOTTOM_RIGHT);
Button btnNew = new Button("Add...");
bottomHbox2.getChildren().add(btnNew);
btnNew.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Stage secondStage = new Stage();
BorderPane dialogPane = new BorderPane();
VBox dialogVbox = new VBox();
dialogVbox.setPadding(new Insets(20, 10, 20, 20));
dialogVbox.setSpacing(20);
TextField addId = new TextField();
addId.setPromptText("ID Number");
addId.setMinWidth(50);
//addId.setMaxWidth(idNumberCol.getPrefWidth());
TextField addDes = new TextField();
addDes.setPromptText("Description");
addDes.setMinWidth(100);
//addDes.setMaxWidth(desCol.getPrefWidth());
TextField addExp = new TextField();
addExp.setPromptText("Expiration Date");
addExp.setMinWidth(50);
//addExp.setMaxWidth(expCol.getPrefWidth());
dialogVbox.getChildren().addAll(addId, addDes, addExp);
VBox dialogVbox2 = new VBox();
dialogVbox2.setPadding(new Insets(20, 20, 20, 10));
dialogVbox2.setSpacing(20);
Text txtIdLabel = new Text("ID: ");
dialogVbox2.getChildren().add(txtIdLabel);
txtIdLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
Text txtDesLabel = new Text("Description: ");
dialogVbox2.getChildren().add(txtDesLabel);
txtDesLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
Text txtExpLabel = new Text("Expiration: ");
dialogVbox2.getChildren().add(txtExpLabel);
txtExpLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16));
HBox addHbox = new HBox();
addHbox.setPadding(new Insets(20, 10, 50, 20));
addHbox.setSpacing(10);
addHbox.setAlignment(Pos.BOTTOM_RIGHT);
Button btnAdd = new Button("Add Product");
addHbox.getChildren().add(btnAdd);
btnAdd.setOnAction((ActionEvent e) -> {
productData.add(new Product(
addId.getText(),
addDes.getText(),
addExp.getText()));
addId.clear();
addDes.clear();
addExp.clear();
});
Button btnClose = new Button("Close");
addHbox.getChildren().add(btnClose);
btnClose.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent arg0) {
secondStage.close();
}
});
dialogPane.setCenter(dialogVbox);
dialogPane.setLeft(dialogVbox2);
dialogPane.setBottom(addHbox);
Scene scene2 = new Scene(dialogPane, 400, 200);
secondStage.setTitle("Add New Product");
secondStage.setScene(scene2);
secondStage.show();
//Set position of second window, related to primary window.
secondStage.setX(primaryStage.getX() + 250);
secondStage.setY(primaryStage.getY() + 100);
secondStage.show();
}
});
// DELETE BUTTON & EVENT HANDLER
Button btnDelete = new Button("Delete");
bottomHbox2.getChildren().add(btnDelete);
btnDelete.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent arg0) {
deleteButtonClicked();
}
});
Button btnSave = new Button("Save & Exit");
bottomHbox2.getChildren().add(btnSave);
btnSave.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent arg0) {
primaryStage.close();
}
});
rightVbox.getChildren().add(bottomHbox2);
topPane.setLeft(topHbox);
topPane.setCenter(rightHbox);
leftPane.setLeft(leftVbox);
rightPane.setLeft(rightVbox);
//rightPane.setCenter(bottomHbox2);
root.setTop(topPane);
root.setLeft(leftPane);
root.setCenter(rightPane);
Scene scene = new Scene(root, 650, 500);
primaryStage.setTitle("Perishables Application");
primaryStage.setScene(scene);
primaryStage.show();
}
// DELETE BUTTON FUNCTION
public void deleteButtonClicked() {
ObservableList<Product> productSelected, productData;
productData = table.getItems();
productSelected = table.getSelectionModel().getSelectedItems();
productSelected.forEach(productData::remove);
}
public ObservableList<Product> productData = FXCollections.observableArrayList(
new Product("001", "Cereal", "1/1/2017"),
new Product("002", "Dog Food", "3/3/2017"),
new Product("003", "Juice", "1/1/2018")
);
}
Alle Vorschläge werden sehr geschätzt. Danke fürs Lesen.
Wow danke, dass und eine sehr einfache Lösung gearbeitet zu. Hat "das" getan. arbeiten, weil es direkt auf das aktuelle Objekt verweist? Wollen Sie in einfachen Worten erklären, warum es in dieser Situation benötigt wird? Weil, wie ich erklärte, es ohne vorher gut funktioniert hat, das ist das, was mich verwirrt hat. Danke noch einmal. – BecauseTurtles
@BecauseTurtles Bevor Sie in Ihrem Code '.getItems()' verwenden, haben Sie die 'FilteredList' zurückbekommen und versucht, Elemente daraus zu entfernen. Aber die 'FilteredList ' hat ursprünglich die Elemente der 'ObservableList', also Sie möchten die Objekte aus der "ObservableList" entfernen. Dadurch werden sie automatisch aus der 'FilteredList ' entfernt. Ich benutze 'this', um auf die äußere' ObservableList' zu verweisen. –
GOXR3PLUS