Javafx-用xml文件填充表
我对javafx相当陌生,一直在学习一个教程(),我的所有代码都来自该教程 我在用xml文件填充表格时遇到了一个问题,我认为这是因为我想先切换场景,然后在此新场景中显示表格。在指南中,他们只在加载的第一个场景中执行此操作,如果我执行此操作,我可以很好地工作,但是当我希望表格数据可以在不同的场景中查看时,它似乎不起作用。我所做的只是更改了一些代码在类中的位置,以尝试反映这一点,因为我不希望它出现在我的第一个场景中,但现在它不会显示 LibraryAppJavafx-用xml文件填充表,javafx,Javafx,我对javafx相当陌生,一直在学习一个教程(),我的所有代码都来自该教程 我在用xml文件填充表格时遇到了一个问题,我认为这是因为我想先切换场景,然后在此新场景中显示表格。在指南中,他们只在加载的第一个场景中执行此操作,如果我执行此操作,我可以很好地工作,但是当我希望表格数据可以在不同的场景中查看时,它似乎不起作用。我所做的只是更改了一些代码在类中的位置,以尝试反映这一点,因为我不希望它出现在我的第一个场景中,但现在它不会显示 LibraryApp package libraryapp; i
package libraryapp;
import java.io.File;
import java.io.IOException;
import java.util.prefs.Preferences;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import libraryapp.model.Book;
import libraryapp.model.BookListWrapper;
import libraryapp.view.HomeOverviewController;
import libraryapp.view.RootLayoutController;
public class LibraryApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
/**
* The data as an observable list of Books.
*/
private ObservableList<Book> bookData = FXCollections.observableArrayList();
/**
* Constructor
*/
public LibraryApp() {
// Add some sample data
bookData.add(new Book("Hans", "Muster"));
bookData.add(new Book("Ruth", "Mueller"));
bookData.add(new Book("Heinz", "Kurz"));
bookData.add(new Book("Cornelia", "Meier"));
bookData.add(new Book("Werner", "Meyer"));
bookData.add(new Book("Lydia", "Kunz"));
bookData.add(new Book("Anna", "Best"));
bookData.add(new Book("Stefan", "Meier"));
bookData.add(new Book("Martin", "Mueller"));
}
/**
* Returns the data as an observable list of Books.
* @return
*/
public ObservableList<Book> getBookData() {
return bookData;
}
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("LibraryApp");
initRootLayout();
showHomeOverview();
}
/**
* Initializes the root layout and tries to load the last opened
* person file.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(LibraryApp.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
// Give the controller access to the main app.
RootLayoutController controller = loader.getController();
controller.setLibraryApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
// Try to load last opened person file.
File file = getBookFilePath();
if (file != null) {
loadBookDataFromFile(file);
}
}
/**
* Shows the book overview inside the root layout.
*/
public void showHomeOverview() {
try {
// Load home overview.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(LibraryApp.class.getResource("view/HomeOverview.fxml"));
AnchorPane homeOverview = (AnchorPane) loader.load();
// Set home overview into the center of root layout.
rootLayout.setCenter(homeOverview);
// Give the controller access to the main app.
HomeOverviewController controller = loader.getController();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the main stage.
* @return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
/**
* Returns the book file preference, i.e. the file that was last opened.
* The preference is read from the OS specific registry. If no such
* preference can be found, null is returned.
*
* @return
*/
public File getBookFilePath() {
Preferences prefs = Preferences.userNodeForPackage(LibraryApp.class);
String filePath = prefs.get("filePath", null);
if (filePath != null) {
return new File(filePath);
} else {
return null;
}
}
/**
* Sets the file path of the currently loaded file. The path is persisted in
* the OS specific registry.
*
* @param file the file or null to remove the path
*/
public void setBookFilePath(File file) {
Preferences prefs = Preferences.userNodeForPackage(LibraryApp.class);
if (file != null) {
prefs.put("filePath", file.getPath());
// Update the stage title.
primaryStage.setTitle("LibraryApp - " + file.getName());
} else {
prefs.remove("filePath");
// Update the stage title.
primaryStage.setTitle("LibraryApp");
}
}
/**
* Loads book data from the specified file. The current book data will
* be replaced.
*
* @param file
*/
public void loadBookDataFromFile(File file) {
try {
JAXBContext context = JAXBContext
.newInstance(BookListWrapper.class);
Unmarshaller um = context.createUnmarshaller();
// Reading XML from the file and unmarshalling.
BookListWrapper wrapper = (BookListWrapper) um.unmarshal(file);
bookData.clear();
bookData.addAll(wrapper.getBooks());
// Save the file path to the registry.
setBookFilePath(file);
} catch (Exception e) { // catches ANY exception
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not load data");
alert.setContentText("Could not load data from file:\n" + file.getPath());
alert.showAndWait();
}
}
/**
* Saves the current book data to the specified file.
*
* @param file
*/
public void saveBookDataToFile(File file) {
try {
JAXBContext context = JAXBContext
.newInstance(BookListWrapper.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Wrapping our book data.
BookListWrapper wrapper = new BookListWrapper();
wrapper.setBooks(bookData);
// Marshalling and saving XML to the file.
m.marshal(wrapper, file);
// Save the file path to the registry.
setBookFilePath(file);
} catch (Exception e) { // catches ANY exception
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not save data");
alert.setContentText("Could not save data to file:\n" + file.getPath());
alert.showAndWait();
}
}
}
浏览器控制器
package libraryapp.view;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.layout.AnchorPane;
import libraryapp.view.BrowseController;
public class HomeOverviewController implements Initializable {
@FXML
private AnchorPane homePane;
@FXML
private void goToBrowse(ActionEvent event) throws IOException {
AnchorPane pane = FXMLLoader.load(getClass().getResource("Browse.fxml"));
homePane.getChildren().setAll(pane);
}
@FXML
private void goToManageAccount(ActionEvent event) throws IOException {
AnchorPane pane = FXMLLoader.load(getClass().getResource("ManageAccount.fxml"));
homePane.getChildren().setAll(pane);
}
@FXML
public void logout(ActionEvent event) throws IOException {
AnchorPane pane = FXMLLoader.load(getClass().getResource("Login.fxml"));
homePane.getChildren().setAll(pane);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
package libraryapp.view;
import java.io.File;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import libraryapp.LibraryApp;
import libraryapp.model.Book;
public class BrowseController {
@FXML
private TableView<Book> bookTable;
@FXML
private TableColumn<Book, String> titleColumn;
@FXML
private Label titleLabel;
@FXML
private Label authorLabel;
@FXML
private Label isbnLabel;
@FXML
private Label quantityLabel;
@FXML
private AnchorPane browsePane;
// Reference to the main application.
private LibraryApp libraryApp;
/**
* The constructor.
* The constructor is called before the initialize() method.
*/
public BrowseController() {
}
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
@FXML
private void initialize() {
// Initialize the book table
titleColumn.setCellValueFactory(
cellData -> cellData.getValue().titleProperty());
// Clear person details.
showBookDetails(null);
// Listen for selection changes and show the person details when changed.
bookTable.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> showBookDetails(newValue));
}
/**
* Is called by the main application to give a reference back to itself.
*
* @param libraryApp
*/
public void setLibraryApp(LibraryApp libraryApp) {
this.libraryApp = libraryApp;
// Add observable list data to the table
bookTable.setItems(libraryApp.getBookData());
}
private void showBookDetails(Book book) {
if (book != null) {
// Fill the labels with info from the book object.
titleLabel.setText(book.getTitle());
authorLabel.setText(book.getAuthor());
isbnLabel.setText(book.getIsbn());
quantityLabel.setText(Integer.toString(book.getQuantity()));
} else {
// Book is null, remove all the text.
titleLabel.setText("");
authorLabel.setText("");
isbnLabel.setText("");
quantityLabel.setText("");
}
}
/**
* Called when the user clicks on the borrow button.
*/
@FXML
private void handleDeleteBook() {
int selectedIndex = bookTable.getSelectionModel().getSelectedIndex();
if (selectedIndex >= 0) {
bookTable.getItems().remove(selectedIndex);
} else {
// Nothing selected.
Alert alert = new Alert(AlertType.WARNING);
alert.initOwner(libraryApp.getPrimaryStage());
alert.setTitle("No Selection");
alert.setHeaderText("No book Selected");
alert.setContentText("Please select a book.");
alert.showAndWait();
}
}
@FXML
public void logout(ActionEvent event) throws IOException {
File bookFile = libraryApp.getBookFilePath();
libraryApp.saveBookDataToFile(bookFile);
AnchorPane pane = FXMLLoader.load(getClass().getResource("Login.fxml"));
browsePane.getChildren().setAll(pane);
}
}
package libraryapp.view;
导入java.io.File;
导入java.io.IOException;
导入javafx.event.ActionEvent;
导入javafx.fxml.fxml;
导入javafx.fxml.fxmloader;
导入javafx.scene.control.Alert;
导入javafx.scene.control.Alert.AlertType;
导入javafx.scene.control.Label;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.layout.ancorpane;
导入libraryapp.libraryapp;
导入libraryapp.model.Book;
公共类浏览器控制器{
@FXML
私人书桌;
@FXML
私有表列标题列;
@FXML
私有标签标题标签;
@FXML
私有标签作者标签;
@FXML
自有品牌isbnLabel;
@FXML
专用标签quantityLabel;
@FXML
私人锚烷棕烷;
//对主应用程序的引用。
私人图书馆APP图书馆APP;
/**
*构造器。
*在initialize()方法之前调用构造函数。
*/
公共浏览器控制器(){
}
/**
*初始化控制器类。自动调用此方法
*加载fxml文件后。
*/
@FXML
私有void初始化(){
//初始化图书表
titleColumn.setCellValueFactory(
cellData->cellData.getValue().titleProperty());
//清楚个人信息。
showBookDetails(空);
//侦听选择更改并在更改时显示人员详细信息。
bookTable.getSelectionModel().SelectEditeProperty().addListener(
(可观察、旧值、新值)->showBookDetails(新值);
}
/**
*由主应用程序调用以返回对自身的引用。
*
*@param libraryApp
*/
公共无效设置LibraryApp(LibraryApp LibraryApp){
this.libraryApp=libraryApp;
//将可观察列表数据添加到表中
bookTable.setItems(libraryApp.getBookData());
}
私人作废展示册详细信息(书籍){
if(book!=null){
//用图书对象中的信息填充标签。
titleLabel.setText(book.getTitle());
authorLabel.setText(book.getAuthor());
isbnlab.setText(book.getIsbn());
quantityLabel.setText(Integer.toString(book.getQuantity());
}否则{
//书本为空,请删除所有文本。
标题标签setText(“”);
authorLabel.setText(“”);
isbnLabel.setText(“”);
quantityLabel.setText(“”);
}
}
/**
*当用户单击“借用”按钮时调用。
*/
@FXML
私有无效handleDeleteBook(){
int-selectedIndex=bookTable.getSelectionModel().getSelectedIndex();
如果(已选择索引>=0){
bookTable.getItems().remove(selectedIndex);
}否则{
//未选择任何内容。
警报=新警报(警报类型.警告);
alert.initOwner(libraryApp.getPrimaryStage());
alert.setTitle(“无选择”);
alert.setHeaderText(“未选择书本”);
alert.setContentText(“请选择一本书”);
alert.showAndWait();
}
}
@FXML
公共作废注销(ActionEvent事件)引发IOException{
File bookFile=libraryApp.getBookFilePath();
libraryApp.saveBookDataToFile(bookFile);
AnchorPane pane=FXMLLoader.load(getClass().getResource(“Login.fxml”);
browsePane.getChildren().setAll(窗格);
}
}
我想按下一个按钮,调用goToBrowse
,加载浏览场景,然后用xml文件中的数据填充该表。它会很好地浏览场景,但不会填充表格
请原谅任何混乱的代码和任何不好的命名约定,因为我对javafx这个东西非常陌生,一直在尝试遵循前面提到的教程,并将其调整到我认为正确的位置
我相信我想在
浏览器控制器中调用的是设置库应用程序
,但我尝试的似乎不起作用。我想我不太理解你的代码。在BrowseController
中,您的setLibraryApp
方法显示表中的数据,但我看不到您调用该方法的任何地方。另外,在您的showHomeOverview
方法中,您有一条注释“允许控制器访问主应用程序”,但实际上您并没有这样做。该注释下方的showHomeOverview末尾有一行代码,即controller.setLibraryApp(此);与教程中的内容类似,但由于我没有在该场景中显示数据,因此我将其从该场景中删除,并说明了为什么我尝试将其添加到该场景中,它表示不存在此类方法。我承认,我也曾困惑于试图遵循本教程,但对其进行了调整以满足我的需要,即在加载浏览场景时调用setLibaryApp方法,但无论我尝试什么,似乎都不起作用,因此,我肯定我不了解ITI的某些内容如果您希望HomeController
向BrowseController
提供LibraryApp
,HomeController
首先需要访问它。听起来你正在学习的教程已经向你展示了如何做到这一点:你只需要做(两次)同样的方法。我相信现在我已经给了HomeController
和BrowseController
访问LibraryApp
的权限,但我仍然不太确定在导航到浏览场景后如何让表中填充数据。我肯定我遗漏了一些明显的东西。bookTable.setItems(libraryApp.ge