This week's book giveaway is in the Java in General forum.
We're giving away four copies of Event Streams in Action and have Alexander Dean & Valentin Crettaz on-line!
See this thread for details.
Win a copy of Event Streams in Action this week in the Java in General forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Paul Clapham
  • Knute Snortum
  • Rob Spoor
Saloon Keepers:
  • Tim Moores
  • Ron McLeod
  • Piet Souris
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Frits Walraven
  • Ganesh Patekar

Posting a wait dialog while a process runs- I don't like my solution

 
Ranch Hand
Posts: 250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a requirement which involves doing the following:

  • put up a dialog that says I am updating a table
  • run a command that does some calculations to refill a table
  • the user should not be able to do anything while this is happening
  • inform the user if the update actually worked

  • I experimented with ways of posting a modal dialog while my task was running and came up with this (example leaves out the table)

    The table seems to update really slowly and flashes, I am afraid I am using up all my CPU somewhere other than the updateValues method. Passing an array by reference to return the status also seems pretty kludgy. But I have not had a lot of success working out an alternate that doesn't just display the statusDialog and then never returns.

    Could someone have a look and let me know if I am going down the wrong track with this problem?

    Thanks.


     
    Marshal
    Posts: 65035
    247
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You have some so‑lcalled arrow code starting in line 20. That doesn't look right. Why are you running that sort of code on the EDT? Then you are starting  new thread. Use a SwingWorker obect instead, and a progress bar. The swing worker can use its own thread.
    Don't use Calendar. If you need times, use the two methods in the System class.
    If you set the dialogue not visible, will that take away its modality? Surely it should be disposed of.
    Why are you extending the frame and dialogue classes? Neither of those classes is used as a subclass of frame nor of dialogue.
    What is your wait method doing? I suspect that loop will use so many resources in your thread that there will be nothing left to run the other methods.
    What does the update values method do? I can't see that it does anything more than introduce a few milliseconds' delay into your execution.
     
    Jon Swanson
    Ranch Hand
    Posts: 250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    A number of the questions you brought up come from trying to reduce a large application to a small example. In the full application, there is a GUI that contains a table and a number of options to run calculations on the data in the table. It is very important that there is no user interaction with the GUI while the calculations are running. TestUpdateStatus is a stand-in for the main application. The calculations can run for up to 30 seconds and some are not even run in Java. The updateValues in the code I posted is a stand-in for one of those calculations. As you said, it does nothing except act as a placeholder. It is also possible that the calculations run for 0.1 seconds. In that case the statusDialog goes up and down too fast to read. So the wait method was intended to force the status dialog to display for a minimum of two seconds. My thought was the updateValues would run and use whatever resources and time it needed. When it finished, if two seconds had not elapsed, wait would run and use up the remaining time. At that point I didn't think I had to worry about wasting resources.

    I think the key point is related to the "arrow code." I had actually tried implementing a progress bar at one point. I could write simple examples that worked great, but trying to insert them into the real application never worked. Either the progress bar did not display or it never posted any progress. Very frustrating. I thought it might be due to the fact that since user interaction should be disabled when calculations where running, I was running afoul of code somewhere else that someone put in to enforce that behavior. But since there is general agreement the code doesn't look right, I will try again to take it off the EDT.

    I did learn one way to improve the code. Runnable does not allow you to return a value, but Callable does, by using a Future variable. So my code now looks like this:




    The behavior is identical to the previous code. The table still seems to update slowly, i.e. I see each row paste one at a time. Before I tried to have a status dialog, the whole table posted at once.

    I am going to go back and read more about pools and SwingWorker. I am also going to add a table to my simple example. I wouldn't be surprised if a simple example updated the table smoothly and the large application did not. I might also add a pause in the wait, so it doesn't check the time as often. Though, as I said, I thought it was just spinning its wheels until it was time to close the status dialog, so didn't need to be very smart.


     
    Rancher
    Posts: 3409
    33
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    no user interaction with the GUI


    Most of the user interaction can be reduced/controlled  by disabling the controls.
     
    Campbell Ritchie
    Marshal
    Posts: 65035
    247
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Jon Swanson wrote:. . . It is very important that there is no user interaction with the GUI while the calculations are running. . . . The calculations can run for up to 30 seconds and some are not even run in Java.

    Sounds like something which should run in its own thread, in code completely separate from the GUI.

    . . . It is also possible that the calculations run for 0.1 seconds. . . .

    If you design the code on the pessimistic assumption that it is going to take 30″, you will be able to cope with its running faster in 0.1″. Don't do it the other way round, making optimistic assumptions and getting pessimistic results.

    I had actually tried implementing a progress bar at one point. I could write simple examples that worked great, but trying to insert them into the real application never worked. Either the progress bar did not display or it never posted any progress. . . .

    Is there nothing in the Java™ Tutorials that will explain that?

    Runnable does not allow you to return a value, but Callable does, by using a Future variable.  . . .

    Once I saw you mention Callable, I thought a Future would be a good idea. But why are you using a Boolean as the return type? Why not create a class to encapsulate all your calculations and return an instance of that. Consider whether it is still necessary to block interactions until the calculations are completed, or inactivate the controls as Norm suggested.
     
    Jon Swanson
    Ranch Hand
    Posts: 250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I started thinking over what the code was originally intended to do. The goal was to provide immediate response whenever a user entered data anywhere in the UI. So for example, the table is hooked to an ObservableValue. If the user changes data in any cell, the observable is updated, which notifies half a dozen other elements of the program which all update based on the change. Likewise, other elements of the UI could also be changed, again notifying all, the observers, including the table, which has columns that update on any change to the data, anywhere in the UI.

    Originally, the calculations that were requested were all fast, i.e., tens of ms at most. Things have changed by adding UI elements that while they still either set objects in the observable or respond to changes in the observable, they take a long time to get their work done. Which created the request to post a "Just a minute..." dialog while they were working through their calculations.

    I think that is where some of the problems occur. Press button -> update observable -> notify observers -> calculations -> update UI currently does not separate the set of calculations from the UI update because they used to be fast. I am actually trying to get the "Just a minute..." to post when I run a method that has been in the code from the start that updates the table, which updates the observable, which notifies the observers, which triggers calculations, which update other parts of the UI. But if I run that method in a thread other than the EDT, I think I am ending up with the final UI update running in that other thread also and then the table update is really slow. And, in fact, the button is not in a class that has any methods that are slow (it just updates a parameter in the observable), it is one of the other classes that is an observer that has the slow piece in it. That class usually needs to be silent, except, it has been requested that in one specific case, the user is warned. So I was trying to post the dialog from the class with the button that implements that one case. That is no longer sounding like a good idea.
     
    Sheriff
    Posts: 24594
    55
    Eclipse IDE Firefox Browser MySQL Database
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Norm Radder wrote:

    no user interaction with the GUI


    Most of the user interaction can be reduced/controlled  by disabling the controls.



    Indeed. I remember years ago reading about using a "glass pane" to do that; here's the tutorial: How to Use Root Panes.
     
    Jon Swanson
    Ranch Hand
    Posts: 250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    For what's it's worth, I modified my original method in two ways.

    1. Removed the line that posted the dialog



    2. Ran the calculation in the EDT



    In either case, the elapsed time to run the update averaged about 5 s, whereas using either the original runnable or the callable, the elapsed time averaged 14 s. The latter option meets my requirements. I believe that doing better than this would require refactoring updateValues, which is not something I can do as part of this project.
     
    Norm Radder
    Rancher
    Posts: 3409
    33
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Eat up the remainder  


    Why not use Thread sleep instead of a busy loop?
     
    Jon Swanson
    Ranch Hand
    Posts: 250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mostly I was just being lazy. I could have calculated the amount of time that the process took, subtracted that from the 2000 ms I am currently using as the minimum time to display the dialog and used Thread.sleep() for the remaining time (if any). I did try changing the wait method to sleep for 100 ms before checking to see if the full 2000 ms was exhausted. Making no change, making the change I mentioned or leaving out the wait altogether doesn't affect the problems I am having with the update and the former two produce identical results even on short updates. The average time required for the update is longer than 2000 ms, so I wasn't focused on that bit of the code. But you are right, it would make more sense to calculate the time left and just sleep.
     
    Aaaaaand ... we're on the march. Stylin. Get with it tiny ad.
    Java Code Review and Psychology
    https://coderanch.com/t/714798/java/Java-Code-Review-Psychology
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!