0

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);
}
7
  • 1
    Your in essence asking "why isn't this code working", but are posting highly complex code full of dependencies that we have no access to. I suggest that you greatly simplify your code so as to make it as easy for us to understand as possible by removing all outside dependencies and by creating a new program that has no Corba, etc stuff, but just shows what you're attempting to do -- enable communication between a continuously running program and a Swing GUI, and show us how you're trying to do this. Create and post a minimal example program. Commented Mar 15, 2015 at 17:04
  • @HovercraftFullOfEels I have cut out the code that's unrelated to problem leaving bare minimum, it's literally just GUI function now that I can't solve. Commented Mar 15, 2015 at 17:12
  • First of all, java code convention says that each of your .java file should always contain only one class except inner classes. Commented Mar 15, 2015 at 17:18
  • @Everv0id so without moving class into it's own java file, there is no solution? Commented Mar 15, 2015 at 17:25
  • If RPSGU is the GUI why duo you create one in the message handler class? It should be given a reference to the gui on creation. Commented Mar 15, 2015 at 17:30

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Well it somewhat worked, it updates label but only if new GUI is called using rps.setVisible(true) it creates new GUI window but has updated label. Is there any way to refresh the GUI that was called from main class?
@arleitiss: the issue is no different from the very basic question of how to have two objects communicate with each other, and the answer is the same: make sure that one, here your RPClientWhatever, has a valid reference to the currently displayed GUI. So pass it in! Use a constructor parameter or setter method to pass references. Again this is no different from non-GUI coding.
I just up-voted you (only 5 votes left today), but now see that your latest edit starts the RPClientOpsImpl on the Swing event thread, something that I'm not sure should be done.
I agree, it shouldn't. But the alternative was creating rps in the main thread, which is also wrong (followed by the creation of rpc). We don't have the code of RPClientOpsImpl, so as long as the concept is clear I would say it could pass as a good example.
Actually, maybe this one is better. I changed the code and added a setter method for RPClientOpsImpl.
|
1

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");
      }
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.