Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Question about JButton events  RSS feed

 
Dirk Coppieters
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello all,
As a newbee to java and awt
I have created a small java application that will draw a JFrame with
a JTextArea and as the program progresses, messages are added to this textarea. This works fine. (I call this window my progress_screen)

Now I want to call before my progress_screen another window, my welcome_screen, which simply contains some JLabels and a Next button.
As the Next button is pressed, the progress_screen needs to be called
and to program needs to do its work. (and add messages to the textarea)
So I added an actionlistener to this next button, and when an action event occurs, I generate the progress_screen and do all the work I need to do in this ActionPerformed method.

The problem I have is that the progress_screen frame is drawn but has no components until all the stuff in the 'ActionPerformed method' is completed. (so I loose the progressing messages and I get everything after it all has been done).

...
static JButton next_button2 = new JButton("Next");
...
next_button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*****************************************
//
// PROGRESS_SCREEN
//
******************************************/
welcome_screen.hide();
welcome_screen.dispose();

GraphicalUserInterface.run(progress_screen, installer_program_name+" "+installer_program_version, 500, 450);

progress_screen.setVisible(true);
progress_screen.show_all();


...
do some work that adds messages to the textarea
but textarea is not shown on JFrame
...
do some additional work
...
} //here the textarea is drawn buts its too late for me
...
welcome_screen = new WelcomeScreen(next_button1, welcome_info);
...


Is this logical behavior ?

What would be the correct way to setup such an application ?

Thanks for any response,
Dirk Coppieters
 
Eddie Vanda
Ranch Hand
Posts: 283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Dirk,

One way is to break a task into a number of different subtasks, and call them one by one from a switch statements driven by a swing timer. You would only call one subtask each time the timer calls, and after the last task you would probably want to turn the timer off. You would need a class variable to keep track of what task the timer is up to.

Ed
 
clio katz
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi dirk!

i can't say i know *exactly* what's happening ... but i can spot an oncoming train when you do the

welcome_screen.dispose();

this is my guess about the particulars of what's going wrong:

- your 'next' button's listener is trying to dispose of the button's
own container (welcome_screen), and thus the button itself (w listener!)

- swing is kind enough to forestall this action until the button's
actionListener link is dispos-able too

- code continues to execute, but suppresses intermediate gui q events

- the single-threaded swing q is hogging the gui until the _dispose()
action completes and he can revalidate (in the post-dispose world)

- finally, the listener semi-finishes (_dispose() still pending!),
swing does the _dispose(), THEN he gets to the next Q'd item: progresswin


if you want to test that this is actually what's going on just for fun, try commenting out the _dispose() call...


That's my attempt at diagnostics. On the overall design, I'll throw in my two cents, for what it's worth...

You might want to generally structure the code so that the actionListeners trigger things to happen, rather than actually doing things themselves. This keeps listener Q's unclogged, and also helps you think in terms of "state": events, gui, data ... (conversely model-view-controller:=)


By way of a small example, your welcome win has 2 states: OPEN/CLOSED

The OPEN state is the default, the NEXT button triggers the state-change to CLOSED.

So (assuming there is no third state like CANCELLED:-), the NEXT button only needs to close the welcome window.

Next, the progress window init is triggered by the CLOSED (not CANCELLED:-) state of the welcome window ... so you can add a WindowListener for the welcome window. The welcomewin listener's windowClosed method can invoke the progress window's init code ... and so on...

ActionListeners have to do stuff, but the trick is to make them do as little as possible - especially time-consuming stuff. Since a listener just represents a new item in a given Q of events, it's best to hand off as much work as you can to a thread somewhere - which you have wisely chosen to do already.

hth
 
Dirk Coppieters
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, using swingworker example of sun with the timer worked.
(it took me some time to understand the fact that the work in
the events and the work for the gui is done by the same thread;
as per:
The Event-Dispatching Thread
Swing event-handling and painting code executes in a single thread, called the event-dispatching thread. This ensures that each event handler finishes executing before the next one executes and that painting isn't interrupted by events. To avoid the possibility of deadlock, you must take extreme care that Swing components and models are created, modified, and queried only from the event-dispatching thread.
Thanks!
Dirk
 
clio katz
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yeah, the single-event-q strikes me as a pretty big deficiency in the java gui. it kindof primitive-izes the fluidity of multi-tasking, event-based gui model. sure, machines are getting bigger n faster, but 'programming around' the single q requires "great care", and thread creation/class instantiation are both relatively expensive ops in memory and clock cycles

(on the other hand, i've hosed my box more than a few times clanging windows around with hastily-constructed vc++ mfc's ...)

bravo for acquainting yourself w swingworker the first time out. i gulped for a long while considering the performance hit of introducing class, thread, synchronized methods ... but the headache eventually subsided. i'm ok now .. and when the classloader gods are smiling i even manage to paint a splash/progress window before the background task has finished!:-)

ah well.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!