Reputation: 1286
**I'm unable to create a constructor from "GUIController".. The program runs if i delete this line "GUIController(){myModel = new TheModel(this)" but i still need it in other part. Please help!
**
package theclient;
import java.rmi.RemoteException;
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.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class GUIController extends Application {
TheModel myModel;
GUIController(){
myModel = new TheModel(this);
}
//public void init(){}
public TextArea myTextArea;
public TextField myTextField;
// Button and text field actions
public void myButtonAction() {
sendMsg();
}
public void myTextFieldAction() {
sendMsg();
}
// Append coming message
public void displayMsg(String comingMSG) {
System.out.println("Receive 01");
myTextArea.appendText(comingMSG);
}
public void sendMsg() {
try {
System.out.println("Send 01");
myModel.myChatServer.tellOthers(myTextField.getText());
} catch (RemoteException ex) {
Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("GUI.fxml"));
Scene scene = new Scene(root, 600, 400);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
public static void main(String[] args) throws Exception {
new GUIController();
launch(args);
}
}
The Second class. I'd be thankful if you can suggest any edits to the code. Thanks in advance for your efforts.
package theclient;
import common.ChatServerInt;
import common.ClientInt;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TheModel implements ClientInt {
public GUIController myCtrl;
ChatServerInt myChatServer;
TheModel(GUIController myCtrl) {
this.myCtrl = myCtrl;
}
public ChatServerInt connection() {
if (myChatServer == null) {
try {
Registry reg = LocateRegistry.getRegistry(1111);
myChatServer = (ChatServerInt) reg.lookup("ChatService");
myChatServer.register(this);
myChatServer.tellOthers("I'm here!");
} catch (RemoteException | NotBoundException ex) {
Logger.getLogger(TheModel.class.getName()).log(Level.SEVERE, null, ex);
}
} return myChatServer;
}
@Override
public void receive(String msg) throws RemoteException {
myCtrl.displayMsg(msg);
}
}
Upvotes: 0
Views: 71
Reputation: 89
Following the Model-view-controller design pattern, the model shouldn't be holding a reference to its controller. If the controller needs to respond to changes in the model's data, then this can be done with properties and listeners. The model holds a property (here, a StringProperty) and the controller listens for changes to the property.
For your code, this means storing the msg
in a StringProperty
. The controller, after constructing the model, attaches a ChangeListener
that calls displayMsg
when the model receives a message.
Using a property and listener, TheModel
no longer stores a reference to GUIController
and does not take a GUIController
as a parameter in its constructor.
GUIController
would look something like this:
public class GUIController extends Application {
...
TheModel myModel;
...
GUIController(){
myModel = new TheModel();
// Listen for changes in the msg StringProperty and call displayMessage when it changes
myModel.getMsgProperty().addListener(msg -> this.displayMsg(msg));
}
...
Note that the constructor for GUIController
no longer needs to pass this
to the constructor TheModel
. (In general, avoid passing this
outside of the constructor. An object is not fully constructed until the constructor returns.)
TheModel
would look something like this:
public class TheModel implements ClientInt {
...
private StringProperty msgProperty;
...
// remember to add a getter and setter for msgProperty!
...
@Override
public void receive(String msg) throws RemoteException {
// When a message is received, listeners attached to msgProperty will execute when setValue is called
msgProperty.setValue(msg);
}
Upvotes: 2