FXML Exception in JavaFx | TableView - Table is Null | Eclispe IDE - javafx

I have been working on it for the past 3-4 days. I have googled it and also saw similar questions' answers but it did not help me.
Exception at Changing Scence:javafx.fxml.LoadException:
address-to-//application/Dashboard.fxml
This is the Exception I am getting when I log into the dashboard from the login page. Usually, I am not getting this exception but when I am trying to display the data in tableView from the xampp server then this exception occurs otherwise it is working fine.
here is the code of Main.java
public class Main extends Application {
private static Stage stg;
#Override
public void start(Stage primaryStage) {
stg = primaryStage;
try {
primaryStage.setResizable(false);
Parent root = FXMLLoader.load(getClass().getResource("/application/Login.fxml"));
primaryStage.setTitle("My Application Title");
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root , 1200,670));
primaryStage.show();
}catch(Exception e) {
System.out.println("Exception Occured: " +e);
}
}
//to change the scene
public void changeScene(String fxml) {
//passing XML file via a string parameter
try {
Parent pane = FXMLLoader.load(getClass().getResource(fxml));
stg.getScene().setRoot(pane);
}catch(Exception e) {
System.out.println("Exception at Changing Scence:" +e);
}
}
public static void main(String[] args) {
launch(args);
}
}
and this is the code on the login button
/*TO CHECK THE LOGIN
* CREDENTIALS STARTS*/
#FXML
public void loginUser(ActionEvent event) {
uname = username.getText().toString();
upass = password.getText().toString();
try {
DbConnectivity db = new DbConnectivity();
pst = db.connect.prepareStatement("SELECT * FROM adminlogin WHERE admin=? AND password=?");
pst.setString(1, uname);
pst.setString(2, upass);
rst = pst.executeQuery();
if(uname.isEmpty() && upass.isEmpty()) {
wronginput.setText("Please Enter Credentials!");
} else if(rst.next()) {
wronginput.setText("Log In Success!");
Main main = new Main();
main.changeScene("/application/Dashboard.fxml");
} else {
wronginput.setText("Wrong Username or Password");
username.setText("");
password.setText("");
username.requestFocus();
}
} catch (SQLException e) {
System.out.println("Prepared Exception: "+e);
}
}
/*TO CHECK LOGIN
* CREDENTIALS ENDS*/
And these are StackTrace
javafx.fxml.LoadException:
address-to-/application/Dashboard.fxml
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2714)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2692)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2555)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3368)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3324)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3292)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3264)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3240)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3233)
at application.Main.changeScene(Main.java:39)
at application.LoginControl.loginUser(LoginControl.java:59)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javafx.base#19.0.2.1/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml#19.0.2.1/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1852)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base#19.0.2.1/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics#19.0.2.1/javafx.scene.Node.fireEvent(Node.java:8923)
at javafx.controls#19.0.2.1/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls#19.0.2.1/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:207)
at javafx.controls#19.0.2.1/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base#19.0.2.1/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base#19.0.2.1/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base#19.0.2.1/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics#19.0.2.1/javafx.scene.Scene$MouseHandler.process(Scene.java:3894)
at javafx.graphics#19.0.2.1/javafx.scene.Scene.processMouseEvent(Scene.java:1887)
at javafx.graphics#19.0.2.1/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics#19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.View.notifyMouse(View.java:937)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics#19.0.2.1/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TableView.setItems(javafx.collections.ObservableList)" because "this.studentTable" is null
at application.DashboardController.RefreshStudentRecord(DashboardController.java:343)
at application.DashboardController.loadData(DashboardController.java:289)
at application.DashboardController.initialize(DashboardController.java:281)
at javafx.fxml#19.0.2.1/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2662)
... 66 more
For more clarifications
I have DashboardController.java that is implementing Initializable class.
Inside the controller class I have method to implement called initialize.
here is this method
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
loadData();
}
In this method I am using loadData() method that is
private void loadData() {
DbConnectivity db = new DbConnectivity();
conn = db.getConnection();
RefreshStudentRecord();
stsno.setCellValueFactory(new PropertyValueFactory<>("stsno"));
stsname.setCellValueFactory(new PropertyValueFactory<>("stsname"));
stsfname.setCellValueFactory(new PropertyValueFactory<>("stsfname"));
stsid.setCellValueFactory(new PropertyValueFactory<>("stsid"));
stscnic.setCellValueFactory(new PropertyValueFactory<>("stscnic"));
stsphone.setCellValueFactory(new PropertyValueFactory<>("stsphone"));
stsaddress.setCellValueFactory(new PropertyValueFactory<>("stsaddress"));
stsclass.setCellValueFactory(new PropertyValueFactory<>("stsclass"));
}
Inside the loadData() method I am calling another method that is
#FXML
public void RefreshStudentRecord() {
studentDataList.clear();
studentquery = "SELECT * FROM studentdata";
try {
studentPst = conn.prepareStatement(studentquery);
studentRst = studentPst.executeQuery();
while(studentRst.next()) {
studentDataList.add(new StudentsDataController(
studentRst.getInt("S_NO"),
studentRst.getString("studentname"),
studentRst.getString("fathername"),
studentRst.getString("studentid"),
studentRst.getString("studentcnic"),
studentRst.getString("phone"),
studentRst.getString("address"),
studentRst.getString("class")
)
);
studentTable.setItems(studentDataList);
}
} catch (SQLException e) {
System.out.println("Exception at Refresing student data: "+e);
e.printStackTrace();
}
}
I think the problem is somewhere thereby, seeing the StackTrace as it is pointing out that the table is null that's why all of the problems have occurred, but I have no clue why the table is null.
Kindly help me to solve this problem

