簡易聊天程序教程(六)主窗口和聊天窗口

源代碼下載鏈接:http://download.csdn.net/detail/sky453589103/9514686

如果有什麼問題,歡迎留言。

主窗口用的是JList控件,在顯示了登陸的跟人信息之後,接下來就是好友的列表。

爲了方便以後拓展 ,我把好友的信息封裝在FriendInformation中,FriendInformation類的定義也很簡單的,都能看懂。


下面來逐步分析一下MainWin類:

MainWin中比較重要的是事件的監聽:

好友列表中的右鍵菜單的監聽:

		JMenuItem item = new JMenuItem("remove");
		item.addActionListener(new ActionListener () {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				RequestMessage request = new RequestMessage();
				request.setFrom(username);
				request.setTo(friendJList.getSelectedValue().getName());
				request.setCommand("remove a friend");
				try {
					PrintStream out = new PrintStream(getServer().getOutputStream());
					out.print(request.Format());
				} catch (IOException e) {

				}
			}
			
		});
		friendListPopupMenu.add(item);
在因爲我的右鍵菜單中只有一個選項,因此寫的很簡單,但是用來舉例,完全足夠了。當選中了這個選項之後,客戶端會生成刪除還有的請求報文發送給服務器端,服務器端hi執行這個動作,如果刪除成功,就返回刪除了之後的好友列表。


好友列表的選定模式應該是單選的,通過下面的函數來設定:

this.friendJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

好友列表的監聽操作:

		this.friendJList.addMouseListener(new MouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {
				// if mouse's right key click, the line will be selected.
				if (e.getButton() == 3) {
					friendJList.setSelectedIndex(friendJList.locationToIndex(e.getPoint()));
				}
				// getButton function's return value has three value.
				// 1 represent mouse's left key.
				// 3 represent mouse's right key.
				if (e.getButton() == 1 && e.getClickCount() >= 2) {
					// index of being double clicked line
					// int index = friendJList.getSelectedIndex();
					FriendInformation f = (FriendInformation) friendJList.getSelectedValue();
					// FriendInformation f = friendList.get(index);
					if (f.getStatus().equals("on")) {
						AddChatWin(f.getName());
					} else {
						JOptionPane.showMessageDialog(null, f.getName() + " is offline!", "message",
								JOptionPane.INFORMATION_MESSAGE);
					}
					friendJList.clearSelection();
				}
				else if (e.getButton() == 3 && friendJList.getSelectedIndex() >= 0) {
					friendListPopupMenu.show(e.getComponent(), e.getX(), e.getY());
				}

			}
		});

省略了的後面的三個函數可以不看,都是空的。

				if (e.getButton() == 3) {
					friendJList.setSelectedIndex(friendJList.locationToIndex(e.getPoint()));
				}

getButton函數會有三個返回值,1代表左鍵,2代表中鍵,3代表右鍵。

這段代碼,實現的是,如果是右擊一行,這一行也會被選中。

接下來判斷的

1.是不是左鍵雙擊了某一行。如果是,就創建響應的聊天窗口,如果聊天窗口存在就將它顯示出來。

2.是不是右鍵單擊了某一行,如果是,就彈出右鍵菜單。

自定義JList的渲染模式, 需要調用setCellRenderer函數纔會生效:

class FriendJListRenderer extends JPanel implements ListCellRenderer<FriendInformation> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JLabel lbIcon = new JLabel();
	private JLabel lbName = new JLabel();
	private JLabel lbStatus = new JLabel();

	public FriendJListRenderer() {
		setLayout(new BorderLayout(5, 5));

		JPanel panelText = new JPanel(new GridLayout(0, 1));
		panelText.add(lbName);
		panelText.add(lbStatus);
		add(lbIcon, BorderLayout.WEST);
		add(panelText, BorderLayout.CENTER);
	}

	@Override
	public Component getListCellRendererComponent(JList<? extends FriendInformation> list, FriendInformation friend,
			int index, boolean isSelected, boolean cellHasFocus) {
		ImageIcon icon = new ImageIcon(getClass().getResource("/SimpleChat/Mushroom2.png"));
		lbIcon.setIcon(icon);
		// lbIcon.setText("this is a icon \r\n but not show by List\r\n
		// error?");
		lbName.setText(friend.getName());
		lbStatus.setText(friend.getStatus());
		lbStatus.setForeground(Color.blue);

		// set Opaque to change background color of JLabel
		lbName.setOpaque(true);
		lbStatus.setOpaque(true);
		lbIcon.setOpaque(true);

		// when select item
		if (isSelected) {
			lbName.setBackground(list.getSelectionBackground());
			lbStatus.setBackground(list.getSelectionBackground());
			lbIcon.setBackground(list.getSelectionBackground());
			setBackground(list.getSelectionBackground());
		} else { // when don't select
			lbName.setBackground(list.getBackground());
			lbStatus.setBackground(list.getBackground());
			lbIcon.setBackground(list.getBackground());
			setBackground(list.getBackground());
		}
		return this;
	}
}


添加好友的按鈕的事件監聽:

在按下添加好友的按鈕之後會先出現一個帶輸入框的窗口,在輸入了要添加的好友的名字之後,就可以執行添加好友的操作。

		addFriendButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// String inputValue = JOptionPane.showInputDialog(this, "Please
				// input a name");
				String inputValue = JOptionPane.showInputDialog(null,
						"Please input a name",
						"add a new friend",
						JOptionPane.CLOSED_OPTION);
				if (!inputValue.equals("")) {
					RequestMessage request = new RequestMessage();
					request.setFrom(username);
					request.setTo(inputValue);
					request.setCommand("add a friend");

					try {
						PrintStream out = new PrintStream(getServer().getOutputStream());
						out.print(request.Format());
					} catch (IOException e) {

					}
				}
			}

		});


需要注意的是,在登陸操作之後,所有的來自服務器的響應的消息都會在startn函數中接收,然後根據響應消息的code和description做出響應的處理。因爲篇幅原因,這不在展開了。

而聊天窗口中,負責的只是消息文本的添加和發送,接收信息的四級操作是在主窗口中進行的。因爲在這樣做可以避免同時有多個流在監聽輸入,而造成混亂。

聊天窗口在接收到對方的信息的時候,會加上當前的系統時間,通過下面代碼實現:

	public void addMessage(String from, String content) {
		Date date = new Date();
		messageTextArea.setText(
				messageTextArea.getText() + "\r\n" + from + "    " + dateFormat.format(date) + "\r\n" + content);

	}
通過Date類來獲取當前的系統時間,並格式化消息,添加到消息文本框中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章