我一直在尝试为计算机中的帧之间的端到端消息传输创建聊天程序。但不知何故它不起作用。没有错误或警告。我一直在摸着头大约2个小时。用户界面和其他组件工作正常,我无法在互联网上找到任何答案。 有一个客户端脚本。
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
class ChatClient extends JFrame implements ActionListener,FocusListener{
JButton button;
JLabel label;
JTextField text;
Socket socket;
String hostname = "localhost";
final int portno = 3000;
PrintWriter out;
BufferedReader bin;
int y=10;
String defaultMessage = "Enter your message..";
public ChatClient(){
try{
makeUI();
socket = new Socket(hostname,portno);
out = new PrintWriter(socket.getOutputStream());
bin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new ClientThread().start();
}catch(Exception ae){
System.out.println("Error! --> "+ae.getMessage());
}
}
public void makeUI(){
setTitle("FIreFly-Client");
text = new JTextField(defaultMessage);
text.setBounds(10,620,295,40);
text.addFocusListener(this);
add(text);
button = new JButton("SEND");
button.setBounds(310,620,80,40);
button.setForeground(Color.WHITE);
button.setBackground(Color.decode("#11A458"));
button.setFocusPainted(false);
button.addActionListener(this);
add(button);
setSize(400,700);
setLayout(null);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void focusGained(FocusEvent ae){
if(text.getText().equals(defaultMessage)){
text.setText("");
}
}
public void focusLost(FocusEvent ae){
if(text.getText().isEmpty()){
text.setText(defaultMessage);
}
}
public void actionPerformed(ActionEvent ae){
if(!text.getText().isEmpty()){
if(!text.getText().equals(defaultMessage)){
out.println(text.getText());
label = new JLabel(text.getText());
label.setBounds(10,y,380,20);
y = y+20;
add(label);
revalidate();
repaint();
}
}
}
public static void main(String []args){
try{
new ChatClient();
}catch(Exception ae){
System.out.println("Error! --> "+ae.getMessage());
}
}
class ClientThread extends Thread{
public void run(){
String receive;
try{
while(true){
receive = bin.readLine();
if(!receive.isEmpty()){
System.out.println(receive);
label = new JLabel(receive);
label.setBounds(10,y,380,20);
y = y+20;
label.setHorizontalAlignment(SwingConstants.RIGHT);
add(label);
revalidate();
repaint();
}
}
}catch(Exception ae){
ae.printStackTrace();
}
}
}
}
程序的服务器部分看起来像,
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
class ChatServer extends JFrame implements ActionListener,FocusListener{
JButton button;
JLabel label;
JTextField text;
Socket socket;
ServerSocket ss;
String hostname = "localhost";
final int portno = 3000;
PrintWriter out;
BufferedReader bin;
int y=10;
String defaultMessage = "Enter your message..";
public ChatServer(){
try{
makeUI();
ss = new ServerSocket(portno);
socket = ss.accept();
out = new PrintWriter(socket.getOutputStream());
bin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new ServerThread().start();
}catch(Exception ae){
System.out.println("Error! --> "+ae.getMessage());
}
}
public void makeUI(){
setTitle("FireFly-Server");
text = new JTextField(defaultMessage);
text.setBounds(10,620,295,40);
text.addFocusListener(this);
add(text);
button = new JButton("SEND");
button.setBounds(310,620,80,40);
button.setForeground(Color.WHITE);
button.setBackground(Color.decode("#11A458"));
button.setFocusPainted(false);
button.addActionListener(this);
add(button);
setSize(400,700);
setLayout(null);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void focusGained(FocusEvent ae){
if(text.getText().equals(defaultMessage)){
text.setText("");
}
}
public void focusLost(FocusEvent ae){
if(text.getText().isEmpty()){
text.setText(defaultMessage);
}
}
public void actionPerformed(ActionEvent ae){
if(!text.getText().isEmpty()){
if(!text.getText().equals(defaultMessage)){
System.out.println(text.getText());
out.println(text.getText());
label = new JLabel(text.getText());
label.setBounds(10,y,380,20);
y = y+20;
add(label);
revalidate();
repaint();
}
}
}
public static void main(String []args){
try{
new ChatServer();
}catch(Exception ae){
System.out.println("Error! --> "+ae.getMessage());
}
}
class ServerThread extends Thread{
public void run(){
String receive;
try{
while(true){
receive = bin.readLine();
if(!receive.isEmpty()){
System.out.println(receive);
label = new JLabel(receive);
label.setBounds(10,y,380,20);
y = y+20;
label.setHorizontalAlignment(SwingConstants.RIGHT);
add(label);
revalidate();
repaint();
}
}
}catch(Exception ae){
ae.printStackTrace();
}
}
}
}
有人可以告诉我它有什么问题吗?
答案 0 :(得分:1)
您需要在调用println后刷新输出流,否则它将位于输出流缓冲区中,并且永远不会被发送。
out.println(text.getText());
out.flush(); // add this
将刷新添加到两个程序中。
客户端gui可能看起来像:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
@SuppressWarnings("serial")
public class ChatClient2 extends JPanel {
private static final int VIS_ROW_CNT = 25;
private static final String HOST_NAME = "localhost";
private static final int PORT_NO = 3000;
private DefaultListModel<String> listModel = new DefaultListModel<>();
private JList<String> jList = new JList<>(listModel);
private SendAction sendAction = new SendAction("Send");
private JButton sendButton = new JButton(sendAction);
private JTextField textField = new JTextField(20);
private PrintWriter out;
public ChatClient2(Socket socket) throws IOException {
out = new PrintWriter(socket.getOutputStream());
SocketWorker worker = new SocketWorker(socket);
worker.addPropertyChangeListener(new WorkerListener());
worker.execute();
jList.setPrototypeCellValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
jList.setVisibleRowCount(VIS_ROW_CNT);
JScrollPane scrollPane = new JScrollPane(jList);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
textField.setAction(sendAction);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
bottomPanel.add(textField);
bottomPanel.add(sendButton);
setLayout(new BorderLayout());
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
public void lineToGui(String line) {
listModel.addElement(line);
}
private class SendAction extends AbstractAction {
public SendAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
if (!text.trim().isEmpty()) {
out.println(text);
out.flush();
lineToGui("Me: " + text);
}
textField.selectAll();
textField.requestFocusInWindow();
}
}
private class SocketWorker extends SwingWorker<Void, String> {
private BufferedReader bin;
public SocketWorker(Socket socket) throws IOException {
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
bin = new BufferedReader(isr);
}
@Override
protected Void doInBackground() throws Exception {
String line = null;
while ((line = bin.readLine()) != null) {
publish(line);
}
return null;
}
@Override
protected void process(List<String> chunks) {
for (String line : chunks) {
lineToGui("Server: " + line);
}
}
}
private class WorkerListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
@SuppressWarnings("rawtypes")
SwingWorker worker = (SwingWorker) evt.getSource();
try {
worker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
try {
Socket socket = new Socket(HOST_NAME, PORT_NO);
SwingUtilities.invokeLater(() -> createAndShowGui(socket));
} catch (IOException e) {
e.printStackTrace();
}
}
private static void createAndShowGui(Socket socket) {
ChatClient2 mainPanel = null;
try {
mainPanel = new ChatClient2(socket);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("ChatClient2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
答案 1 :(得分:0)
您应该使用EDT(事件调度线程)来更新UI,如下所示:
SwingUtilities.invokeLater(() -> {
label = new JLabel(receive);
label.setBounds(10,y,380,20);
y = y+20;
label.setHorizontalAlignment(SwingConstants.RIGHT);
add(label);
revalidate();
repaint();
});
在客户端和服务器端。希望这可以解决您的问题(虽然奇怪的是这不会导致异常)。