Java Instant Messenger-从登录表单启动时客户端无法正常运行
我目前正在编写一个即时通讯应用程序。我从一个运行正常的基本客户机/服务器设置开始。但是,当我从Login.java启动Java Instant Messenger-从登录表单启动时客户端无法正常运行,java,Java,我目前正在编写一个即时通讯应用程序。我从一个运行正常的基本客户机/服务器设置开始。但是,当我从Login.java启动Client()类时(在第一次运行Server.java之后),JFrame会出现,但完全为空,即对话面板、用户文本输入字段等元素不存在。这很奇怪,因为服务器指示客户端已连接,但我无法在客户端窗体中键入/查看任何内容 如果我启动服务器并直接连接客户机(即不从Login.java启动它),那么客户机和服务器都可以完美地工作,并且可以一起进行对话 奇怪的是,当我在服务器不运行的情况下
Client()类时(在第一次运行Server.java之后),JFrame会出现,但完全为空,即对话面板、用户文本输入字段等元素不存在。这很奇怪,因为服务器指示客户端已连接,但我无法在客户端窗体中键入/查看任何内容
如果我启动服务器并直接连接客户机(即不从Login.java启动它),那么客户机和服务器都可以完美地工作,并且可以一起进行对话
奇怪的是,当我在服务器不运行的情况下从Login.java启动Client.java时,窗口显示为它应该显示的样子,元素保持不变(但显然无法使用,因为它没有连接到服务器)。此外,当我关闭Server.Java时,Client.Java将恢复为显示所有元素,但在没有服务器连接的情况下仍然无法使用
非常感谢您的帮助。
谢谢
Login.Java:
import java.awt.*;//contains layouts, buttons etc.
import java.awt.event.*; //contains actionListener, mouseListener etc.
import javax.swing.*; //allows GUI elements
public class Login extends JFrame implements ActionListener, KeyListener {
private JLabel usernameLabel = new JLabel("Username/Email:");
private JLabel userPasswordLabel = new JLabel("Password:");
public JTextField usernameField = new JTextField();
private JPasswordField userPasswordField = new JPasswordField();
private JLabel status = new JLabel("Status: Not yet logged in.");
private JButton loginButton = new JButton("Login");
private JButton registerButton = new JButton("New User");
public Login() {
super("Please Enter Your Login Details...");//titlebar
setVisible(true);
setSize(400, 250);
this.setLocationRelativeTo(null); //places frame in center of screen
this.setResizable(false); //disables resizing of frame
this.setLayout(null); //allows me to manually define layout of text fields etc.
ImageIcon icon = new ImageIcon("bin/mm.png");
JLabel label = new JLabel(icon);
this.add(usernameLabel);
this.add(userPasswordLabel);
this.add(usernameField);
this.add(userPasswordField);
this.add(loginButton);
this.add(registerButton);
this.add(status);
this.add(label);
label.setBounds(0, 0, 400, 70);
usernameLabel.setBounds(30, 90, 120, 30); //(10, 60, 120, 20);
userPasswordLabel.setBounds(30, 115, 80, 30);//(10, 85, 80, 20);
usernameField.setBounds(150, 90, 220, 30);
userPasswordField.setBounds(150, 115, 220, 30);
loginButton.setBounds(150, 160, 110, 25);
registerButton.setBounds(260, 160, 110, 25);
status.setBounds(30, 190, 280, 30);
status.setForeground(new Color(50, 0, 255)); //sets text colour to blue
loginButton.addActionListener(this);
registerButton.addActionListener(this);
registerButton.setEnabled(false);
userPasswordField.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == loginButton) {
String userName = usernameField.getText();
String password = userPasswordField.getText();
if (userName.equals("mick") && password.equals("mick")) {
status.setText("Status: Logged in.");
this.setVisible(false);
new Client("127.0.0.1").startRunning();
} else {
status.setText("Status: Password or username is incorrect.");
status.setForeground(new Color(255, 0, 0)); //changes text colour to red
}
}
}
}
Client.java:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Date; //timestamp functionality
import javax.swing.*;
public class Client extends JFrame { //inherits from JFrame
//1. Creating instance variables
private JTextField userText; //where user inputs text
private JTextArea chatWindow; //where messages are displayed
private String fullTimeStamp = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date());
//fullTimeStamp - MM = months; mm = minutes; HH = 24-hour cloc
private ObjectOutputStream output; //output from Client to Server
private ObjectInputStream input; //messages received from Server
private String message = "";
private String serverIP;
private Socket connection;
//2. Constructor (GUI)
public Client(String host) { //host=IP address of server
super("Mick's Instant Messenger [CLIENT]");
serverIP = host; //placed here to allow access to private String ServerIP
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMessage(event.getActionCommand()); //For this to work, must build sendData Method
userText.setText(""); //resets userText back to blank, after message has been sent to allow new message(s)
}
}
);
add(userText, BorderLayout.SOUTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER); //allows you to scroll up and down when text outgrows chatWindow
chatWindow.setLineWrap(true); //wraps lines when they outgrow the panel width
chatWindow.setWrapStyleWord(true); //ensures that above line wrap occurs at word end
setSize(400, 320);
this.setLocationRelativeTo(null); //places frame in center of screen
setVisible(true);
}
//3. startRunning method
public void startRunning() {
try {
connectToServer(); //unlike Server, no need to wait for connections. This connects to one specific Server.
setupStreams();
whileChatting();
} catch (EOFException eofException) {
//Display timestamp for disconnection
showMessage("\n\n" + fullTimeStamp);
showMessage("\nConnection terminated by CLIENT! ");
} catch (IOException ioException) {
ioException.printStackTrace();
} finally {
closeCrap();
}
}
//4. Connect to Server
void connectToServer() throws IOException {
showMessage(" \n Attempting connection to SERVER... \n");
connection = new Socket(InetAddress.getByName(serverIP), 6789);//Server IP can be added later
showMessage(" Connected to: " + connection.getInetAddress().getHostName()); //displays IP Address of Server
}
//5. Setup streams to send and receive messages
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n Streams are now setup! \n");
}
//6. While chatting method
private void whileChatting() throws IOException {
//Display timestamp for connection
showMessage("\n" + fullTimeStamp);
ableToType(true);
String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
do {
try {
message = (String) input.readObject(); //read input, treat as String, store in message variable
showMessage("\n" + message);
} catch (ClassNotFoundException classNotfoundException) {
showMessage("\n I don't know that object type");
}
//***broken by timestamp?***
} while (!message.equalsIgnoreCase("SERVER " + "[" + timeStamp + "]" + ": " + "END")); //Conversation happens until Server inputs 'End'
}
//7. Close the streams and sockets
private void closeCrap() {
showMessage("\n\nClosing streams and sockets...");
ableToType(false);//disable typing feature when closing streams and sockets
try {
output.close();
input.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace(); //show error messages or exceptions
}
}
//8. Send Messages to Server
private void sendMessage(String message) {
try {
String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
output.writeObject("CLIENT" + " [" + timeStamp + "]" + ": " + message);
output.flush();
showMessage("\nCLIENT" + " [" + timeStamp + "]" + ": " + message);
} catch (IOException ioexception) {
chatWindow.append("\n Error: Message not sent!");
}
}
//9.change/update chatWindow
private void showMessage(final String m) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
chatWindow.setEditable(false); //disallows text editing in chatWindow
chatWindow.append(m); //appends text, which was passed in from above
}
}
);
}
//10. Lets user type
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userText.setEditable(tof); //passes in 'true'
}
}
);
}
}
检查这个问题,它将帮助您从主JFrame显示登录JFrame(您需要创建该框架)
考虑更改此代码
@Override
public void actionPerformed(ActionEvent e) {
this.setVisible(false);
new Client().setVisible(true);
}
为此:
@Override
public void actionPerformed(ActionEvent e) {
Client charlie = new Client("127.0.0.1"); //Server IP Address would be placed here, where not
localhost.charlie.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //ensures process closes when 'X' is clicked
charlie.setVisible(true);
charlie.startRunning();
}
替换这个
new Client("127.0.0.1").startRunning();
借
Thread t1 = new Thread(new Runnable() {
public void run(){
Client client = new Client("127.0.0.1");
client.startRunning();
}
});
t1.start();
谢谢你的回复。我已经在Eclipse中构建了一个登录表单(参见代码),但无法实现建议的方法。请参阅编辑的帖子。@user3029329很抱歉遗漏了一件事,客户端构造函数需要一个主机公共客户端(字符串主机)
,因此当您调用新客户端()
时,您应该执行新客户端(“此处主机”)
谢谢。当我输入“new Client().setVisible(true);”时,尽管Client()在同一个包中(请参阅我的源代码),但new Client()仍带有红色下划线。编译器说“构造函数客户端()未定义”。我可以运行表单,但当我单击按钮时,控制台会给出以下错误:线程“AWT-EventQueue-0”java.lang中出现异常。错误:未解决的编译问题:javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)中的javax.swing.AbstractButton$Handler.actionPerformed中未定义构造函数客户端()(AbstractButton.java:2341)…很抱歉,我不确定我是否理解您的最后一条评论。根据我所附的代码,我将如何实现您的建议?谢谢。@user3029329您如何将ip地址提供给客户端?再次感谢您的帮助。我尝试了此操作,但再次获得相同的结果,即客户端成功连接到服务器(根据服务器输出),但客户端只是一个灰色的无功能窗口,没有任何选项。奇怪的是,当我直接启动客户端时,这种情况不会发生。谢谢你的建议。我已经尝试过了,但同样的问题仍然存在。你这个天才!它与你的新线程建议配合使用。非常感谢。这个问题整天都在困扰我!!!你能解释为什么它有效吗?Y你在与GUI相同的线程中运行客户端,这就是GUI冻结(等待客户端)的原因。啊哈..我现在完全理解了。非常感谢你教我一些新东西。