我正在创建一个TableView来显示有关自定义对象列表(EntityEvents)的信息。
表视图必须有2列。显示相应EntityEvent名称的第一列。第二列将显示一个按钮。按钮文本依赖于EntityEvent的属性。如果属性为零,则为“创建”,否则为“编辑”。
我做得很好,只是当相应的EntityEvent对象更改时,我找不到更新TableView行的方法。
非常重要:我不能将EntityEvent类更改为使用JavaFX属性,因为它们不在我的控制之下。此类使用PropertyChangeSupport在监视的属性更改时通知侦听器。
注意:我意识到向列表中添加新元素可能会导致TableView重新绘制自己,但这不是我所需要的。我这么说可能是因为我读到了一些影响这种行为的bug。我尝试使用这种方法来强制重新绘制,但我无法使其工作。
有人知道怎么做吗?
非常感谢。
下面是一个简化的代码示例,演示了该场景:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
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.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
public class Main extends Application {
//=============================================================================================
public class EntityEvent {
private String m_Name;
private PropertyChangeSupport m_NamePCS = new PropertyChangeSupport(this);
private int m_ActionCounter;
private PropertyChangeSupport m_ActionCounterPCS = new PropertyChangeSupport(this);
public EntityEvent(String name, int actionCounter) {
m_Name = name;
m_ActionCounter = actionCounter;
}
public String getName() {
return m_Name;
}
public void setName(String name) {
String lastName = m_Name;
m_Name = name;
System.out.println("Name changed: " + lastName + " -> " + m_Name);
m_NamePCS.firePropertyChange("Name", lastName, m_Name);
}
public void addNameChangeListener(PropertyChangeListener listener) {
m_NamePCS.addPropertyChangeListener(listener);
}
public int getActionCounter() {
return m_ActionCounter;
}
public void setActionCounter(int actionCounter) {
int lastActionCounter = m_ActionCounter;
m_ActionCounter = actionCounter;
System.out.println(m_Name + ": ActionCounter changed: " + lastActionCounter + " -> " + m_ActionCounter);
m_ActionCounterPCS.firePropertyChange("ActionCounter", lastActionCounter, m_ActionCounter);
}
public void addActionCounterChangeListener(PropertyChangeListener listener) {
m_ActionCounterPCS.addPropertyChangeListener(listener);
}
}
//=============================================================================================
private class AddPersonCell extends TableCell<EntityEvent, String> {
Button m_Button = new Button("Undefined");
StackPane m_Padded = new StackPane();
AddPersonCell(final TableView<EntityEvent> table) {
m_Padded.setPadding(new Insets(3));
m_Padded.getChildren().add(m_Button);
m_Button.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent actionEvent) {
// Do something
}
});
}
@Override protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(m_Padded);
m_Button.setText(item);
}
}
}
//=============================================================================================
private ObservableList<EntityEvent> m_EventList;
//=============================================================================================
@SuppressWarnings("unchecked")
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Table View test.");
VBox container = new VBox();
m_EventList = FXCollections.observableArrayList(
new EntityEvent("Event 1", -1),
new EntityEvent("Event 2", 0),
new EntityEvent("Event 3", 1)
);
final TableView<EntityEvent> table = new TableView<EntityEvent>();
table.setItems(m_EventList);
TableColumn<EntityEvent, String> eventsColumn = new TableColumn<>("Events");
TableColumn<EntityEvent, String> actionCol = new TableColumn<>("Actions");
actionCol.setSortable(false);
eventsColumn.setCellValueFactory(new Callback<CellDataFeatures<EntityEvent, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<EntityEvent, String> p) {
EntityEvent event = p.getValue();
event.addActionCounterChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
// TODO: I'd like to update the table cell information.
}
});
return new ReadOnlyStringWrapper(event.getName());
}
});
actionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EntityEvent, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<EntityEvent, String> ev) {
String text = "NONE";
if(ev.getValue() != null) {
text = (ev.getValue().getActionCounter() != 0) ? "Edit" : "Create";
}
return new ReadOnlyStringWrapper(text);
}
});
// create a cell value factory with an add button for each row in the table.
actionCol.setCellFactory(new Callback<TableColumn<EntityEvent, String>, TableCell<EntityEvent, String>>() {
@Override
public TableCell<EntityEvent, String> call(TableColumn<EntityEvent, String> personBooleanTableColumn) {
return new AddPersonCell(table);
}
});
table.getColumns().setAll(eventsColumn, actionCol);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
// Add Resources Button
Button btnInc = new Button("+");
btnInc.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent ev) {
System.out.println("+ clicked.");
EntityEvent entityEvent = table.getSelectionModel().getSelectedItem();
if (entityEvent == null) {
System.out.println("No Event selected.");
return;
}
entityEvent.setActionCounter(entityEvent.getActionCounter() + 1);
// TODO: I expected the TableView to be updated since I modified the object.
}
});
// Add Resources Button
Button btnDec = new Button("-");
btnDec.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent ev) {
System.out.println("- clicked.");
EntityEvent entityEvent = table.getSelectionModel().getSelectedItem();
if (entityEvent == null) {
System.out.println("No Event selected.");
return;
}
entityEvent.setActionCounter(entityEvent.getActionCounter() - 1);
// TODO: I expected the TableView to be updated since I modified the object.
}
});
container.getChildren().add(table);
container.getChildren().add(btnInc);
container.getChildren().add(btnDec);
Scene scene = new Scene(container, 300, 600, Color.WHITE);
primaryStage.setScene(scene);
primaryStage.show();
}
//=============================================================================================
public Main() {
}
//=============================================================================================
public static void main(String[] args) {
launch(Main.class, args);
}
}
尝试javafx。豆子。所有物适配器类,尤其是JavaBeanStringProperty和JavaBeanIntergerProperty。我没有用过这些,但我想你可以这样做
TableColumn<EntityEvent, Integer> actionCol = new TableColumn<>("Actions");
actionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EntityEvent, Integer> ev) {
return new JavaBeanIntegerPropertyBuilder().bean(ev.getValue()).name("actionCounter").build();
});
// ...
public class AddPersonCell extends TableCell<EntityEvent, Integer>() {
final Button button = new Button();
public AddPersonCell() {
setPadding(new Insets(3));
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
button.setOnAction(...);
}
@Override
public void updateItem(Integer actionCounter, boolean empty) {
if (empty) {
setGraphic(null);
} else {
if (actionCounter.intValue()==0) {
button.setText("Create");
} else {
button.setText("Add");
}
setGraphic(button);
}
}
}
正如我所说,我没有使用Java bean属性适配器类,但其思想是将属性更改事件“转换”为JavaFX更改事件。我只是在这里输入了这个,没有进行测试,但它至少应该给你一些开始的东西。
更新:经过一点实验后,我认为如果您的EntityEvent真的按照您在代码示例中显示的方式设置,那么这种方法就行不通了。标准的JavaBeans绑定属性模式(JavaFX属性适配器所依赖的)有一个属性更改侦听器和一个addPropertyChangeListener(…)方法(监听器可以查询事件以查看更改了哪个属性。)
我想如果你这样做
public class EntityEvent {
private String m_Name;
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private int m_ActionCounter;
public EntityEvent(String name, int actionCounter) {
m_Name = name;
m_ActionCounter = actionCounter;
}
public String getName() {
return m_Name;
}
public void setName(String name) {
String lastName = m_Name;
m_Name = name;
System.out.println("Name changed: " + lastName + " -> " + m_Name);
pcs.firePropertyChange("name", lastName, m_Name);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
public int getActionCounter() {
return m_ActionCounter;
}
public void setActionCounter(int actionCounter) {
int lastActionCounter = m_ActionCounter;
m_ActionCounter = actionCounter;
System.out.println(m_Name + ": ActionCounter changed: " + lastActionCounter + " -> " + m_ActionCounter);
pcs.firePropertyChange("ActionCounter", lastActionCounter, m_ActionCounter);
}
}
它将与上面的适配器类一起工作。显然,如果您有调用addActionChangeListener和addNameChangeListener方法的现有代码,那么您可能希望保留这些现有方法和现有属性更改侦听器,但我认为没有理由不能两者兼有。
我正在使用Android MVVM架构和LiveData。我有一个这样的物体 我的视图模型是这样的 如何确保用户对象中的某个字段发生更改时,观察员收到通知?顺便说一句,重要的是要将这些数据保存在单独的对象中,而不是在ViewModel中使用字符串等主要值。
问题内容: 单击时,我必须调整tableView的一行的大小。我该怎么做?有人可以帮助我吗? 我的视图控制器类: 问题答案: 首先,您必须跟踪属性中当前选定单元格的indexPath: 它应该是可选的,因为您不能选择任何单元格。接下来让我们声明选定状态和未选定状态的高度(将值更改为所需的值): 现在您必须实现: 现在,在您的方法中,您必须检查是否选中了选定行或未选定行: 该和电话是给你一个动画的高
我试图理解hibernate是如何工作的,即在类上放置@Entity是如何使它成为一个持久类的?即
我的课程注册项目应该有很多方法,比如(添加课程),(添加导师),等等(添加学生())就是其中之一,我想知道每次创建对象时如何更改对象的变量(std)我不知道每个对象如何都有相同的变量 那么,我想把变量改为std1、std2之类的任何建议 我想知道这是不是我做错了什么? 如果每个对象都用相同的变量声明,那么它会将每个创建的对象的数据克隆到新创建的对象? 谢谢你。
问题内容: 我是Postgresql的新手,正在使用9.3版。我有一张桌子,里面有几行。我的问题是,当我更新一行时,该行号被更改并将其移动到表中的最后一个位置。我的问题是:这是否是默认行为,因为我认为在更新行时,不应将其从其位置移开?该操作似乎就像先删除然后再插入该行。 这是示例SQL: 从今起: 将ID为1的更新后的行移动到最后一个位置。 谢谢 问题答案: 行号已更改 关系表中没有“行号”之类的