[英]JavaFX - RadioButtons in TableCell with Add Data Button
I'm currently working on an application where I use a TableView
including RadioButton
s in one TableCell
.我目前正在开发一个应用程序,在该应用程序中我使用TableView
其中一个TableCell
包含RadioButton
。 For that I created an own RadioButtonCell
class.为此,我创建了一个自己的RadioButtonCell
类。 I also have a "Add new Row"-Button to let the user add some additional rows.我还有一个“添加新行”按钮,让用户添加一些额外的行。 After clicking the "Add" button a third time, I get more RadioButtonCell
s than rows.第三次单击“添加”按钮后,我得到的RadioButtonCell
比行多。 I don't find the mistake in my code.我在我的代码中没有发现错误。
Here a screenshot after clicking the Button
a third time:这是第三次单击Button
后的屏幕截图:
RadioButtonCell:单选按钮单元:
import java.util.EnumSet;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TableCell;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
public class RadioButtonCell<S,T extends Enum<T>> extends TableCell<S,T>{
private EnumSet<T> enumeration;
public RadioButtonCell(EnumSet<T> enumeration) {
this.enumeration = enumeration;
}
@Override
protected void updateItem(T item, boolean empty)
{
super.updateItem(item, empty);
if (!empty)
{
// GUI
HBox hb = new HBox(7);
hb.setAlignment(Pos.CENTER);
final ToggleGroup group = new ToggleGroup();
// create a radio button for each 'element' of the enumeration
for (Enum<T> enumElement : enumeration) {
RadioButton radioButton = new RadioButton(enumElement.toString());
radioButton.setUserData(enumElement);
radioButton.setToggleGroup(group);
hb.getChildren().add(radioButton);
if (enumElement.equals(item)) {
radioButton.setSelected(true);
}
}
// issue events on change of the selected radio button
group.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
@SuppressWarnings("unchecked")
@Override
public void changed(ObservableValue<? extends Toggle> observable,
Toggle oldValue, Toggle newValue) {
getTableView().edit(getIndex(), getTableColumn());
RadioButtonCell.this.commitEdit((T) newValue.getUserData());
}
});
setGraphic(hb);
}
}
}
Model:模型:
public class Points {
private final SimpleObjectProperty<Participation> participation = new SimpleObjectProperty<Participation>(); // radio buttons
public static enum Participation {
NONE, HALO, BORDER;
public String toString() {
return super.toString().toLowerCase();
};
}
/**
* Constructor.
* @param <Participation>
*/
public Points(Participation p) {
this.participation.setValue(p);
public void setParticipation(Participation p){
participation.set(p);
}
public Participation getParticipation(){
return participation.get();
}
public SimpleObjectProperty<Participation> ParticipationProperty() {
return participation;
}
}
FXML:文件格式:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox prefHeight="900.0" prefWidth="1250.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="address.view.DataOverviewController">
<children>
<SplitPane fx:id="splitPaneVertical" prefHeight="776.0" prefWidth="1200.0" VBox.vgrow="ALWAYS">
<items>
<TabPane fx:id="tabPane" stylesheets="@Theme.css">
<tabs>
<Tab text="Points">
<content>
<SplitPane fx:id="splitPaneHorizontal" dividerPositions="0.949874686716792" orientation="VERTICAL" stylesheets="@Theme.css">
<items>
<TableView fx:id="pointsDataTable">
<columns>
<TableColumn fx:id="pointsBackgroundColumn" prefWidth="200.0" resizable="false" text="Background" />
</columns>
</TableView>
<AnchorPane SplitPane.resizableWithParent="false">
<children>
<HBox fx:id="pointsHBoxButton" alignment="CENTER" prefHeight="35.0" prefWidth="1016.0" spacing="20.0" stylesheets="@Theme.css" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Button fx:id="pointsAddButton" mnemonicParsing="false" onAction="#handleAddPoints" text="Add" />
</children>
</HBox>
</children>
</AnchorPane>
</items>
</SplitPane>
</content>
</Tab>
</tabs>
</TabPane>
</items>
</SplitPane>
Controller:控制器:
public class DataOverviewController {
@FXML
private TableView<Points> pointsDataTable;
@FXML
private TableColumn<Points, Participation> pointsBackgroundColumn;
@FXML
private Button pointsButtonAdd;
public DataOverviewController() {
}
@FXML
private void initialize() {
// select multipe rows, make rows editable
pointsDataTable.setEditable(true);
pointsDataTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
linesDataTable.setEditable(true);
pointsBackgroundColumn.setCellFactory((param) -> new RadioButtonCell<Points, Participation>(EnumSet.allOf(Participation.class)));
pointsBackgroundColumn.setCellValueFactory(new PropertyValueFactory<Points, Participation>("Participation"));
pointsBackgroundColumn.setOnEditCommit(
new EventHandler<CellEditEvent<Points, Participation>>() {
@Override
public void handle(CellEditEvent<Points, Participation> t) {
((Points) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setParticipation(t.getNewValue());
}
}
);
public void setMainConfig(MainConfig mainConfig) {
// Add observable list data to the table
pointsDataTable.setItems(mainConfig.getTableDataPoints());
}
@FXML
private void handleAddPoints() {
// create new record and add it to the tableview
Points dataPoints = new Points(0, "Points", "TabFileName.tab",Participation.NONE, false, false, 18, "new");
pointsDataTable.getItems().add(dataPoints);
}
}
}
I reduced my code to the important parts.我将代码简化为重要部分。 Maybe someone can help?也许有人可以帮忙? Thanks.谢谢。
Items can be added as well as removed from TableCell
s.可以在TableCell
添加和删除项目。 This means you need to handle the case where the TableCell
becomes empty by undoing any changes done to the cell when a item was added.这意味着您需要通过撤消添加项目时对单元格所做的任何更改来处理TableCell
变空的情况。 Otherwise there may be TableCell
s that look as if they contain a item although they are actually empty.否则,可能会有TableCell
看起来好像包含一个项目,尽管它们实际上是空的。
A updateItem
method should look like this: updateItem
方法应如下所示:
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
// modifications to restore the empty state
} else {
// customized way of displaying the item
}
}
Furthermore I do not recommend recreating the Node
s for displaying the item in the cell every time the item is changed, since this means you'll have a lot of unnecessary node creations which is the thing TableView
is trying to avoid by reusing cells.此外,我不建议在每次更改项目时重新创建Node
以在单元格中显示项目,因为这意味着您将有很多不必要的节点创建,而TableView
试图通过重用单元来避免这种情况。 Store them in fields and keep them for later use instead.将它们存储在字段中并保留以备后用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.