Before setting the table ArrayList, do a check to check if the ArrayList has some data. Also, move your studentTable.setItems outside the loop such that it looks as follows:
while(studentRst.next()) {
studentDataList.add(new StudentsDataController(
studentRst.getInt("S_NO"),
studentRst.getString("studentname"),
studentRst.getString("fathername"),
studentRst.getString("studentid"),
studentRst.getString("studentcnic"),
studentRst.getString("phone"),
studentRst.getString("address"),
studentRst.getString("class")
)
);
}
if(studentDataList.size()>0){
studentTable.setItems(studentDataList);
}

Thanks to all for taking interest in my Question.
Here is how I solved it.
I created a separate class to handle the stuff for the tableView and made this class the controller of the fxml of tableView.
Then everything went right :)

Related

How do i update a textfield in javafx in loop ?

I have a small javafx application using scene builder which on a button click should read a string from COM port at regular intervals and update in a text field.
But now it only shows the last string if I use a for loop, and nothing if i put the code in infinite loop (That's my temporary requirement).
Can anyone help me so that at each read from COM port the new string is updated in the text field.
Here is the code I used for both the cases :
Note : In both cases in controller class, I'm getting perfect output on console.
public class Main extends Application
{
#Override
public void start(Stage primaryStage)
{
try
{
Parent root = FXMLLoader.load(getClass().getResource("test.fxml"));
Scene scene = new Scene(root);
//scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("test");
primaryStage.setScene(scene);
primaryStage.show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
launch(args);
}
}
Here is the Controller class :
// In this case it shows only the last string in the text field.
public class Controller implements Initializable
{
#FXML
private Button sayHelloButton;
#FXML
private TextField helloField;
#Override
public void initialize(URL arg0, ResourceBundle arg1)
{
}
#FXML
public void printHello(ActionEvent event)
{
if(event.getSource() == sayHelloButton)
{
SerialPort serialPort = new SerialPort("COM22");
for(int i=0;i<5;i++)
{
try
{
if(!serialPort.isOpened())
{
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
}
String str = serialPort.readString(10,3000);
System.out.println(str);
helloField.clear();
helloField.setText(str);
}
catch(Exception e)
{
helloField.setText(e.toString());
}
}
}
}
}
Here is the method with infinite loop :
//this shows nothing in the text field
#FXML
public void printHello(ActionEvent event)
{
if(event.getSource() == sayHelloButton)
{
SerialPort serialPort = new SerialPort("COM22");
while(true)
{
try
{
if(!serialPort.isOpened())
{
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
}
String str = serialPort.readString(10,3000);
System.out.println(str);
helloField.clear();
helloField.setText(str);
}
catch(Exception e)
{
helloField.setText(e.toString());
}
}
}
}
There are a couple things happening here. In your first example, you state that the console output is correct but the TextField only shows the last result.
This is expected if the loop executes quickly. The TextField is being updated, but it happens so quickly that you can't see it until the loop ends and the last result is still being displayed. Even if you have a delay built into the loop, this could still block the UI from being updated until the loop is completed.
With your infinite loop, the issue is that the loop is being run on the JavaFX Application Thread (JFXAT). This blocks any updates to the GUI until the loop is finished, which is never is.
You will need to move the infinite loop to a new background thread. From there, you can update the GUI using the Platform.runLater() method.
SerialPort serialPort = new SerialPort("COM22");
new Thread(() -> {
while(true)
{
try
{
if(!serialPort.isOpened())
{
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
}
String str = serialPort.readString(10,3000);
System.out.println(str);
// Update the UI on the JavaFX Application Thread
Platform.runLater(() -> {
helloField.clear();
helloField.setText(str);
});
}
catch(Exception e)
{
Platform.runLater(() -> helloField.setText(e.toString()));
}
}
}).start();
This allows your UI to continually update as the background thread sends it new information.

why server GUI freezing after i clicking on startButton for connecting to server (JavaFX)?

Its a traficklight programm. the GUI is a server. on GUI i used a button to start the server but my gui is freezing because it waiting for clients. The cliens are just recivers. i know that i should use threads but i dont know how. the problem is freezing of GUI.please help me
public class Controller {
public TextArea meldingPlass;
private static int portNr = 5555;
public void startServer() throws IOException {
Server cs = new Server();
cs.connectToServer(portNr);
}
}
//Here my SeverThreads class
public class ServerThread extends Thread {
Socket s;
InetAddress ca;
public ServerThread(Socket s)
{
this.s=s;
ca=s.getInetAddress();
}
public void run()
{
try(
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
//BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
)
{
while (true){
System.out.println(ca.getHostAddress());
out.println("Status of Server");
}
// s.close();
}
catch(Exception e){
System.out.println(e);
}
}
}
//here is ServerClass
public class Server implements Runnable {
public void connectToServer(int portNr){
try(
ServerSocket ss = new ServerSocket(portNr);
)
{
while (true)
{
System.out.println("In Server - while loop");
ServerThread st = new ServerThread(ss.accept());
System.out.println("Client connected. Starting client");
st.start();
}
}
catch (Exception e){
System.out.println("Exception occurred when trying to listen on port "
+portNr+ " or listening for a connection");
System.out.println(e.getMessage());
}
}
#Override
public void run() {
}
}
You don't show all the required code. Most probably you're running your server on the JavaFX thread.
Anyway, here's an excellent resource about how to create a web server.

Handle multiple JavaFX application launches within a loop

My code currently reads my Gmail inbox via IMAP (imaps) and javamail, and once it finds an email with zip/xap attachment, it displays a stage (window) asking whether to download the file, yes or no.
I want the stage to close once I make a selection, and then return to the place within the loop from which the call came. My problem arises because you cannot launch an application more than once, so I read here that I should write Platform.setImplicitExit(false); in the start method, and then use primartyStage.hide() (?) and then something like Platform.runLater(() -> primaryStage.show()); when I need to display the stage again later.
The problem occuring now is that the flow of command begins in Mail.java's doit() method which loops through my inbox, and launch(args) occurs within a for loop within the method. This means launch(args) then calls start to set the scene, and show the stage. Since there is a Controller.java and fxml associated, the Controller class has an event handler for the stage's buttons which "intercept" the flow once start has shown the stage. Therefore when I click Yes or No it hides the stage but then just hangs there. As if it can't return to the start method to continue the loop from where launch(args) occurred. How do I properly hide/show the stage whenever necessary, allowing the loop to continue whether yes or no was clicked.
Here is the code for Mail.java and Controller.java. Thanks a lot!
Mail.java
[Other variables set here]
public static int launchCount = 0;#FXML public Text subjectHolder;
public static ReceiveMailImap obj = new ReceiveMailImap();
public static void main(String[] args) throws IOException, MessagingException {
ReceiveMailImap.doit();
}
#Override
public void start(Stage primaryStage) throws Exception {
loader = new FXMLLoader(getClass().getResource("prompts.fxml"));
root = loader.load();
controller = loader.getController();
controller.setPrimaryStage(primaryStage);
scene = new Scene(root, 450, 250);
controller.setPrimaryScene(scene);
scene.getStylesheets().add("styleMain.css");
Platform.setImplicitExit(false);
primaryStage.setTitle("Download this file?");
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void doit() throws MessagingException, IOException {
Folder inbox = null;
Store store = null;
try {
Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);
store = session.getStore("imaps");
store.connect("imap.gmail.com", "myAccount#gmail.com", "Password");
inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_WRITE);
Message[] messages = inbox.getMessages();
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(UIDFolder.FetchProfileItem.FLAGS);
fp.add(UIDFolder.FetchProfileItem.CONTENT_INFO);
fp.add("X-mailer");
inbox.fetch(messages, fp);
int doc = 0;
int maxDocs = 400;
for (int i = messages.length - 1; i >= 0; i--) {
Message message = messages[i];
if (doc < maxDocs) {
doc++;
message.getSubject();
if (!hasAttachments(message)) {
continue;
}
String from = "Sender Unknown";
if (message.getReplyTo().length >= 1) {
from = message.getReplyTo()[0].toString();
} else if (message.getFrom().length >= 1) {
from = message.getFrom()[0].toString();
}
subject = message.getSubject();
if (from.contains("myAccount#gmail.com")) {
saveAttachment(message.getContent());
message.setFlag(Flags.Flag.SEEN, true);
}
}
}
} finally {
if (inbox != null) {
inbox.close(true);
}
if (store != null) {
store.close();
}
}
}
public static boolean hasAttachments(Message msg) throws MessagingException, IOException {
if (msg.isMimeType("multipart/mixed")) {
Multipart mp = (Multipart) msg.getContent();
if (mp.getCount() > 1) return true;
}
return false;
}
public static void saveAttachment(Object content)
throws IOException, MessagingException {
out = null; in = null;
try {
if (content instanceof Multipart) {
Multipart multi = ((Multipart) content);
parts = multi.getCount();
for (int j = 0; j < parts; ++j) {
part = (MimeBodyPart) multi.getBodyPart(j);
if (part.getContent() instanceof Multipart) {
// part-within-a-part, do some recursion...
saveAttachment(part.getContent());
} else {
int allow = 0;
if (part.isMimeType("application/x-silverlight-app")) {
extension = "xap";
allow = 1;
} else {
extension = "zip";
allow = 1;
}
if (allow == 1) {
if (launchCount == 0) {
launch(args);
launchCount++;
} else {
Platform.runLater(() -> primaryStage.show());
}
} else {
continue;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if ( in != null) { in .close();
}
if (out != null) {
out.flush();
out.close();
}
}
}
public static File createFolder(String subject) {
JFileChooser fr = new JFileChooser();
FileSystemView myDocs = fr.getFileSystemView();
String myDocuments = myDocs.getDefaultDirectory().toString();
dir = new File(myDocuments + "\\" + subject);
savePathNoExtension = dir.toString();
dir.mkdir();
System.out.println("Just created: " + dir);
return dir;
}
}
Controller.java
public class Controller implements Initializable {
#FXML
private Text subjectHolder;
public Button yesButton, noButton;
public ReceiveMailImap subject;
#Override
public void initialize(URL url, ResourceBundle rb) {
subject= new ReceiveMailImap();
subjectHolder.setText(subject.returnSubject());
}
public Stage primaryStage;
public Scene scene;
#FXML
ComboBox<String> fieldCombo;
public void setPrimaryStage(Stage stage) {
this.primaryStage = stage;
}
public void setPrimaryScene(Scene scene) {
this.scene = scene;
}
public String buttonPressed(ActionEvent e) throws IOException, MessagingException {
Object source = e.getSource();
if(source==yesButton){
System.out.println("How to tell Mail.java that user clicked Yes?");
return "POSITIVE";}
else{subject.dlOrNot("no");
System.out.println("How to tell Mail.java that user clicked No?");
primaryStage.hide();
return "NEGATIVE";}
}
}
There are a lot of issues with the code you have posted, but let me just try to address the ones you ask about.
The reason the code hangs is that Application.launch(...)
does not return until the application has exited
In general, you've kind of misunderstood the entire lifecycle of a JavaFX application here. You should think of the start(...) method as the equivalent of the main(...) method in a "traditional" Java application. The only thing to be aware of is that start(...) is executed on the FX Application Thread, so if you need to execute any blocking code, you need to put it in a background thread.
The start(...) method is passed a Stage instance for convenience, as the most common thing to do is to create a scene graph and display it in a stage. You are under no obligation to use this stage though, you can ignore it and just create your own stages as and when you need.
I think you can basically structure your code as follows (though, to be honest, I have quite a lot of trouble understanding what you're doing):
public class Mail extends Application {
#Override
public void start(Stage ignored) throws Exception {
Platform.setImplicitExit(false);
Message[] messages = /* retrieve messages */ ;
for (Message message : messages) {
if ( /* need to display window */) {
showMessage(message);
}
}
}
private void showMessage(Message message) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("prompts.fxml"));
Parent root = loader.load();
Controller controller = loader.getController();
Scene scene = new Scene(root, 450, 250);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.setTitle(...);
// showAndWait will block execution until the window is hidden, so
// you can query which button was pressed afterwards:
stage.showAndWait();
if (controller.wasYesPressed()) {
// ...
}
}
// for IDEs that don't support directly launching a JavaFX Application:
public static void main(String[] args) {
launch(args);
}
}
Obviously your logic for decided whether to show a window is more complex, but this will give you the basic structure.
To check which button was pressed, use showAndWait as above and then in your controller do
public class Controller {
#FXML
private Button yesButton ;
private boolean yesButtonPressed = false ;
public boolean wasYesPressed() {
return yesButtonPressed ;
}
// use different handlers for different buttons:
#FXML
private void yesButtonPressed() {
yesButtonPressed = true ;
closeWindow();
}
#FXML
private void noButtonPressed() {
yesButtonPressed = false ; // not really needed, but makes things clearer
closeWindow();
}
private void closeWindow() {
// can use any #FXML-injected node here:
yesButton.getScene().getWindow().hide();
}
}

How to close javafx and swing window threads between subsequent calls?

Below is a functioning class that simulates extracting data from a website. The question is how to close the window and threads after the data is retrieved? The error message is
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Platform.exit has been called
On line: final JFXPanel fxPanel = new JFXPanel() {
Here is the code. When Platform.exit() is inserted at the indicated locations, the above error occurs. In the actual code, javafx is used for obtaining and scanning the html text. Also, javafx is used for setting attributes on the server and starting a program on the server, both done using java script. The javafx functionality was removed from this minimal example that demonstrates the error that occurs when using Platform.exit().
public class Step11a {
public static void main(String[] args) throws ParseException, InterruptedException {
Step11a st = new Step11a();
st.getData();
st.getData();
}
private JTable table;
private String url;
private WebView webView;
public Step11a() {
url = "https://www.tsp.gov/investmentfunds/shareprice/sharePriceHistory.shtml";
table = new JTable();
}
private Scene createScene(ArrayBlockingQueue<DefaultTableModel> platfromQueue) {
StackPane root = new StackPane();
Scene scene = new Scene(root);
webView = new WebView();
WebEngine webEngine = webView.getEngine();
Worker<Void> worker = webEngine.getLoadWorker();
worker.stateProperty().addListener((Observable o) -> {
if (worker.getState() == Worker.State.SUCCEEDED) {
DefaultTableModel tableDataModel = (DefaultTableModel) table.getModel();
// Following steps deleted for minimal example
// 1) Get html code from server
// 2) Locate elements to modify
// 3) Create javascript string to modify element values
// 4) Execute javascript to update elemetns
// 5) Execute javascript to start data retrieval on server
// 6) Get html and extract table of data
// For this example, we just set the rows and columns
// in the table
tableDataModel.setColumnCount(11);
tableDataModel.setRowCount(24);;
try {
platfromQueue.put(tableDataModel);
} catch (Exception e) {
e.printStackTrace();
}
}
});
webEngine.load(url);
root.getChildren().add(webView);
return scene;
}
private DefaultTableModel initAndShowGUI() { // This method is invoked on the EDT thread
JFrame frame = new JFrame("WebViewTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JFXPanel fxPanel = new JFXPanel() {
private static final long serialVersionUID = 1L;
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 400);
}
};
frame.add(fxPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
ArrayBlockingQueue<DefaultTableModel> platformQueue = new ArrayBlockingQueue<DefaultTableModel>(5) ;
Platform.runLater(() -> {
initFX(fxPanel,platformQueue);
});
DefaultTableModel tspData = null;
try {
tspData = platformQueue.take();
} catch (Exception e) {
e.printStackTrace();
}
// Platform.exit(); // At this location causes error on next call
// error occurs on final JFXPanel fxPanel = new JFXPanel() {
return tspData;
}
private void initFX(JFXPanel fxPanel, ArrayBlockingQueue<DefaultTableModel> platformQueue) {
// This method is invoked on the JavaFX thread
// System.out.println("JavaFx thread name "+Thread.currentThread().getName());
Scene scene = createScene(platformQueue);
fxPanel.setScene(scene);
}
private DefaultTableModel getData() {
ArrayBlockingQueue<DefaultTableModel> swingQueue = new ArrayBlockingQueue<>(5);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
DefaultTableModel tspDataLocal = initAndShowGUI( );
swingQueue.put(tspDataLocal);
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
DefaultTableModel tableJFrameData = null;
try {
tableJFrameData = swingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Platform.exit(); // At this location causes error on next call
// error occurs on final JFXPanel fxPanel = new JFXPanel() {
return tableJFrameData;
}
}

how to use progressbar when loading image in picasso?

I want onStart() method to load image from server using picasso and I want to show a progress bar until the photos are fully downloaded
Here is my code:
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Picasso.with(context).load(imageLoad)
.placeholder(R.id.progressBarDetails)
.error(R.drawable.friend_request).noFade().resize(200, 200)
.into(avatarImage, new Callback() {
#Override
public void onError() {
// TODO Auto-generated method stub
}
#Override
public void onSuccess() {
// TODO Auto-generated method stub
progressbar.setVisibility(View.GONE);
}
});
Picasso.with(this).load(imageLoad).into(target);
}
OnFinished a = new OnFinished() {
#Override
public void onSendFinished(IntentSender IntentSender, Intent intent,
int resultCode, String resultData, Bundle resultExtras) {
// TODO Auto-generated method stub
intent = new Intent(getApplicationContext(), Map.class);
}
};
private Target target = new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
File file = new File(Environment
.getExternalStorageDirectory().getPath()
+ "/actress_wallpaper.jpg");
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 75, ostream);
ostream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
I haven't tested your code but even if that works, the file actress_wallpaper.jpg isn't loaded in the ImageView. In the docs, it says
Objects implementing this class must have a working implementation of Object.equals(Object) and Object.hashCode() for proper storage internally.
Try this:
File file = new File(pathToFile);
Picasso.with(context)
.load(file)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
progressbar.setVisibility(View.GONE);
}
});
be warned I haven't tested my code.
Update:
I have tried version 2.3.2 and 2.3.3, it seems like that there's an issue https://github.com/square/picasso/issues/539
It is an old question but may be this answer can help others as I also had issues in showing progress bar while loading image from server.
I am using Picasso 2.4.0. and I am using Picasso Target interface to load image in imageview. Here is the tested and working code:
First add the following lines:
ImageView ivPhoto = (ImageView) findViewById(R.id.iv_photo);
ProgressBar pbLoadingBar = (ProgressBar) findViewById(R.id.pb_loading_bar);
//get image url
String imageUrl = getImageUrl();
//ImageViewTarget is the implementation of Target interface.
//code for this ImageViewTarget is in the end
Target target = new ImageViewTarget(ivPhoto, pbLoadingBar);
Picasso.with(mContext)
.load(imageUrl)
.placeholder(R.drawable.place_holder)
.error(R.drawable.error_drawable)
.into(target);
Here is the implementation of Target interface used above
private static class ImageViewTarget implements Target {
private WeakReference<ImageView> mImageViewReference;
private WeakReference<ProgressBar> mProgressBarReference;
public ImageViewTarget(ImageView imageView, ProgressBar progressBar) {
this.mImageViewReference = new WeakReference<>(imageView);
this.mProgressBarReference = new WeakReference<>(progressBar);
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
//you can use this bitmap to load image in image view or save it in image file like the one in the above question.
ImageView imageView = mImageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
ProgressBar progressBar = mProgressBarReference.get();
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
ImageView imageView = mImageViewReference.get();
if (imageView != null) {
imageView.setImageDrawable(errorDrawable);
}
ProgressBar progressBar = mProgressBarReference.get();
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
ImageView imageView = mImageViewReference.get();
if (imageView != null) {
imageView.setImageDrawable(placeHolderDrawable);
}
ProgressBar progressBar = mProgressBarReference.get();
if (progressBar != null) {
progressBar.setVisibility(View.VISIBLE);
}
}
}
The above code works fine if used for loading image in activity. But if you want to load image in gridview/recyclerview or view pager etc. where same view holder is used, you might get an issue where onBitmapLoaded() is not called (as the view is recycled and Picasso only keeps a weak reference to the Target object). Here is a link to solve this problem.
change to this
Picasso.get()
.load(tImageUrl())
.into(holder.AnimImage, new Callback() {
#Override
public void onSuccess() {
holder.progressBar.setVisibility(View.GONE);
}
#Override
public void onError(Exception e) {
}
});

Resources