我有这个JavaFX表,当我单击右键单击鼠标上下文菜单并选择"删除"时,我想删除一行。
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Callback;
public class MainApp extends Application
{
private TableView<Person> table = new TableView<>();
private final ObservableList<Person> data
= FXCollections.observableArrayList(
new Person("Processor", "72"),
new Person("RAM", "78"),
new Person("HDD Free Space", "890"),
new Person("Lan Adapter NIC 1", "36"),
new Person("Lan Adapter NIC 2", "67"));
public static void main(String[] args)
{
launch(args);
}
@Override
public void start(Stage stage)
{
//Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
//stage.setWidth(850);
//stage.setHeight(550);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(false);
Callback<TableColumn, TableCell> cellFactory
= new Callback<TableColumn, TableCell>()
{
@Override
public TableCell call(TableColumn p)
{
return new EditingCell();
}
};
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
TableColumn firstNameCol = new TableColumn("Credentials");
//firstNameCol.setPrefWidth(300);
firstNameCol.setMinWidth(50);
//firstNameCol.prefWidthProperty().bind(table.widthProperty().divide(2)); // w * 1/2
firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
firstNameCol.setCellFactory(cellFactory);
firstNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>()
{
@Override
public void handle(CellEditEvent<Person, String> t)
{
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())).setFirstName(t.getNewValue());
}
}
);
TableColumn lastNameCol = new TableColumn("Value");
//lastNameCol.setPrefWidth(300);
lastNameCol.setMinWidth(50);
//lastNameCol.prefWidthProperty().bind(table.widthProperty().divide(2)); // w * 1/2
lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
lastNameCol.setCellFactory(cellFactory);
lastNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>()
{
@Override
public void handle(CellEditEvent<Person, String> t)
{
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())).setLastName(t.getNewValue());
}
}
);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol);
VBox vbox = new VBox();
VBox.setVgrow(table, Priority.ALWAYS);
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 10, 10, 10));
vbox.getChildren().addAll(label, table);
Scene scene = new Scene(vbox);
stage.setScene(scene);
stage.show();
}
public static class Person
{
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private Person(String fName, String lName)
{
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
}
public String getFirstName()
{
return firstName.get();
}
public void setFirstName(String fName)
{
firstName.set(fName);
}
public String getLastName()
{
return lastName.get();
}
public void setLastName(String fName)
{
lastName.set(fName);
}
}
class EditingCell extends TableCell<Person, String>
{
private TextField textField;
public EditingCell()
{
}
@Override
public void startEdit()
{
if (!isEmpty())
{
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
@Override
public void cancelEdit()
{
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
@Override
public void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (empty)
{
setText(null);
setGraphic(null);
}
else
{
if (isEditing())
{
if (textField != null)
{
textField.setText(getString());
}
setText(null);
setGraphic(textField);
}
else
{
setText(getString());
setGraphic(null);
setContextMenu(intiContextmenu());
}
}
}
private void createTextField()
{
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.focusedProperty().addListener(new ChangeListener<Boolean>()
{
@Override
public void changed(ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2)
{
if (!arg2)
{
commitEdit(textField.getText());
}
}
});
}
private String getString()
{
return getItem() == null ? "" : getItem().toString();
}
}
public ContextMenu intiContextmenu()
{
final ContextMenu contextMenu = new ContextMenu();
contextMenu.setOnShowing(
new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent e)
{
System.out.println("showing");
}
}
);
contextMenu.setOnShown(new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent e)
{
System.out.println("shown");
}
});
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("Delete row");
item3.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("Delete row");
}
});
contextMenu.getItems().addAll(item1, item2, item3);
return contextMenu;
}
}
问题是如何使用上下文菜单从Observable列表中删除Java Object?也许我需要获取Credentials
值并将其用作删除行的键?
答案 0 :(得分:7)
单击时,该行将被选中。这是我使用的简化代码。
TableView<LineItem> tv = new TableView<>(items);
Stack<LineItem> deletedLines = new Stack<>();
tv.setUserData(deletedLines);
MenuItem mnuDel = new MenuItem("Delete row");
mnuDel.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
LineItem item = items.get(tv.getSelectionModel().getSelectedIndex());
if (item != null){
String fn = item.getFirstName();
deletedLines.push(items.remove(item));
}
}
});
MenuItem mnuUnDel = new MenuItem("Undo Delete");
mnuUnDel.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
if (!deletedLines.isEmpty())items.add(deletedLines.pop());
}
});
tv.setContextMenu(new ContextMenu(mnuDel,mnuUnDel));
答案 1 :(得分:4)
请参阅here的解决方案:
private TableView<Person> table = new TableView<Person>();
...
table.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
@Override
public TableRow<Person> call(TableView<Person> tableView) {
final TableRow<Person> row = new TableRow<>();
final ContextMenu contextMenu = new ContextMenu();
final MenuItem removeMenuItem = new MenuItem("Remove");
removeMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
table.getItems().remove(row.getItem());
}
});
contextMenu.getItems().add(removeMenuItem);
// Set context menu on row, but use a binding to make it only show for non-empty rows:
row.contextMenuProperty().bind(
Bindings.when(row.emptyProperty())
.then((ContextMenu)null)
.otherwise(contextMenu)
);
return row ;
}
});
这对我很有帮助。
答案 2 :(得分:0)
获取所选项目并将其删除。
MenuItem item3 = new MenuItem("Delete row");
item3.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("Delete row");
Person p = table.getSelectionModel().getSelectedItem();
if(p!=null) {
data.remove(p);
}
}
});