所以我有这个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);
}
答案 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)
考虑从另一个方向做事:
例如,......
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");
}
}
}