gpt4 book ai didi

JavaFX:一次有 2 个独立的窗口

转载 作者:行者123 更新时间:2023-11-29 08:23:14 25 4
gpt4 key购买 nike

我想同时创建 2 个独立的窗口。一个窗口将能够容纳一个可观察的列表,另一个窗口将显示所选列表对象的属性。我正在尝试将 ListView 创建为通用列表,并将其与对象特定窗口(例如,客户属性、啤酒属性、商店属性)结合起来。

简而言之:如果用户单击“客户”,它会显示包含所有客户的 ListView ,并且第一个客户的属性会显示在单独的、特定于客户的窗口中。

如果用户单击“Stores”,它会显示相同的 ListView ,但会填满商店。特定于商店的窗口也会打开,其中包含第一个商店的属性。

我尝试使用 2 个 FXMLLoader,但出于某种原因我不知道如何使用它们。我在 JavaFX 方面表现平平,所以我什至不知道从哪里开始。这就是我得到的,但它似乎是错误的。

 FXMLLoader loader = new FXMLLoader(getClass().getResource("List.fxml"));
loader.setRoot(this);
loader.setController(this);
FXMLLoader loader2 = new FXMLLoader(getClass().getResource("StoreWindow.fxml"));
loader2.setRoot(this);
loader2.setController(this);
try {
loader.load();
loader2.load();
} catch (IOException ex) {
throw new RuntimeException(ex);
}

最佳答案

您基本上必须遵循@Slaw 的说明。创建一个模型。在两个 Controllers 之间共享 Model。观察模型的当前 Customer 并做出相应的 react 。 MCVE 下面:

Main Class: (load both stages with the correct Scene. Create model and pass it to both Controllers):

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
*
* @author sedri
*/
public class JavaFXApplication36 extends Application {

@Override
public void start(Stage stage) {
try {
FXMLLoader listViewFXMLLoader = new FXMLLoader(getClass().getResource("ListViewFXML.fxml"));
Parent listViewRoot = listViewFXMLLoader.load();
ListViewController listViewController = listViewFXMLLoader.getController();
Scene scene1 = new Scene(listViewRoot);
stage.setScene(scene1);

FXMLLoader detailsFXMLLoader = new FXMLLoader(getClass().getResource("DetailsFXML.fxml"));
Parent detailsRoot = detailsFXMLLoader.load();
DetailsController detailsController = detailsFXMLLoader.getController();
Scene scene2 = new Scene(detailsRoot);
Stage stage2 = new Stage();
stage2.setScene(scene2);

DataModel model = new DataModel();
listViewController.initModel(model);
detailsController.initModel(model);

stage.show();
stage2.show();
} catch (IOException ex) {
Logger.getLogger(JavaFXApplication36.class.getName()).log(Level.SEVERE, null, ex);
}
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}

}

Model Class: (Keep up with current Customer and ObservableList of Customer)

import javafx.beans.Observable;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

/**
*
* @author sedrick
*/
public class DataModel {
private final ObservableList<Customer> customerList = FXCollections.observableArrayList(customer -> new Observable[]{customer.nameProperty(), customer.ageProperty()});
private final ObjectProperty<Customer> currentCustomer = new SimpleObjectProperty();

public ObjectProperty<Customer> currentCustomerProperty() {
return currentCustomer;
}

public void setCurrentCustomer(Customer currentCustomer) {
this.currentCustomer.set(currentCustomer);
}

public Customer getCurrentCustomer() {
return this.currentCustomer.get();
}


public ObservableList<Customer> loadCustomers()
{
customerList.add(new Customer("John Doe", 21));
customerList.add(new Customer("Jane Joe", 20));

return customerList;
}
}

Customer Class:

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
*
* @author sedrick
*/
public class Customer {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty age = new SimpleIntegerProperty();
public Customer(String name, int age) {
this.name.set(name);
this.age.set(age);
}

public String getName()
{
return this.name.get();
}

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

public StringProperty nameProperty()
{
return this.name;
}

public int getAge()
{
return this.age.get();
}

public void setAge(int age)
{
this.age.set(age);
}

public IntegerProperty ageProperty()
{
return this.age;
}
}

ListView Controller: (Initialize model, setup ListView and observe current customer property)

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;

/**
*
* @author sedri
*/
public class ListViewController implements Initializable {
@FXML private ListView<Customer> listView;

private DataModel model;



@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}

public void initModel(DataModel model)
{
// ensure model is only set once:
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}

listView.getSelectionModel().selectedItemProperty().addListener((obs, oldCustomer, newCustomer) ->
model.setCurrentCustomer(newCustomer));

model.currentCustomerProperty().addListener((obs, oldCustomer, newCustomer) -> {
if (newCustomer == null) {
listView.getSelectionModel().clearSelection();
} else {
listView.getSelectionModel().select(newCustomer);
}
});

listView.setCellFactory(lv -> new ListCell<Customer>() {
@Override
public void updateItem(Customer customer, boolean empty) {
super.updateItem(customer, empty);
if (empty) {
setText(null);
} else {
setText("Name: " + customer.getName() + " Age: " + customer.getAge());
}
}
});

listView.setItems(model.loadCustomers());
}
}

ListView FXML:

<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication36.ListViewController">
<children>
<ListView fx:id="listView" prefHeight="200.0" prefWidth="200.0" />
</children>
</StackPane>

DetailsController:(Initialize model and observe current customer property)

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;

/**
* FXML Controller class
*
* @author sedri
*/
public class DetailsController implements Initializable {
@FXML TextField tfName, tfAge;

private DataModel model;
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}

public void initModel(DataModel model) {
// ensure model is only set once:
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}

this.model = model ;

model.currentCustomerProperty().addListener((observable, oldCustomer, newCustomer) -> {
if(newCustomer == null){
tfName.setText("");
tfAge.setText("");
}
else{
tfName.setText(newCustomer.getName());
tfAge.setText(Integer.toString(newCustomer.getAge()));
}
});
}
}

Details FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>


<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication36.DetailsController">
<children>
<Label text="Name" />
<TextField fx:id="tfName" />
<Label text="Age" />
<TextField fx:id="tfAge" />
</children>
<padding>
<Insets left="20.0" right="20.0" />
</padding>
</VBox>

More info:

@James D answer on Model-View-Controller(MVC) .
GitHub code .

关于JavaFX:一次有 2 个独立的窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55668795/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com