Java:从同一个.java文件中的另一个类更新GUI?

时间:2015-03-15 16:47:51

标签: java swing user-interface

所以我有这个java文件,它有两个类: RPClient有主要方法。 和 RPClientOpsImlp是一个侦听器,它接受来自服务器的消息并更改GUI。

这里是简化代码。

这是文件:

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

基本上在RPClientOpsImpl中我尝试调用GUI并更新它的标签,但这不起作用。 RPSGU是GUI的.java文件,具有以下功能:

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

2 个答案:

答案 0 :(得分:2)

你写

  

RPClientOpsImlp是一个侦听器,它接受来自服务器的消息并更改GUI

你问题中的代码不是很清楚,但如果我不得不猜测,我会说代码试图从不是EDT的线程更新GUI。你可以尝试做这样的事情:

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] 根据评论刷新相同的GUI:

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

请注意,GUI创建和状态更改(例如调用pack()setVisible())应在EDT上完成,因此invokeAndWait()方法中对main()的调用

此外,SetMyName()实际上应该命名为setMyName(),根据Java约定使用小写首字母。

答案 1 :(得分:1)

考虑从另一个方向做事:

  • 创建GUI
  • 使用SwingWorker从 GUI中启动非GUI程序,以允许它在后台线程中运行并允许通信。

例如,......

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