arleitiss
arleitiss

Reputation: 1304

Java: Update GUI from another class within same .java file?

so I have this java file, it has two classes: RPClient which has main method. and RPClientOpsImlp is being a listener which accepts messages from server and changes GUI.

here is simplified code.

Here is the file:

import java.io.*;
import java.lang.*;
import org.omg.CORBA.*;
import RPSGame.*;
import org.omg.CosNaming.* ;
import org.omg.CosNaming.NamingContextPackage.*;
import java.net.*;
import javax.swing.JOptionPane;


public class RPClient
{
    public static void main(String args[])
    {
    try{
        RPSGU rps = new RPSGU();
        rps.pack();
        rps.setVisible(true);
        String playerName = JOptionPane.showInputDialog(rps, "Please enter your player name.");
        rps.SetMyName(playerName);
        } catch (Exception e) {
            System.out.println("ERROR : " + e) ;
            e.printStackTrace(System.out);
            }

    }
}

class RPClientOpsImpl implements RPClientOpsOperations{
    public void callBack(String message) {
         RPSGU rps = new RPSGU();
         rps.SetMyName("NewName");
    }
}

Basically in RPClientOpsImpl I tried calling the GUI and update it's label but that doesn't work. RPSGU is a .java file of GUI which has this function:

public void SetProgress(String label){
progress.setText(label);
}

Upvotes: 0

Views: 1194

Answers (2)

Giulio Meneghin
Giulio Meneghin

Reputation: 46

You write

RPClientOpsImlp is being a listener which accepts messages from server and changes GUI

The code in your question is not very clear, but if I have to make a guess I would say that the code is trying to update the GUI from a thread that is not the EDT. You can try doing something like this:

class RPClientOpsImpl implements RPClientOpsOperations {

    private RPSGU rps = new RPSGU();

    public void callBack(String message) {
        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                rps.SetMyName("NewName");
            }
        });
    }
}

[FIXED] To refresh the same GUI, as per comment:

public class RPClient {

    public static void main(String args[]) throws Exception {
        final RPClientOpsImpl rpc = new RPClientOpsImpl();
        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                RPSGU rps = new RPSGU();
                rpc.setRps(rps);
                rps.pack();
                rps.setVisible(true);
                String playerName = JOptionPane.showInputDialog(rps, "Please enter your player name.");
                rps.setMyName(playerName);
            }
        });
    }
}

class RPClientOpsImpl implements RPClientOpsOperations {

    private RPSGU rps;

    public void setRps(RPSGU rps) {
        this.rps = rps;
    }

    public void callBack(String message) throws Exception {
        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                rps.setMyName("NewName");
            }
        });
    }
}

Note that GUI creation and state change, such as invoking pack() and setVisible(), should be done on the EDT, hence the call to invokeAndWait() in the main() method.

Also, SetMyName() should actually be named setMyName(), with a lower case initial letter as per Java convention.

Upvotes: 2

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

Consider doing things in the other direction:

  • Create your GUI
  • Launch your non-GUI program from within your GUI, using a SwingWorker to allow it to run in a background thread and to allow communication.

For example,...

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.List;

import javax.swing.*;

public class RpsMain {

   private static void createAndShowGui() {
      RpsGui mainPanel = new RpsGui();

      JFrame frame = new JFrame("RpsMain");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);

      String playerName = JOptionPane.showInputDialog(mainPanel,
            "Please enter your player name.");
      mainPanel.setPlayerName(playerName);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class RpsGui extends JPanel {
   private RpClient2 rpClient2;
   private JTextArea textArea = new JTextArea(30, 50);
   private String playerName;

   public RpsGui() {
      textArea.setWrapStyleWord(true);
      textArea.setLineWrap(true);
      textArea.setFocusable(false);

      JButton startRpClientButton = new JButton(
            new StartRpClientAction("Start"));
      JPanel btnPanel = new JPanel();
      btnPanel.add(startRpClientButton);

      setLayout(new BorderLayout());
      int vsbPolicy = JScrollPane.VERTICAL_SCROLLBAR_ALWAYS;
      int hsbPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
      add(new JScrollPane(textArea, vsbPolicy, hsbPolicy), BorderLayout.CENTER);
      add(btnPanel, BorderLayout.PAGE_END);
   }

   public void setPlayerName(String playerName) {
      this.playerName = playerName;
   }

   private class StartRpClientAction extends AbstractAction {
      public StartRpClientAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (rpClient2 != null && !rpClient2.isDone()) {
            return;
         }
         rpClient2 = new RpClient2(playerName, RpsGui.this);
         rpClient2.execute();
      }
   }

   public void appendText(String text) {
      textArea.append(text);
   }
}

class RpClient2 extends SwingWorker<Void, String> {
   private static final long ARTIFICIAL_SLEEP_TIME = 1000;
   private String playerName;
   private int count = 0;
   private RpsGui gui;
   private boolean running = true;

   public RpClient2(String playerName, RpsGui gui) {
      this.playerName = playerName;
      this.gui = gui;
   }

   @Override
   protected Void doInBackground() throws Exception {

      // the while loop below is just to simulate a long-running task.
      // in a real application, here's where you'd have the code to
      // the non-GUI stuff that you don't want to do on the event thread.

      while (running) {
         String dataForGui = "From RpClient2 background thread. Player: "
               + playerName + "; Count: " + count;

         publish(dataForGui); // allows us to communicate with the GUI

         count++;
         Thread.sleep(ARTIFICIAL_SLEEP_TIME); // to simulate long-running
                                              // activity
      }
      return null;
   }

   @Override
   protected void process(List<String> chunks) {
      for (String chunk : chunks) {
         gui.appendText(chunk + "\n");
      }
   }
}

Upvotes: 1

Related Questions