왜 이건 스레드가 아니냐고? 그냥 한번 스레드 적용안하고만들어봤는데 세상 편하더라 와......
서버와 연결된 모습
닉네임이나 UID가 없으니까 누가 무슨메시지 친지를 모르겠더라고 그래서 나아아~중에 추가해봐야지
서버가 꺼지면 연결된 클라 다 꺼짐
//input_widget.h
#ifndef INPUT_WIDGET_H
#define INPUT_WIDGET_H
#include <QDialog>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QTcpSocket>
#include <QHostAddress>
#include <QtNetwork>
#include <QtEvents>
#include <QMessageBox>
class InputDialog : public QDialog
{
Q_OBJECT
private:
//
//GUI 버튼
//
//IP 입력 부분
QSharedPointer<QLabel>ip_label;
QSharedPointer<QLineEdit>ip_edit;
QSharedPointer<QHBoxLayout>ip_layout;
//PORT 입력부분
QSharedPointer<QLabel>port_label;
QSharedPointer<QLineEdit>port_edit;
QSharedPointer<QHBoxLayout>port_layout;
//연결할지 말지 선택 버튼
QSharedPointer<QPushButton>connect_btn;
QSharedPointer<QPushButton>exit_btn;
QSharedPointer<QHBoxLayout>btn_layout;
//최종 레이아웃 설정
QSharedPointer<QVBoxLayout>layout;
//
QSharedPointer<QTcpSocket>tcp_socket;
//키눌림 이벤트 처리
virtual void keyPressEvent(QKeyEvent *);
public:
InputDialog(QSharedPointer<QTcpSocket>&,
QDialog* dialog = nullptr);
~InputDialog();
signals:
void Press_Enter();
public slots:
void Click_Connect_Btn();
void Click_Exit_Btn();
};
#endif // INPUT_WIDGET_H
//input_widget.cpp
#include "input_widget.h"
InputDialog::InputDialog(QSharedPointer<QTcpSocket>& tcp_socket,
QDialog* dialog)
:tcp_socket(tcp_socket)
{
//
//GUI 설정
//
//ip 입력 및 레이아웃 설정
ip_label.reset(new QLabel("연결할 IP "));
ip_edit.reset(new QLineEdit);
ip_layout.reset(new QHBoxLayout);
ip_layout->addWidget(ip_label.get());
ip_layout->addWidget(ip_edit.get());
//port입력 및 레이아웃 설정
port_label.reset(new QLabel("연결할 PORT"));
port_edit.reset(new QLineEdit);
port_layout.reset(new QHBoxLayout);
port_layout->addWidget(port_label.get());
port_layout->addWidget(port_edit.get());
//연결, 종료 버튼 및 레이아웃 설정
connect_btn.reset(new QPushButton("연결"));
exit_btn.reset(new QPushButton("종료"));
btn_layout.reset(new QHBoxLayout);
btn_layout->addWidget(connect_btn.get());
btn_layout->addWidget(exit_btn.get());
//최종 레이아웃 설정
layout.reset(new QVBoxLayout(this));
layout->addLayout(ip_layout.get());
layout->addLayout(port_layout.get());
layout->addLayout(btn_layout.get());
setLayout(layout.get());
//
//connect
//
//연결 버튼
connect(connect_btn.get(),&QPushButton::clicked,
this,&InputDialog::Click_Connect_Btn);
//Enter누르면 연결 버튼 누른거랑 똑같음
connect(this,SIGNAL(Press_Enter()),
this,SLOT(Click_Connect_Btn()));
//닫기 버튼
connect(exit_btn.get(),&QPushButton::clicked,
this,&InputDialog::Click_Exit_Btn);
}
InputDialog::~InputDialog(){}
void InputDialog::Click_Connect_Btn()
{
QString ip = ip_edit->text();
quint16 port = port_edit->text().toUShort();
tcp_socket->connectToHost(ip,port);
//10초동안 연결이 되길 기다린다.
if(!tcp_socket->waitForConnected(10000)){
QMessageBox::critical(this,
"Connect Error!",
tcp_socket->errorString());
exit(-1);
}
close();
}
void InputDialog::Click_Exit_Btn()
{
exit(-1);
}
void InputDialog::keyPressEvent(QKeyEvent* event)
{
Q_UNUSED(event);
switch(event->key())
{
case Qt::Key_Return:
emit(Press_Enter());
break;
}
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include "input_widget.h"
#include <QStringList>
#include <QStringListModel>
#include <QListView>
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
private:
//////////////GUI 부분///////////////////////
QSharedPointer<QStringListModel>chat_list_model;
QSharedPointer<QListView>chat_list_view;
QSharedPointer<QStringList>str_list;
QSharedPointer<QLineEdit>chat_edit;
QSharedPointer<QPushButton>send_btn;
QSharedPointer<QHBoxLayout>chat_send_line;
QSharedPointer<QVBoxLayout>layout;
////////////////////////////////////////////////
QSharedPointer<QTcpSocket>tcp_socket;
QSharedPointer<InputDialog>input_dialog;
virtual void keyPressEvent(QKeyEvent *event);
public:
Widget(QWidget *parent = nullptr);
~Widget();
signals:
void Press_Enter();
public slots:
void Click_Btn();
void Ready_Read();
void disconnected();
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//
//Network설정 및 다이얼로그 호출
//
//tcp_socket 할당
tcp_socket.reset(new QTcpSocket);
//Dialog 초기화 및 호출
input_dialog.reset(new InputDialog(tcp_socket));
input_dialog->exec();
//
//GUI 부분
//
//List View 부분
chat_list_model.reset(new QStringListModel);
chat_list_view.reset(new QListView(this));
chat_list_view->setModel(chat_list_model.get());
str_list.reset(new QStringList);
//Chat edit부분
chat_edit.reset(new QLineEdit);
send_btn.reset(new QPushButton("전송"));
chat_send_line.reset(new QHBoxLayout());
chat_send_line->addWidget(chat_edit.get());
chat_send_line->addWidget(send_btn.get());
//레이아웃
layout.reset(new QVBoxLayout(this));
layout->addWidget(chat_list_view.get());
layout->addLayout(chat_send_line.get());
setLayout(layout.get());
////////////////////////////////////////////////////
//전송 버튼 클릭하면 호출
connect(send_btn.get(),&QPushButton::clicked,
this,&Widget::Click_Btn);
//엔터키 누르면 호출
connect(this,SIGNAL(Press_Enter()),
this,SLOT(Click_Btn()));
//데이터 들어오면 호출
connect(tcp_socket.get(),SIGNAL(readyRead()),
this,SLOT(Ready_Read()));
connect(tcp_socket.get(),SIGNAL(disconnected()),
this,SLOT(disconnected()));
}
Widget::~Widget()
{
}
//전송 버튼 클릭하면 호출
//엔터키 누르면 호출
void Widget::Click_Btn()
{
QString message = chat_edit->text();
//예외가 일어나면 다시 보내기 쉽게 하기위해 setText를 위에 올려놓음
chat_edit->setText("");
tcp_socket->write(message.toStdString().c_str());
}
//데이터 들어오면 호출
void Widget::Ready_Read()
{
if(tcp_socket->bytesAvailable()>=0)
{
QByteArray array = tcp_socket->readAll();
*str_list<<array;
chat_list_model->setStringList(*str_list);
}
}
void Widget::disconnected()
{
QMessageBox::critical(this,
"Critical Error",
"서버와 연결이 끊겼습니다.");
tcp_socket->deleteLater();
close();
}
//
void Widget::keyPressEvent(QKeyEvent *event)
{
Q_UNUSED(event);
switch(event->key())
{
case Qt::Key_Return:
emit(Press_Enter());
break;
}
}
tcp_client_chat1.zip
0.01MB