所以我正在用JavaFX制作一个小程序来熟悉它。
我很确定对javafx的工作方式有一些基本的了解,但我似乎无法解决这个问题,因为我遇到了一些我无法找到解决方案的问题。尽管在谷歌上彻底研究过它们。
目前我有一个设置,我使用eclipse和scenebuilder 1.1(因为2.0给我带来了各种麻烦)。
我有一个非常简单的设置,主应用程序加载了初始的主应用程序窗口。
public class Main extends Application {
@Override
public void start(final Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/application/ApplicationWindow.fxml"));
Scene scene = new Scene(root);
stage.getIcons().add(new Image("/application/bug3.png"));
stage.setResizable(true);
stage.setTitle("Simple Bugtracker");
stage.setMinHeight(500);
stage.setMinWidth(800);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
似乎工作正常。然后我创建了一个控制器类,它包含正确的fx:id'et gui元素作为字段值,它工作正常,我可以用java代码操作它们。
到目前为止,我遇到了两个问题。
1)当我从其中一个列表视图中删除某些内容时,我已设法修复更新问题,因此通过添加if null方案立即将其从列表视图中删除。但是当我创建一个我的对象类型的新实例时,listview不会更新,直到我重新启动程序?
2)其次我在控制器类中遇到一个简单的int字段值时遇到问题,我想在im调用的方法中使用它的当前值(在scenebuilder中的一个按钮上设置),但似乎总是坚持认为虽然值设置正确,但它仍然是它在启动时实例化时的原始值。
这是我非常庞大的控制器类。
public class MyController implements Initializable {
// Logic related fields
public ProjectList<Project> projectList = new ProjectList<Project>();
public int currentProjectIndex = -1;
public Bug currentBug;
// Listview buffers
public ObservableList<Project> projectsListBuffer = FXCollections.observableArrayList();
public ObservableList<Bug> unsolvedListBuffer = FXCollections.observableArrayList();
public ObservableList<Bug> solvedListBuffer = FXCollections.observableArrayList();
// GUI related fields
@FXML public ListView<Project> projectsListView;
@FXML public ListView<Bug> unsolvedListView;
@FXML public ListView<Bug> solvedListView;
@FXML public TextArea topDisplayArea;
@FXML public Button btnCreateProject;
@FXML public TextField titleFieldCreateProject;
@FXML public TextArea descriptionAreaCreateProject;
@FXML public AnchorPane createProjectWindow;
@FXML public AnchorPane projectsListViewAnchor;
@FXML public Label projectTitleLabel;
@FXML public Button createBugButton;
@FXML public TextField titleFieldCreateBug;
@FXML public TextArea descriptionAreaCreateBug;
public Stage createProjectStage;
// public Stage createBugStage;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
// load data from file system
try {
loadData();
} catch (IOException e) {
e.printStackTrace();
}
// Instantiate gui field values
// projectsListView = new ListView();
// unsolvedListView = new ListView();
// solvedListView = new ListView();
//
//
// topDisplayArea = new TextArea();
// btnCreateProject = new Button();
//
// titleFieldCreateProject = new TextField();
// descriptionAreaCreateProject = new TextArea();
//
// createProjectWindow = new AnchorPane();
// projectsListViewAnchor = new AnchorPane();
//
// projectTitleLabel = new Label();
// createBugButton = new Button();
//
// titleFieldCreateBug = new TextField();
// descriptionAreaCreateBug = new TextArea();
updateListBuffers();
projectsListView.setPrefHeight( getScreenH() );
projectsListView.setItems(projectsListBuffer);
unsolvedListView.setPrefHeight( getScreenH() );
unsolvedListView.setItems(unsolvedListBuffer);
// settings on necessary gui items
topDisplayArea.setPrefHeight( getScreenH() );
topDisplayArea.setPrefWidth( getScreenW() );
topDisplayArea.setEditable(false);
topDisplayArea.setBackground(null); // something to be done here for transparent logo in background of all project descriptions etc.
// ved dobbeltklik i projektlisten, vælg project og sæt titel
projectsListView.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent click) {
if (click.getClickCount() == 2) {
//Use ListView's getSelected Item
currentProjectIndex = projectsListView.getSelectionModel().getSelectedIndex();
Project currentProject = projectList.get(projectsListView.getSelectionModel().getSelectedIndex());
projectTitleLabel.setText(currentProject.getTitle());
System.out.println( "Selected project:"+currentProject.getTitle());
solvedListView.setItems(unsolvedListBuffer);
for (Bug b : currentProject.solvedBugs) {
System.out.println(b.getTitle()+"\n"+b.getErrorDescription());
}
updateListBuffers();
}
}
});
// ved dobbeltklik i uløste bugs listen, sæt top display område
unsolvedListView.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent click) {
if (click.getClickCount() == 2) {
//Use ListView's getSelected Item
currentBug = unsolvedListView.getSelectionModel().getSelectedItem();
topDisplayArea.setText(currentBug.getErrorDescription());
}
}
});
solvedListView.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent click) {
if (click.getClickCount() == 2) {
//Use ListView's getSelected Item
currentBug = solvedListView.getSelectionModel().getSelectedItem();
topDisplayArea.setText(currentBug.getErrorDescription());
}
}
});
// custom listview cell for the projects listview
projectsListView.setCellFactory(new Callback<ListView<Project>, ListCell<Project>>() {
@Override
public ListCell<Project> call(ListView<Project> p) {
ListCell<Project> cell = new ListCell<Project>() {
@Override
protected void updateItem(Project t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
// program a custom cell with several items in it
Text text = new Text();
Text text2 = new Text();
text.wrappingWidthProperty().bind(p.widthProperty().subtract(15));
text.setText(t.getTitle());
text2.wrappingWidthProperty().bind(p.widthProperty().subtract(15));
text2.setText(t.getCreationDate().toLocaleString());
text.setFont(Font.font ("Verdana", 12));
text2.setFont(Font.font ("Verdana", 10));
text.setFill(Color.BLACK);
text2.setFill(Color.TEAL);
AnchorPane pane = new AnchorPane();
pane.setPrefHeight(90);
pane.setPrefWidth(300);
ImageView imageView = new ImageView();
imageView.setImage(new Image("/application/project1.png"));
imageView.setFitHeight(60);
imageView.setFitWidth(60);
Image imageOk = new Image(getClass().getResourceAsStream("/application/selectionicon.png"));
Button deleteButton = new Button("Delete");
deleteButton.setLayoutX(233);
deleteButton.setLayoutY(60);
text.setLayoutX(70);
text.setLayoutY(30);
text2.setLayoutX(70);
text2.setLayoutY(50);
pane.getChildren().addAll(imageView, text, text2, deleteButton);
// delete actionevent
deleteButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm deletion");
alert.setHeaderText("Are you sure you want to delete this project?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
int selIndex = projectsListView.getSelectionModel().getSelectedIndex();
if (selIndex>-1) {
projectsListBuffer.remove(selIndex);
projectList.remove(selIndex);
projectsListView.setItems(projectsListBuffer);
projectList.save();
}
} else {
System.out.println("DENIED!!");
}
}
});
setPrefWidth(0);
setGraphic(pane);
} else {
setText(null);
setGraphic(null);
}
}
};
return cell;
}
});
// custom listview cell for the unsolved bugs listview
unsolvedListView.setCellFactory(new Callback<ListView<Bug>, ListCell<Bug>>() {
@Override
public ListCell<Bug> call(ListView<Bug> p) {
ListCell<Bug> cell = new ListCell<Bug>() {
@Override
protected void updateItem(Bug t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
// program a custom cell with several items in it
Text text = new Text();
Text text2 = new Text();
text.wrappingWidthProperty().bind(p.widthProperty().subtract(15));
text.setText(t.getTitle());
text2.wrappingWidthProperty().bind(p.widthProperty().subtract(15));
text2.setText(t.getCreationDate().toLocaleString());
text.setFont(Font.font ("Verdana", 12));
text2.setFont(Font.font ("Verdana", 10));
text.setFill(Color.BLACK);
text2.setFill(Color.TEAL);
AnchorPane pane = new AnchorPane();
pane.setPrefHeight(90);
pane.setPrefWidth(300);
ImageView imageView = new ImageView();
imageView.setImage(new Image("/application/bug3.png"));
imageView.setFitHeight(60);
imageView.setFitWidth(60);
Image imageOk = new Image(getClass().getResourceAsStream("/application/selectionicon.png"));
Button selectButton = new Button("Select");
Button deleteButton = new Button("Delete");
selectButton.setLayoutX(233);
selectButton.setLayoutY(60);
deleteButton.setLayoutX(180);
deleteButton.setLayoutY(60);
text.setLayoutX(70);
text.setLayoutY(30);
text2.setLayoutX(70);
text2.setLayoutY(50);
pane.getChildren().addAll(imageView, text, text2);
deleteButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
projectsListBuffer.remove(projectsListView.getSelectionModel().getSelectedIndex());
projectList.remove(projectsListView.getSelectionModel().getSelectedIndex());
projectsListView.setItems(projectsListBuffer);
projectList.save();
}
});
setPrefWidth(0);
setGraphic(pane);
} else {
setText(null);
setGraphic(null);
}
}
};
return cell;
}
});
}
// loads and show the create project window from it's fxml file (CreateProjectWindow.fxml)
public void showCreateProjectWindow() {
try {
Parent root1 = FXMLLoader.load(getClass().getResource("/application/CreateProjectWindow.fxml"));
createProjectStage = new Stage();
Scene scene = new Scene(root1);
createProjectStage.setScene(scene);
createProjectStage.setMinWidth(374);
createProjectStage.setMinHeight(416);
createProjectStage.setResizable(false);
createProjectStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
// actionevent method that creates a new project MANGLER AT FIKSE DET SÅ LISTVIEWET OPDATERER SIG MED DET SAMME
public void createProject() {
String title = titleFieldCreateProject.getText();
String description = descriptionAreaCreateProject.getText();
Project project = new Project(title, description, new Date());
projectList.add(project);
projectsListBuffer.add(project);
projectList.save();
updateListBuffers();
projectsListView.setItems(projectsListBuffer);
}
// loads and show the create project window from it's fxml file (CreateProjectWindow.fxml)
public void showCreateBugWindow() {
try {
Parent root1 = FXMLLoader.load(getClass().getResource("/application/CreateBugWindow.fxml"));
createProjectStage = new Stage();
Scene scene = new Scene(root1);
createProjectStage.setScene(scene);
createProjectStage.setMinWidth(374);
createProjectStage.setMinHeight(416);
createProjectStage.setResizable(false);
createProjectStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
// actionevent method that creates a new bug MANGLER AT FIKSE DET SÅ LISTVIEWET OPDATERER SIG MED DET SAMME
public void createBug() {
if (currentProjectIndex >-1) {
String title = titleFieldCreateBug.getText();
String description = descriptionAreaCreateBug.getText();
System.out.println(title+"\n"+description);
Bug bug = new Bug(title, description, new Date());
projectList.get(currentProjectIndex).unsolvedBugs.add(bug);
unsolvedListBuffer.add(bug);
projectList.save();
updateListBuffers();
} else {
System.out.println("Failed creation.");
}
}
// load, clear and reload buffers
public void updateListBuffers() {
if (currentProjectIndex>-1) {
unsolvedListBuffer.clear();
for (int i=0; i<projectList.get(currentProjectIndex).unsolvedBugs.size(); i++) {
unsolvedListBuffer.add( projectList.get(currentProjectIndex).unsolvedBugs.get(i) );
}
solvedListBuffer.clear();
for (int i=0; i<projectList.get(currentProjectIndex).solvedBugs.size(); i++) {
solvedListBuffer.add( projectList.get(currentProjectIndex).solvedBugs.get(i) );
}
// unsolvedListView.setItems(null);
// solvedListView.setItems(null);
unsolvedListView.setItems(unsolvedListBuffer);
solvedListView.setItems(solvedListBuffer);
}
projectsListBuffer.clear();
for (int i=0; i<projectList.size(); i++) {
projectsListBuffer.add( projectList.get(i) );
}
// projectsListView.setItems(null);
projectsListView.setItems(projectsListBuffer);
}
// file system related methods
public void loadData() throws IOException {
File fil = new File("Project_Data.dat");
if ( !fil.exists() ) {
fil.createNewFile();
projectList = new ProjectList<Project>();
projectList.save();
} else {
projectList = ProjectList.load();
}
}
// practical methods
public double getScreenH() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
return screenSize.getHeight();
}
public double getScreenW() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
return screenSize.getWidth();
}
}
我遇到的问题是currentProjectIndex,它似乎正确地保存了它的值但是当单击按钮运行“createBug()”方法时,它表示它仍然是-1(就像它一样)被初始化了吗?
关于第一个问题,正如您所看到的,我正在调用一个窗口来创建一个新项目或错误,然后通过单击按钮运行createProject()或createBug()方法。但是当我运行某些方法时,它就像控制器中的字段值(selectedProjectIndex)没有保存?
简而言之,我可以成功创建项目,将它们保存到文件中。但是在重新启动程序之前列表视图不会更新。
其次我不能创建任何错误,因为selectedProjectIndex由于某种原因总是被视为-1?
编辑:使用新建议更新了控制器类。
当我尝试使用showCreateProjectWindow()或showCreateBugWindow()方法打开一个新窗口时的Stacktrace。
/C:/Users/Giuseppe/Dropbox/Java/BugTracker/bin/application/CreateProjectWindow.fxml
at javafx.fxml.FXMLLoader.constructLoadException(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.load(Unknown Source)
at application.MyController.showCreateProjectWindow(MyController.java:320)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.Trampoline.invoke(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.control.MenuItem.fire(Unknown Source)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(Unknown Source)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$341(Unknown Source)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$$Lambda$313/1964728071.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.Scene$MouseHandler.process(Unknown Source)
at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$282/1128114225.get(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
at com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
at com.sun.glass.ui.View.notifyMouse(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at application.MyController.updateListBuffers(MyController.java:399)
at application.MyController.initialize(MyController.java:114)
... 65 more
答案 0 :(得分:1)
您的问题几乎无法回答,因为您拥有的代码多于重现问题所需的代码,但您不包含关键元素(例如FXML文件)。最好从头开始创建一个小的,简单的,完整的示例来演示问题,而不是发布整个控制器类。
以下是一些可能适用于您所看到的问题的一般性事项。
以下是调用FXMLLoader
的{{1}}方法时发生的基本过程:
load(...)
加载FXML文件。FXMLLoader
属性,则为no
控制器先前已设置,加载程序将字符串转换为fx:controller
。如果在加载器上设置了Class
,则会将controllerFactory
传递给控制器工厂的Class
方法,从而检索构造函数。否则,通过指定的类'无参数构造函数实例化控制器。 (如果先前已设置控制器,则加载过程将终止,但会出现异常。)call(...)
属性的对象并且已创建控制器(通过任何方式)时,控制器中的fx:id
- 带注释的字段与{{1}同名如果存在,则将值初始化为该对象。@FXML
方法,则会调用fx:id
方法。从编码的角度来看,这是一些后果:
声明并初始化initialize()
- 带注释的字段,例如:
initialize()
总是多余的。如果@FXML
已正确设置,则@FXML
private Label myLabel = new Label();
将在加载过程中重新分配新值,并且将丢弃原始初始化值。更糟糕的是,如果未正确设置fx:id
,则使用myLabel
完成的任何内容都将应用于不属于场景图的标签,因此您将获得难以调试的意外结果(基本上,操作会成功但在UI中没有明显的效果)。如果您没有初始化该字段,那么如果fx:id
未正确设置,则会立即使用myLabel
失败,然后您可以轻松地进行调试。
同样,在fx:id
方法中重新初始化NullPointerException
- 带注释的字段始终是一场灾难:
@FXML
在这种情况下,initialize()
首先由FXML加载器初始化,但是当调用@FXML
private Label myLabel ;
public void initialize() {
myLabel = new Label(...);
// ...
}
方法时,它将被不属于场景图的不同标签替换。因此myLabel
上的操作将成功,但在UI中无效。
其次,在“标准”控制器设置中,您不在initialize()
上调用myLabel
或setController
,而是通过{{1}指定控制器类每个setControllerFactory
创建一个相应控制器类的实例。从堆栈跟踪中,FXMLLoader
和fx:controller
看起来都使用相同的控制器类。这总是一个坏主意:共享控制器类的每个实例只有FXMLLoader
- 当对应于特定FXML文件定义的FXML元素时,已注释的字段被初始化。显然他们不会意识到彼此的数据。您应该为每个FXML文件创建一个不同的控制器类。如果他们需要共享数据,请使用this question中列出的技术。通常,您可以通过在一个控制器中创建和公开可观察属性并从另一个控制器中观察它来管理它,如下例所示。
这是一个简单的例子,我猜你的例子有一些相同的结构。这可能有助于研究和理解这一点。这里的所有内容都在一个名为“application”的包中(包括FXML文件)。
数据模型类:Person.java
ApplicationWindow.fxml
主要fxml文件:PersonList.fxml:
CreateProjectWindow.fxml
主控制器:PersonListController.java:
@FXML
编辑器fxml:PersonEditor.fxml:
package application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
private final StringProperty firstName = new SimpleStringProperty();
private final StringProperty lastName = new SimpleStringProperty();
public Person(String firstName, String lastName) {
setFirstName(firstName);
setLastName(lastName);
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
@Override
public String toString() {
return getFirstName() +" "+getLastName();
}
}
编辑器控制器:PersonEditorController.java:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.PersonListController">
<center>
<ListView fx:id="personList" />
</center>
<bottom>
<HBox spacing="5">
<padding>
<Insets top="10" bottom="10" left="10" right="10" />
</padding>
<Button text="New..." onAction="#newPerson" />
<Button text="Edit..." onAction="#editPerson" fx:id="editButton" />
</HBox>
</bottom>
</BorderPane>
应用程序:Main.java:
package application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
public class PersonListController {
@FXML
private ListView<Person> personList ;
@FXML
private Button editButton ;
public void initialize() {
// list created so it fires updates if either the firstName or lastName change:
ObservableList<Person> people = FXCollections.observableArrayList(person ->
new Observable[] {person.firstNameProperty(), person.lastNameProperty()});
people.addAll(new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Johnson"));
personList.setItems(people);
editButton.disableProperty().bind(
Bindings.isNull(personList.getSelectionModel().selectedItemProperty()));
}
@FXML
private void newPerson() throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("PersonEditor.fxml"));
Parent root = loader.load();
PersonEditorController controller = loader.getController();
controller.personProperty().addListener((obs, oldPerson, newPerson) -> {
if (newPerson != null) {
personList.getItems().add(newPerson);
}
});
showEditorWindow(root);
}
@FXML
private void editPerson() throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("PersonEditor.fxml"));
Parent root = loader.load();
PersonEditorController controller = loader.getController();
controller.setPerson(personList.getSelectionModel().getSelectedItem());
showEditorWindow(root);
}
private void showEditorWindow(Parent root) {
Scene scene = new Scene(root, 350, 200);
Stage stage = new Stage();
stage.initOwner(personList.getScene().getWindow());
stage.setScene(scene);
stage.show();
}
}