Java模擬qq軟件的詳細過程
**之前在封裝代碼后出現(xiàn)了問題,按照最初的寫法,在登陸完畢后彈出聊天界面后會卡死,原因是當時登陸界面和聊天界面都是使用的主線程,我的代碼沒有寫其他線程,無法多線程運行,因此在彈出聊天界面時線程不夠用了,就卡在了監(jiān)聽線程里,因為在監(jiān)聽線程中再有新的監(jiān)聽就會被卡住
在宇哥的指點下,將啟動服務器和客戶端的部分改為線程,就解決了此問題。改善后的代碼簡練和清晰了很多,更方便大家參考,代碼如下:
**
登陸界面的實現(xiàn)
登陸界面主要使用了JFrame,以及相關的一些組件,并且在界面中加上監(jiān)聽
登陸界面效果圖
登陸界面代碼Login類
package com.lding.net; import javax.swing.*; import java.awt.*; /** * @program: Chat * @description: * @author: 王丁 * @date: 2021-09-26 08:58 **/ public class Login{ JTextField jTextField; public static void main(String[] args){ Login login = new Login (); login.showUI ("kk"); } public void showUI(String str){ JFrame jf = new JFrame (); jf.setTitle ("❤️DDqq登陸界面❤️"); jf.setSize (500, 400); jf.setDefaultCloseOperation (3); jf.setLocationRelativeTo (null); jf.setResizable (false); FlowLayout fl = new FlowLayout (FlowLayout.CENTER, 5, 5); jf.setLayout (fl); Dimension dim1 = new Dimension (500, 200);//圖片大小 Dimension dim2 = new Dimension (100, 50);//標簽大小 Dimension dim3 = new Dimension (300, 30);//輸入框大小 Dimension dim4 = new Dimension (100, 40);//按鈕大小 ImageIcon icon = new ImageIcon ("source/Login1.jpg"); JLabel labimg = new JLabel (icon); labimg.setPreferredSize (dim1); jf.add (labimg); JLabel labuser = new JLabel (); labuser.setText ("user:"); labuser.setPreferredSize (dim2); jf.add (labuser); JTextField textuser = new JTextField (); textuser.setPreferredSize (dim3); jf.add (textuser); JLabel labpassword = new JLabel (); labpassword.setText ("password:"); labpassword.setPreferredSize (dim2); jf.add (labpassword); JPasswordField textPassword = new JPasswordField (); textPassword.setPreferredSize (dim3); jf.add (textPassword); JButton button = new JButton (); button.setBorder (BorderFactory.createRaisedBevelBorder ()); button.setText ("login"); button.setPreferredSize (dim4); jf.add (button); jf.setVisible (true); LoginListener ll = new LoginListener(textuser,textPassword, jf); button.addActionListener (ll); this.jTextField=ll.jTextField; } }
login的監(jiān)聽類 LoginListener
package com.lding.net; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @program: Chat * @description: * @author: 王丁 * @date: 2021-09-26 08:59 **/ public class LoginListener implements ActionListener { JTextField jTextField; JPasswordField jPasswordField; JFrame jf ; LoginListener( JTextField jTextField,JPasswordField jPasswordField,JFrame jf){ this.jf=jf; this.jTextField = jTextField; this.jPasswordField = jPasswordField; } @Override public void actionPerformed(ActionEvent e){ if(jTextField.getText().equals("Alice")&&String.valueOf(jPasswordField.getPassword()).equals("1234")){ System.out.println ("服務端登錄??!"); String name =jTextField.getText(); new Server(name).start(); jf.dispose(); }else if(jTextField.getText().equals("Lding")&&String.valueOf(jPasswordField.getPassword()).equals("1234")){ String name =jTextField.getText(); System.out.println ("客戶端登錄?。?); new Client(name).start(); jf.dispose(); } } }
在登陸完畢后,需要跳轉到聊天界面,這里采用的方法是通過一個flag標志來判斷是否登陸完畢,當?shù)顷懲戤吅?,會?chuàng)建新的聊天界面,并且登陸頁面會被關閉
依然是雙端通信,假定一端為客戶端,一端為服務端,其實兩端都可為用戶。
聊天界面運行圖
先登陸Alice的賬號 密碼為123456
登陸成功后顯示ok,并等待連接
再登陸冷丁的賬號,密碼為123456
當lding賬號登陸成功后完成連接,這時候會彈出兩個新的JFram窗口,為聊天見面
隨后可以發(fā)送消息,消息可以實時顯示時間,并顯示用戶名
一方發(fā)送的消息會在另一方的窗口上實時顯示出來
Client類代碼
package com.lding.net; import com.lding.ui.MsgUI; import javax.swing.*; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; /** * @program: Chat * @description: 客戶端 * @author: 王丁 * @date: 2021-09-26 08:58 **/ public class Client extends Thread{ String name; public Client(String name) { this.name=name; } public static void main(String[] args) { String port="客戶端"; Login login=new Login(); login.showUI(port); } @Override public void run(){ try { startClient(); } catch (IOException e) { e.printStackTrace (); } } void startClient() throws IOException{ Socket socket=new Socket("127.0.0.1",8888); //輸入 輸出流對象 InputStream inputStream=socket.getInputStream(); OutputStream outputStream=socket.getOutputStream(); MsgUI msgUI=new MsgUI(outputStream,name); JTextPane showmsgpane=msgUI.initUI("客戶端"); outputStream.flush(); int count=1; while(true){ int msglenth=inputStream.read(); System.out.println("消息長度:"+msglenth); byte[] msgbytes=new byte[msglenth]; //將接下來的數(shù)據(jù)讀入字節(jié)數(shù)組中 inputStream.read(msgbytes); count++; if(count%2==0){ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式 String date = df.format(new Date());// new Date()為獲取當前系統(tǒng)時間,也可使用當前時間戳 String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+date+" ["+getmsg+"]"+"說:"+"\n"); }else{ String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+getmsg+"\n"); } } } }
Server代碼
package com.lding.net; import com.lding.ui.MsgUI; import javax.swing.*; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; /** * @program: Chat * @description: * @author: 王丁 * @date: 2021-09-26 08:58 **/ public class Server extends Thread{ JTextField jTextField; String name; public Server(String name){ this.name=name; } public static void main(String[] args) { String port="服務端"; Login login=new Login(); login.showUI(port); } @Override public void run(){ try { startServer(); } catch (IOException e) { e.printStackTrace (); } } void startServer() throws IOException{ ServerSocket serverSocket=new ServerSocket(8888); System.out.println("等待連接?。?); Socket clientsocket=serverSocket.accept();//監(jiān)聽連接 System.out.println("連接成功??!"); InputStream inputStream=clientsocket.getInputStream(); OutputStream outputStream=clientsocket.getOutputStream(); MsgUI msgUI=new MsgUI(outputStream,name); JTextPane showmsgpane=msgUI.initUI("服務端"); //outputStream.flush(); int count=1; while(true){ int msglenth=inputStream.read(); System.out.println("消息長度是:"+msglenth); byte[] msgbytes=new byte[msglenth]; //將接下來的數(shù)據(jù)讀入字節(jié)數(shù)組中 inputStream.read(msgbytes); count++; if(count%2==0){ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式 String date = df.format(new Date());// new Date()為獲取當前系統(tǒng)時間,也可使用當前時間戳 String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+date+" ["+getmsg+"]"+"說:"+"\n"); }else{ String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+getmsg+"\n"); } } } }
登陸界面代碼
MsgUI
package com.lding.ui; import javax.swing.*; import java.awt.*; import java.io.OutputStream; /** * @program: Chat * @description: * @author: 王丁 * @date: 2021-09-26 08:59 **/ public class MsgUI extends JFrame { OutputStream outputStream; String name; public MsgUI(OutputStream outputStream,String name){ this.outputStream=outputStream; this.name=name; } public JTextPane initUI(String title){ setTitle(title); setSize(800,800); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLocationRelativeTo(null); setLayout(new FlowLayout()); //接收顯示框 JTextPane jtp=new JTextPane(); jtp.setPreferredSize(new Dimension(750,400)); JScrollPane jsp=new JScrollPane(jtp); jtp.getText(); Dimension dim=new Dimension(750,400);//按鈕大小 //發(fā)送框 JTextPane jtp1=new JTextPane(); jtp1.setPreferredSize(new Dimension(750,200)); JScrollPane jsp1=new JScrollPane(jtp1); JButton btn=new JButton("發(fā)送"); add(jsp); add(jsp1); add(btn); setVisible(true); MsgListener msgl=new MsgListener(jtp1,this.outputStream,name); btn.addActionListener(msgl); return jtp; } }
MsgUIListener
package com.lding.ui; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.OutputStream; /** * @program: Chat * @description: * @author: 王丁 * @date: 2021-09-26 09:00 **/ public class MsgListener implements ActionListener { JTextPane jtp; OutputStream outputStream; String name; public MsgListener(JTextPane jtp,OutputStream outputStream,String name){ this.jtp=jtp; this.outputStream=outputStream; this.name=name; } @Override public void actionPerformed(ActionEvent e) { byte[] names=this.name.getBytes(); try { outputStream.write(names.length); outputStream.write(names); outputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); } String msg=jtp.getText(); byte[] msgs=msg.getBytes(); try { outputStream.write(msgs.length); outputStream.write(msgs); outputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); } jtp.setText(null); } }
之后會豐富更多功能 敬請期待! 感謝您的觀看?。?!
到此這篇關于Java模擬qq軟件的詳細過程的文章就介紹到這了,更多相關Java 模擬 qq內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot中接收POST參數(shù)的幾種方式詳解
這篇文章主要介紹了SpringBoot中接收POST參數(shù)的幾種方式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06解決mybatis plus字段為null或空字符串無法保存到數(shù)據(jù)庫的問題
這篇文章主要介紹了解決mybatis plus字段為null或空字符串無法保存到數(shù)據(jù)庫的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02如何解決@PutMapping或@PostMapping接收String類型參數(shù)多兩個“引號問題
這篇文章主要介紹了如何解決@PutMapping或@PostMapping接收String類型參數(shù)多兩個“引號問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08