Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operation priority in Java. (An object instantiates and runs before the GUI is updated?)

I want the GUI to change the title of a button from "Go" to "Working..." before an object is instantiated and actually does the work. When finished, I want the title of the button to switch back to "Go."

Here's the code:

    private class convert implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        JButton button = (JButton)e.getSource();

        button.setText("Working...");
        button.setEnabled(false);

        anObject name = new AnObject();
        boolean result = name.methodName(chooser.getSelectedFile(),encoding);

        // A bunch of stuff was here but irrelevant to the question,
        // so it was removed to save room.

        button.setEnabled(true);
        button.setText("Go");
    }

What actually happens in practise is name is instantiated, methodName gets called, and THEN the button gets updated on the screen, despite the fact that I have told the VM to change the button title first.

My working theory is, given I have not made this program threaded, this has something to do with operational priority, or internal threading of the JVM, or something...

Any suggestions?

like image 488
Steven C. Britton Avatar asked Jul 24 '11 12:07

Steven C. Britton


People also ask

What are the GUI components in Java?

GUI Component classes, such as Button , TextField , and Label . GUI Container classes, such as Frame and Panel . Layout managers, such as FlowLayout , BorderLayout and GridLayout . Custom graphics classes, such as Graphics , Color and Font .

What is the purpose of setText () and getText () methods?

the getText method returns a String, while the setText receives a String, so you can write it like label1. setText(nameField. getText()); in your listener.

What is Java GUI programming?

In Java applications, the components that comprise a GUI (Graphical User Interface) are stored in containers called forms. The Java language provides a set of user interface components from which GUI forms can be built.

Which classes represent GUI components have names beginning with the letter J?

In Swing, classes that represent GUI components have names beginning with the letter J. Some examples are JButton, JLabel, and JSlider.


2 Answers

I know that you've already accepted a solution, but since you are running into the "frozen gui" syndrome, you most definitely have a threading issue, and invokeLater won't solve your problem. As noted above by extraneon, you need a SwingWorker or some background thread to solve this. Also, I think that this is a good case for use of an AbstractAction rather than an ActionListener. For example:

import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class Convert extends AbstractAction {
   private static final long SLEEP_TIME = 3000; // 3 seconds
   private String enabledText;
   private String disabledText;

   public Convert(String enabledText, String disabledText) {
      super(enabledText);
      this.enabledText = enabledText;
      this.disabledText = disabledText;
   }

   public void actionPerformed(ActionEvent e) {
      Object source = e.getSource();
      if (!(source instanceof JButton)) {
         return;
      }
      final JButton button = (JButton) source;
      setButtonEnabled(button, false);
      new SwingWorker<Void, Void>() {
         @Override
         protected Void doInBackground() throws Exception {
            // TODO: long-running code goes here. 
            // Emulated by Thread.sleep(...) 
            Thread.sleep(SLEEP_TIME);
            return null;
         }

         @Override
         protected void done() {
            setButtonEnabled(button, true);
         }
      }.execute();
   }

   public void setButtonEnabled(JButton button, boolean enabled) {
      if (enabled) {
         button.setText(enabledText);
         button.setEnabled(true);
      } else {
         button.setText(disabledText);
         button.setEnabled(false);
      }
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Convert");
      frame.getContentPane().add(new ConvertGui());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

@SuppressWarnings("serial")
class ConvertGui extends JPanel {
   public ConvertGui() {
      add(new JButton(new Convert("GO", "Working...")));
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(300, 200);
   }
}
like image 130
Hovercraft Full Of Eels Avatar answered Nov 10 '22 07:11

Hovercraft Full Of Eels


An "ActionPerformed" callback occurs in the event thread, and generally nothing on the GUI will update until it returns. If you want to update the gui, do something, and then update it again, you will need to update the gui and spawn a thread and return. The thread will then have to do it's action, and then do a SwingUtilities.invokeLater to update the gui.

like image 42
Paul Tomblin Avatar answered Nov 10 '22 07:11

Paul Tomblin