如何使用 JavaFX 将对象从一个控制器传递到另一个控制器
How to pass an object from one controller to another with JavaFX
我目前正在尝试构建具有登录和注销功能的客户端-服务器应用程序。在 LoginViewController 中,我正在创建一个客户端对象。我希望能够在 ClientViewController 中使用这个对象,例如用于注销。如何将此对象从 LoginViewController 传递到 ClientViewController?由于登录成功我不想实例化一个新对象,我想使用通过登录并且当前在服务器端处于活动状态的对象。
如何实现?
Main.java
public class Main extends Application {
private static Stage primaryStage;
private static BorderPane mainLayout;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
showLoginView();
}
public static void showLoginView() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("LoginView.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout, 540, 400);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
public static void showClientView() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("ClientView.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout, 900, 600);
primaryStage.setScene(scene);
primaryStage.setResizable(true);
primaryStage.show();
}
}
LoginViewController.java
public class LoginViewController implements Initializable {
@FXML
private Main main;
@FXML
private TextField username;
@FXML
private PasswordField password;
@FXML
private Button login;
@FXML
private Button register;
private Client client;
private Login userLogin;
private String loginStatus;
@FXML
private Label loginInfo;
@Override
public void initialize(URL location, ResourceBundle resources) {
loginInfo.setVisible(false);
}
@FXML
public void login() throws IOException {
loginStatus = "timeout";
loginInfo.setVisible(false);
client = new Client("127.0.0.1", 3250, this); // Client object created
userLogin = new Login(username.getText(), password.getText());
client.setOnConnected(() -> client.sendToServer(userLogin));
client.start();
int waitForLoginStatusCounter = 0;
while(loginStatus.equals("timeout")) {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
waitForLoginStatusCounter++;
if(waitForLoginStatusCounter >= 20) {
break;
}
}
if(loginStatus.equals("success")) {
main.showClientView();
}
else if(loginStatus.equals("failed")) {
loginInfo.setVisible(true);
loginInfo.setText("Login failed: Wrong username or password");
}
else {
loginInfo.setVisible(true);
loginInfo.setText("Timeout: Check connection");
}
}
public String getLoginStatus() {
return loginStatus;
}
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
}
ClientViewController.java
public class ClientViewController implements Initializable {
@FXML
private Main main;
@FXML
private TreeView<String> treeview;
@FXML
private Button logout;
private Client client;
private String username;
private Logout userLogout;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
@FXML
public void logout() throws IOException {
userLogout = new Logout(username);
client.sendToServer(userLogout); // Null at this point
main.showLoginView();
}
}
Client.java(从服务器发送和接收对象)
public class Client extends Thread {
private String ip;
private int port;
private Socket socket;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private Runnable onConnected;
private LoginViewController lvc;
private RegisterViewController rvc;
public void setOnConnected(Runnable onConnected) {
this.onConnected = onConnected;
}
public Client(String ip, int port, LoginViewController lvc) {
this.ip = ip;
this.port = port;
this.lvc = lvc;
}
public Client(String ip, int port, RegisterViewController rvc) {
this.ip = ip;
this.port = port;
this.rvc = rvc;
}
public void run() {
try {
socket = new Socket(ip, port);
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
if(onConnected != null) {
onConnected.run();
}
while (true) {
try {
Object obj = ois.readObject();
if (obj instanceof Login) {
String loginStatus = ((Login) obj).getLoginStatus();
lvc.setLoginStatus(loginStatus);
}
else if(obj instanceof Register) {
String registerStatus = ((Register) obj).getRegisterStatus();
rvc.setRegisterStatus(registerStatus);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendToServer(Object obj) {
try {
oos.writeObject(obj);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行以下代码后问题解决:
LoginViewController.java
if(loginStatus.equals("success")) {
main.showClientView(client); // Passing the client-object to showClientView method
}
Main.java
public static void showClientView(Client client) throws IOException { // Taking the client-object as an argument from LoginViewController
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("ClientView.fxml"));
mainLayout = loader.load();
ClientViewController cvc = loader.getController(); // This did the "trick"
cvc.setClient(client); // Passing the client-object to the ClientViewController
Scene scene = new Scene(mainLayout, 900, 600);
primaryStage.setScene(scene);
primaryStage.setResizable(true);
primaryStage.show();
}
ClientViewController.java
public void setClient(Client client) { // Setting the client-object in ClientViewController
this.client = client;
}
我目前正在尝试构建具有登录和注销功能的客户端-服务器应用程序。在 LoginViewController 中,我正在创建一个客户端对象。我希望能够在 ClientViewController 中使用这个对象,例如用于注销。如何将此对象从 LoginViewController 传递到 ClientViewController?由于登录成功我不想实例化一个新对象,我想使用通过登录并且当前在服务器端处于活动状态的对象。
如何实现?
Main.java
public class Main extends Application {
private static Stage primaryStage;
private static BorderPane mainLayout;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
showLoginView();
}
public static void showLoginView() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("LoginView.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout, 540, 400);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
public static void showClientView() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("ClientView.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout, 900, 600);
primaryStage.setScene(scene);
primaryStage.setResizable(true);
primaryStage.show();
}
}
LoginViewController.java
public class LoginViewController implements Initializable {
@FXML
private Main main;
@FXML
private TextField username;
@FXML
private PasswordField password;
@FXML
private Button login;
@FXML
private Button register;
private Client client;
private Login userLogin;
private String loginStatus;
@FXML
private Label loginInfo;
@Override
public void initialize(URL location, ResourceBundle resources) {
loginInfo.setVisible(false);
}
@FXML
public void login() throws IOException {
loginStatus = "timeout";
loginInfo.setVisible(false);
client = new Client("127.0.0.1", 3250, this); // Client object created
userLogin = new Login(username.getText(), password.getText());
client.setOnConnected(() -> client.sendToServer(userLogin));
client.start();
int waitForLoginStatusCounter = 0;
while(loginStatus.equals("timeout")) {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
waitForLoginStatusCounter++;
if(waitForLoginStatusCounter >= 20) {
break;
}
}
if(loginStatus.equals("success")) {
main.showClientView();
}
else if(loginStatus.equals("failed")) {
loginInfo.setVisible(true);
loginInfo.setText("Login failed: Wrong username or password");
}
else {
loginInfo.setVisible(true);
loginInfo.setText("Timeout: Check connection");
}
}
public String getLoginStatus() {
return loginStatus;
}
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
}
ClientViewController.java
public class ClientViewController implements Initializable {
@FXML
private Main main;
@FXML
private TreeView<String> treeview;
@FXML
private Button logout;
private Client client;
private String username;
private Logout userLogout;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
@FXML
public void logout() throws IOException {
userLogout = new Logout(username);
client.sendToServer(userLogout); // Null at this point
main.showLoginView();
}
}
Client.java(从服务器发送和接收对象)
public class Client extends Thread {
private String ip;
private int port;
private Socket socket;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private Runnable onConnected;
private LoginViewController lvc;
private RegisterViewController rvc;
public void setOnConnected(Runnable onConnected) {
this.onConnected = onConnected;
}
public Client(String ip, int port, LoginViewController lvc) {
this.ip = ip;
this.port = port;
this.lvc = lvc;
}
public Client(String ip, int port, RegisterViewController rvc) {
this.ip = ip;
this.port = port;
this.rvc = rvc;
}
public void run() {
try {
socket = new Socket(ip, port);
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
if(onConnected != null) {
onConnected.run();
}
while (true) {
try {
Object obj = ois.readObject();
if (obj instanceof Login) {
String loginStatus = ((Login) obj).getLoginStatus();
lvc.setLoginStatus(loginStatus);
}
else if(obj instanceof Register) {
String registerStatus = ((Register) obj).getRegisterStatus();
rvc.setRegisterStatus(registerStatus);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendToServer(Object obj) {
try {
oos.writeObject(obj);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行以下代码后问题解决:
LoginViewController.java
if(loginStatus.equals("success")) {
main.showClientView(client); // Passing the client-object to showClientView method
}
Main.java
public static void showClientView(Client client) throws IOException { // Taking the client-object as an argument from LoginViewController
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("ClientView.fxml"));
mainLayout = loader.load();
ClientViewController cvc = loader.getController(); // This did the "trick"
cvc.setClient(client); // Passing the client-object to the ClientViewController
Scene scene = new Scene(mainLayout, 900, 600);
primaryStage.setScene(scene);
primaryStage.setResizable(true);
primaryStage.show();
}
ClientViewController.java
public void setClient(Client client) { // Setting the client-object in ClientViewController
this.client = client;
}