我有一个带有4个JButton和一个动作侦听器的主窗口,其中三个调用另一个窗口,第四个退出。我的两个窗口可以正常工作,但是由于某种原因,等待客户端连接的窗口会打开,您可以看到窗口的边界,但是窗口的内部是透明的。
我尝试从我的主要班级说new HostWindow()
,效果很好;只是当我从StartWindow类调用它时,它不起作用。
码:
起始窗口:
public class StartWindow extends JFrame{
private JPanel pane;
private JButton host;
private JButton join;
private JButton comp;
private JButton exit;
public StartWindow()
{
this.setSize(220, 110);
this.setTitle("Closed Arena");
pane = new JPanel();
this.add(pane);
host = new JButton("Host Match");
host.addActionListener(new myButtonListener());
join = new JButton("Join Match");
join.addActionListener(new myButtonListener());
comp = new JButton("Play Computer");
comp.addActionListener(new myButtonListener());
exit = new JButton("Exit");
exit.addActionListener(new myButtonListener());
pane.add(host);
pane.add(join);
pane.add(comp);
pane.add(exit);
this.setResizable(false);
pane.setVisible(true);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//If I make a new Hostwindow here it displays properly
//new HostWindow();
}
private class myButtonListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if(source.equals(host))
{
close();
//But here it displays improperly.
new HostWindow();
}
if(source.equals(join))
{
close();
new JoinWindow();
}
if(source.equals(comp))
{
close();
new Arena();
}
if(source.equals(exit))
{
close();
}
}
}
public void close()
{
this.dispose();
}
}
主机窗口:
private JPanel panel;
private JLabel text;
private JButton stop;
private LabelEditor edit;
private Thread editThread;
private ServerSocket server;
private Socket mySocket;
public HostWindow()
{
panel = new JPanel();
text = new JLabel("Waiting for client");
stop = new JButton("Stop");
stop.addActionListener(new buttonList());
panel.add(text);
panel.add(stop);
this.add(panel);
this.setResizable(false);
this.setSize(160, 90);
this.setTitle("Server");
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
edit = new LabelEditor(text, "Waiting for client", 700);
editThread = new Thread(edit);
editThread.start();
try
{
server = new ServerSocket(4011);
mySocket = server.accept();
server.close();
new Arena(mySocket, true);
}
catch (IOException e) {
System.out.print("Failed to set up server!");
}
editThread.interrupt();
this.dispose();
}
编辑:HostWindow确实扩展了JFrame,我jsut并未复制粘贴标题,但它看起来像这样:
公共类HostWindow扩展了JFrame {
Edit2:谢谢回答者,当我这样做时它已修复,以便serer在单独的线程中启动:
if(source.equals(host))
{
close();
HostWindow hoster = new HostWindow();
Thread hosterThread = new Thread(hoster);
hosterThread.start();
}
并在hostwindow中:
我将服务器中的内容移到运行中。
public void run() {
try
{
server = new ServerSocket(4011);
mySocket = server.accept();
server.close();
new Arena(mySocket, true);
}
catch (IOException e) {
System.out.print("Failed to set up server!");
}
editThread.interrupt();
this.dispose();
}
最佳答案
这里的问题是您正在UIThread内部执行持久的阻塞操作。
线程是在单个程序中运行的命令的同时序列(我建议在Java concurrency上阅读)。通常有一个线程被称为UIThread,它执行UI元素的绘制并与其代码一起工作。
创建套接字-与远程主机的连接意味着您正在启动一个过程,该过程可能需要花费几秒钟的时间。这发生在UIThread的UI类的构造函数内部。在建立连接之前,构造函数中的其余代码无法运行。这是因为连接过程是一个阻塞操作-套接字创建后的代码要等到套接字创建完成后才能运行。
因此,您应该将套接字创建移至其他线程。