`

JavaFX学习之样例7

阅读更多
  该代码是个可编辑的table。
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.logging.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.collections.*;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Callback;

// click in the value column (a couple of times) to edit the value in the column.
// property editors are defined only for String and Boolean properties.
// change focus to something else to commit the edit.
public class TableViewPropertyEditor extends Application {
	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(Stage stage) {
		final Person aPerson = new Person("Fred", true);
		final Label currentObjectValue = new Label(aPerson.toString());

		TableView<NamedProperty> table = new TableView();
		table.setEditable(true);

		table.setItems(createNamedProperties(aPerson));

		TableColumn<NamedProperty, String> nameCol = new TableColumn("Name");
		nameCol.setCellValueFactory(new PropertyValueFactory<NamedProperty, String>(
				"name"));

		TableColumn<NamedProperty, Object> valueCol = new TableColumn("Value");
		valueCol.setCellValueFactory(new PropertyValueFactory<NamedProperty, Object>(
				"value"));
		valueCol.setCellFactory(new Callback<TableColumn<NamedProperty, Object>, TableCell<NamedProperty, Object>>() {
			@Override
			public TableCell<NamedProperty, Object> call(
					TableColumn<NamedProperty, Object> param) {
				return new EditingCell();
			}
		});

		//提交后更新pojo的值
		valueCol.setOnEditCommit(new EventHandler<CellEditEvent<NamedProperty, Object>>() {
			@Override
			public void handle(CellEditEvent<NamedProperty, Object> t) {
				int row = t.getTablePosition().getRow();
				NamedProperty property = (NamedProperty) t.getTableView()
						.getItems().get(row);
				 property.setValue(t.getNewValue());
				 currentObjectValue.setText(aPerson.toString());
			}
		});

		table.getColumns().setAll(nameCol, valueCol);
		table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

		VBox layout = new VBox(10);
		layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
		layout.getChildren().setAll(currentObjectValue, table);
		VBox.setVgrow(table, Priority.ALWAYS);

		stage.setScene(new Scene(layout, 650, 600));
		stage.show();
	}

	private ObservableList<NamedProperty> createNamedProperties(Object object) {
		ObservableList<NamedProperty> properties = FXCollections
				.observableArrayList();

		for (Method method : object.getClass().getMethods()) {
			String name = method.getName();
			Class type = method.getReturnType();
			if (type.getName().endsWith("Property")) {
				try {
					properties.add(new NamedProperty(name, (Property) method
							.invoke(object)));
				} catch (IllegalAccessException ex) {
					Logger.getLogger(TableViewPropertyEditor.class.getName())
							.log(Level.SEVERE, null, ex);
				} catch (InvocationTargetException ex) {
					Logger.getLogger(TableViewPropertyEditor.class.getName())
							.log(Level.SEVERE, null, ex);
				} catch (IllegalArgumentException ex) {
					Logger.getLogger(TableViewPropertyEditor.class.getName())
							.log(Level.SEVERE, null, ex);
				}
			}
		}

		return properties;
	}

	public class NamedProperty {
		public NamedProperty(String name, Property value) {
			nameProperty.set(name);
			valueProperty = value;
		}

		private StringProperty nameProperty = new SimpleStringProperty();

		public StringProperty nameProperty() {
			return nameProperty;
		}

		public StringProperty getName() {
			return nameProperty;
		}

		public void setName(String name) {
			nameProperty.set(name);
		}

		private Property valueProperty;

		public Property valueProperty() {
			return valueProperty;
		}

		public Object getValue() {
			return valueProperty.getValue();
		}

		public void setValue(Object value) {
			valueProperty.setValue(value);
		}
	}

	public class Person {
		private final SimpleStringProperty firstName;
		private final SimpleBooleanProperty married;

		private Person(String firstName, Boolean isMarried) {
			this.firstName = new SimpleStringProperty(firstName);
			this.married = new SimpleBooleanProperty(isMarried);
		}

		public SimpleStringProperty firstNameProperty() {
			return firstName;
		}

		public SimpleBooleanProperty marriedProperty() {
			return married;
		}

		public String getFirstName() {
			return firstName.get();
		}

		public void setFirstName(String fName) {
			firstName.set(fName);
		}

		public Boolean getMarried() {
			return married.get();
		}

		public void setMarried(Boolean isMarried) {
			married.set(isMarried);
		}

		@Override
		public String toString() {
			return firstName.getValue() + ": " + married.getValue();
		}
	}

	class EditingCell extends TableCell<NamedProperty, Object> {
		private TextField textField;
		private CheckBox checkBox;

		public EditingCell() {
		}

		@Override
		public void startEdit() {  //开始编辑时,设置Graphic
			if (!isEmpty()) {
				super.startEdit();

				if (getItem() instanceof Boolean) {
					createCheckBox();
					setText(null);
					setGraphic(checkBox);
				} else {
					createTextField();
					setText(null);
					setGraphic(textField);
					textField.selectAll();
				}
			}
		}

		@Override
		public void cancelEdit() { //结束编辑时,取消Graphic,设置text
			super.cancelEdit();
			System.out.println("cancel");
			if (getItem() instanceof Boolean) {
				setText(getItem().toString());
			} else {
				setText((String) getItem());
			}
			setGraphic(null);
		}

		@Override
		public void updateItem(Object item, boolean empty) {
			super.updateItem(item, empty);
			if (getIndex() < 2) {
				NamedProperty property = getTableView().getItems().get(
						getIndex());
				System.out.println("property=" + property.getValue());
				System.out.println("item=" + getItem());
			}
			if (empty) {
				setText(null);
				setGraphic(null);
			} else {
				if (isEditing()) {
					if (getItem() instanceof Boolean) {   //为boolean就设置checkbox
						if (checkBox != null) {
							checkBox.setSelected(getBoolean());
						}
						setText(null);
						setGraphic(checkBox);
					} else {                     //设置textFiled
						if (textField != null) {
							textField.setText(getString());
						}
						setText(null);
						setGraphic(textField);
					}
				} else {
					setText(getString());
					setGraphic(null);
				}
			}
		}

		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> observable,
								Boolean oldValue, Boolean newValue) {
							if (!newValue) {
							    commitEdit(textField.getText());  //传递值
							}
						}
					});
		}

		private void createCheckBox() {
			checkBox = new CheckBox();
			checkBox.setSelected(getBoolean());
			checkBox.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
			checkBox.focusedProperty().addListener(
					new ChangeListener<Boolean>() {
						@Override
						public void changed(
								ObservableValue<? extends Boolean> observable,
								Boolean oldValue, Boolean newValue) {
							if (!newValue) {
								commitEdit(checkBox.isSelected());
							}
						}
					});
		}

		private String getString() {
			return getItem() == null ? "" : getItem().toString();
		}

		private Boolean getBoolean() {
			return getItem() == null ? false : (Boolean) getItem();
		}
	}
}

一般使用自定义tableCell实现cell的多样化,重写updateItem,设置Graphic和Text内容。若要实现编辑功能则可以重写startEdit和cancelEdit方法,这样就有在需要编辑时,显示需要的node,取消时,只显示text。

需要注意的地方是需要实现column.setOnEditCommit方法,更新pojo的值。因为cell的值对应pojo里面的get的值,若你不更新pojo,则cell值不变。
举个例子:value column的cell即对应NamedProperty的getValue。在方法updateItem里面参数item和getItem()方法获取的对象均等于getValue()。
但是当我注释掉setOnEditCommit方法里面的property.setValue(t.getNewValue()); 然后编辑value值,按逻辑来说getValue()没变,页面显示的值应该不会变化, 但是结果却变了。我在updateItem方法里面输出item和NamedProperty的getValue,发现不一样了。这让我疑惑了。我在想不应该啊,这二个值应该一样的。我试着重新加载,也就是把窗口缩小,直到看不到那行记录,然后在拉大(table会重新加载)。再一输出,页面显示的值变回来了,二个打印一样了。Item和getItem()的值始终是来自pojo的get方法的。
在代码里面可以看到,通过监听checkBox和textField的焦点集中属性来传递修改后的值。
commitEdit(textField.getText());  //传递值

正是通过commitEdit方法,修改了item的值。然后在cancel里面获取item的值,此时是最新的(在这里发现为什么item和get方法的值不一样了)。其实也不需要这样做,直接在cancel里面textField.getText或checkBox.isSelected获取最新值。

理解不对的地方希望大家评论下

这里有个javafx学习的中文网站,我把内容都丢那上面去了。
http://www.jfxee.com/
分享到:
评论

相关推荐

    JavaFX学习之样例8

    这个"JavaFX学习之样例8"可能是一个教程或示例集合,用于教授如何使用JavaFX来创建一个特定的图形元素,比如时钟。在这个例子中,我们可能将学习如何利用JavaFX的图形和动画功能来构建一个可交互的模拟时钟。 首先...

    javafx2introbyexample:javaFX中的样例代码

    7. **动画和转换**:JavaFX的`Timeline`和`Transition`类允许创建各种动态效果,如淡入淡出、平移、旋转等。这些动画使得应用程序更加生动和吸引人。 8. **图表组件**:JavaFX内置了多种图表组件,如线图、柱状图、...

    JavaFX2开发教程

    运行时还允许你体验官方提供的样例程序,这些样例展示了JavaFX的各种功能,源代码可供学习参考。 在NetBeans环境中配置JavaFX开发环境是另一个关键步骤。JavaFX2.0在Mac系统上的安装提供了更丰富的功能,如高性能...

    GUI样例.7z

    在本压缩包"GUI样例.7z"中,包含了三个关键部分:day25_GUI、登录注册案例和模拟四则运算,这些都是GUI设计和实现的经典应用场景。 首先,"day25_GUI"可能是一个教学或项目开发中的第25天,专门讨论GUI设计的内容。...

    我的代码样例

    综上所述,这个压缩包“我的代码样例”提供了丰富的编程实践材料,覆盖了Java API的运用以及完整的图书管理系统开发,对于Java初学者和进阶者都有很大的学习价值。通过分析和学习这些代码,可以提升编程技巧,了解...

    javaFX2.0教程

    在学习JavaFX的过程中,不断尝试、运行样例和构建自己的项目对于掌握JavaFX是非常有帮助的。随着JavaFX 2.0的出现,开发者有了一个功能强大、跨平台的工具来创建高质量的桌面应用程序。通过本教程,你将能够学习到...

    java学习和项目中一些典型的应用场景样例代码.zip

    这个名为"java学习和项目中一些典型的应用场景样例代码.zip"的压缩包显然包含了一些Java编程的实际应用示例,旨在帮助学习者理解Java在实际项目中的运用。下面,我们将深入探讨Java的一些关键应用场景和相关知识点。...

    jfreechart样例

    学习和使用JFreeChart样例,你可以逐步理解JFreeChart库的工作原理,掌握创建各种复杂图表的方法,并在自己的项目中灵活运用。这对于任何需要在Java环境中处理数据可视化需求的开发者来说,都是一个非常宝贵的资源。

    JAVA作业目录及样例

    本资源“JAVA作业目录及样例”是针对学习Java编程的学生们提供的一份宝贵的参考资料,它包含了Java程序设计实验和半期考试的相关内容,帮助学生理解和实践Java的核心概念。 Java程序设计实验部分通常涉及基本语法、...

    Java-Learning:java学习样例代码

    【Java学习样例代码】是针对Java编程语言的学习资源,主要包含了各种Java编程示例,旨在帮助初学者或有经验的开发者深入理解Java语言的核心概念和技术。这些代码样例涵盖了从基础语法到高级特性的广泛内容,对于学习...

    e(fx)lipse

    6. **样例代码**:提供JavaFX示例代码,帮助开发者了解和学习JavaFX API的用法。 7. **语法高亮**:对JavaFX剧本语言(FXML)提供语法高亮和错误检查。 在安装了**e(fx)lipse** 的Eclipse中,用户可以通过“File” ...

    demo.rar_DEMO

    9. **Swing和JavaFX**:这两者是Java的GUI库,样例程序可能会创建窗口应用,展示按钮、文本框、菜单等组件的使用。 10. **反射和注解**:反射允许在运行时检查类的信息,注解提供元数据,样例程序会展示它们如何...

    基于智能家居,从客厅到卧室,从中控到sensor,开发者可以体验各种家居的开发样例,打造自己的家居体验,享受万物互联的快感。

    这里,我们主要关注的是基于Java的开发样例,如在"learn-java-master"这个项目中,开发者可以学习如何使用Java语言来实现智能家居系统的关键部分。 首先,让我们深入了解一下Java在智能家居中的应用。Java是一种...

    WebViewSample源码

    总结来说,`WebViewSample`源码是一个学习JavaFX如何集成Web内容的绝佳实例。通过对源码的深入理解和实践,开发者可以掌握如何在JavaFX应用程序中利用`WebView`组件展示丰富的Web内容,并实现与网页的交互。这不仅...

    21天精通java源代码

    7. **反射机制**:反射是Java的一大特色,它允许在运行时检查类、接口、字段和方法的信息,甚至动态调用方法。 8. **Java标准库**:熟悉Java的API,如IO、NIO、网络、XML解析、日期时间处理等。 9. **泛型**:泛型...

    JAVA简单实例

    3. **封装**: 封装是面向对象编程的三大特性之一,它隐藏了对象的内部实现细节,只对外提供公共接口。通过访问修饰符(如public、private、protected),可以控制类成员的可见性。 4. **继承与多态**: 继承允许一个...

    desktop-project:样例项目Kelompok

    为了深入理解这个项目,你需要查看源代码,学习其中的类结构、方法实现以及如何通过JavaFX或Swing等库创建图形用户界面。同时,了解如何在Java中实现文件I/O操作,处理系统事件,以及可能涉及的网络通信(如果有的话...

    Jfreechart学习资源

    JFreeChart是一个强大的开源库,专门用于生成高质量的2D图表,适用于各种Java应用程序,包括Swing、JavaFX、Applet以及Servlet。本文将深入探讨JFreeChart的基础知识、主要功能以及如何使用它来创建各种类型的图表。...

    Chris-Heavner-Portfolio-1:代码样例

    【Chris-Heavner-Portfolio-1:代码样例】是一个与Java编程相关的项目,它展示了开发者克里斯·海夫纳的编程技能和经验。在这个项目中,我们可以期待找到一系列使用Java语言编写的代码示例,可能包括不同领域的应用,...

    java编程实例(精心整理百个实例)

    7. **数据库操作**:Java通过JDBC(Java Database Connectivity)与各种数据库进行交互。实例会包含连接数据库、执行SQL查询、处理结果集等内容,帮助你理解如何在Java中进行数据库操作。 8. **图形用户界面(GUI)...

Global site tag (gtag.js) - Google Analytics