Answer the question
In order to leave comments, you need to log in
Reshaping from another thread?
I'm parsing someone else's code, and I can't figure out how it works.
public class ChatClient implements Notifier {
private Set<MessageObserver> observers = new HashSet<>();
public void start(String name, String password) {
Receiver receiver = new Receiver();
receiver.start();
}
private class Receiver extends Thread {
@Override
public void run() {
try {
notifyObservers(new Message(-1000,"aa", "vv", "ss"));
} catch (IOException e) {
e.printStackTrace();
}
}
public interface MessageObserver {
void newPrivateMessageReceived(Message msg);
void newBroadCastMessageReceived(Message msg);
void sendMessageFailed(Message msg);
void newLoginAnnouncement(Message msg);
void newLogoutAnnouncement(Message msg);
void loginSuccessMessage(Message msg);
void loginFailedMessage(Message msg);
void registerSuccessMessage(Message msg);
void registerFailMessage(Message msg);
}
public interface Notifier {
void addMessageObserver(MessageObserver o);
void removeMessageObserver(MessageObserver o);
void notifyObservers(Message m);
}
@Override
public void notifyObservers(Message m) {
if (m == null) {
throw new NullPointerException("Message is null !");
}
for (MessageObserver observer : observers) {
observer.loginFailedMessage(m);
}}
public class LoginController implements MessageObserver {
private ChatClient model;
@FXML
private Stage stage;
@FXML
public Hyperlink registerHyperlink;
@FXML
TextField usernameField;
@FXML
PasswordField passwordField;
@FXML
Text resultMessage;
@FXML
BorderPane loginBorderPane;
public void initialise(ChatClient model) {
this.model = model;
}
@FXML
public void handleLoginAction(ActionEvent actionEvent) {
stage = (Stage) ((Node) actionEvent.getSource()).getScene().getWindow();
String username = usernameField.getText();
String password = passwordField.getText();
//TODO validate username and pass
model.start(username, password);
}
@Override
public void registerFailMessage(Message msg) {
resultMessage.setText(msg.getMessageBody());
}
}
public class ChatApp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loginLoader = new FXMLLoader(getClass().getResource("../resources/layouts/login_window.fxml"));
Parent root = loginLoader.load();
LoginController loginController = loginLoader.getController();
//setUserAgentStylesheet(STYLESHEET_MODENA);
ChatClient model = new ChatClient();
loginController.initialise(model);
model.addMessageObserver(loginController);
Scene scene = new Scene(root, 400, 400);
primaryStage.setTitle("Login");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)
at com.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.scene.control.Labeled.setText(Labeled.java:145)
at com.coursework.controllers.LoginWindowController.loadMainWindows(LoginWindowController.java:40)
at com.coursework.logics.MainClient.d(MainClient.java:68)
at com.coursework.logics.MainClient$connectionToServer.run(MainClient.java:49)
Answer the question
In order to leave comments, you need to log in
JavaFX, like many other GUI libraries, is single-threaded. When a window is created , an Event Processing Thread is created , inside which the event loop and event handlers will work. You should not attempt to interact with GUI elements from the main thread or any other thread - this will crash. You should not start threads inside event handlers - this will lead to a crash. You should not stop the thread - it will crash. Therefore, it is necessary to use the mechanisms offered by the library for launching background tasks and interacting with them - Platform.runLater() , Service , Tasketc. Or you can come up with your own bicycles, such as used in the code from the question, but then it's better to read "Java Concurrency in Practice" by Brian Goetz first and understand the patterns .
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question