Qt模仿QQ聊天窗口界面(一)
-
- Qt模仿QQ聊天窗口界面(一)
- 简述
- 效果图
- QQ的聊天窗口
- 我做的效果图
- 代码篇
- 结尾
- Qt模仿QQ聊天窗口界面(一)
简述
最近利用业余时间,模仿QQ做了一个聊天窗口界面,功能还不全,准备分几个部分做出来,还是看空闲时间了,以及广大网友的支持了。
效果图
QQ的聊天窗口
我做的效果图
代码篇
//TalkWindowShell.cpp
TalkWindowShell::TalkWindowShell(QWidget *parent): BasicWindow(parent)
{ui.setupUi(this);initControl();{TalkWindow* talkwindow1 = new TalkWindow(this);TalkWindowItem* talkwindowItem1 = new TalkWindowItem(talkwindow1);talkwindow1->setWindowName(QStringLiteral("雨田哥-工作号-1号"));talkwindowItem1->setMsgLabelContent(QStringLiteral("雨田哥-1号"));talkwindow1->setWindowSignName(QStringLiteral("欢迎吐槽、雨田哥-工作号-1号"));addTalkWindow(talkwindow1, talkwindowItem1);}{TalkWindow* talkwindow2 = new TalkWindow(this);TalkWindowItem* talkwindowItem2 = new TalkWindowItem(talkwindow2);talkwindow2->setWindowName(QStringLiteral("雨田哥-工作号-2号-2号"));talkwindowItem2->setMsgLabelContent(QStringLiteral("雨田哥-2号"));talkwindow2->setWindowSignName(QStringLiteral("欢迎吐槽、雨田哥-工作号-2号-2号"));addTalkWindow(talkwindow2, talkwindowItem2);}{TalkWindow* talkwindow3 = new TalkWindow(this);TalkWindowItem* talkwindowItem3 = new TalkWindowItem(talkwindow3);talkwindow3->setWindowName(QStringLiteral("雨田哥-工作号-3号-3号-3号"));talkwindowItem3->setMsgLabelContent(QStringLiteral("雨田哥-3号"));talkwindow3->setWindowSignName(QStringLiteral("欢迎吐槽、雨田哥-工作号-3号-3号-3号"));addTalkWindow(talkwindow3, talkwindowItem3);}
}TalkWindowShell::~TalkWindowShell()
{delete m_emotionWindow;m_emotionWindow = nullptr;
}void TalkWindowShell::initControl()
{loadStyleSheet("TalkWindow");m_emotionWindow = new EmotionWindow;m_emotionWindow->hide();QList<int> leftWidgetSize;leftWidgetSize << 154 << width() - 154;ui.splitter->setSizes(leftWidgetSize);ui.listWidget->setStyle(new CustomProxyStyle(this));connect(ui.listWidget, &QListWidget::itemClicked, this, &TalkWindowShell::onTalkWindowItemClicked);connect(m_emotionWindow, SIGNAL(signalEmotionItemClicked(int)), this, SLOT(onEmotionItemClicked(int)));
}void TalkWindowShell::onEmotionBtnClicked(bool)
{m_emotionWindow->setVisible(!m_emotionWindow->isVisible());QPoint emotionPoint = this->mapToGlobal(QPoint(0, 0));emotionPoint.setX(emotionPoint.x() + 170);emotionPoint.setY(emotionPoint.y() + 220);m_emotionWindow->move(emotionPoint);
}void TalkWindowShell::onTalkWindowItemClicked(QListWidgetItem *item)
{QWidget* talkwindowWidget = m_talkwindowItemMap.find(item).value();ui.rightStackedWidget->setCurrentWidget(talkwindowWidget);
}void TalkWindowShell::addTalkWindow(TalkWindow* talkwindow, TalkWindowItem* talkwindowitem)
{ui.rightStackedWidget->addWidget(talkwindow);connect(m_emotionWindow, SIGNAL(signalEmotionWindowHide()), talkwindow, SLOT(onSetEmotionBtnStatus()));QListWidgetItem *aItem = new QListWidgetItem(ui.listWidget);m_talkwindowItemMap.insert(aItem, talkwindow);aItem->setSelected(true);talkwindowitem->setHeadPixmap("");ui.listWidget->addItem(aItem);ui.listWidget->setItemWidget(aItem, talkwindowitem);onTalkWindowItemClicked(aItem);connect(talkwindowitem, &TalkWindowItem::signalCloseClicked, [talkwindowitem, talkwindow, aItem, this](){m_talkwindowItemMap.remove(aItem);talkwindow->close();ui.listWidget->takeItem(ui.listWidget->row(aItem));delete talkwindowitem;ui.rightStackedWidget->removeWidget(talkwindow);if (ui.rightStackedWidget->count() < 1)close();});
}void TalkWindowShell::onEmotionItemClicked(int emotionNum)
{TalkWindow* curTalkWindow = dynamic_cast<TalkWindow*>(ui.rightStackedWidget->currentWidget());if (curTalkWindow){curTalkWindow->addEmotionImage(emotionNum);}
}
TalkWindow.cpp
TalkWindow::TalkWindow(QWidget *parent): QWidget(parent)
{setAttribute(Qt::WA_DeleteOnClose);ui.setupUi(this);initControl();
}TalkWindow::~TalkWindow()
{}void TalkWindow::initControl()
{setSendBtnMenu();QList<int> rightWidgetSize;rightWidgetSize << 600 << 138;ui.bodySpliter->setSizes(rightWidgetSize);connect(ui.sysmin, SIGNAL(clicked(bool)), parent(), SLOT(onShowMin(bool)));connect(ui.sysclose, SIGNAL(clicked(bool)), parent(), SLOT(onShowClose(bool)));connect(ui.closeBtn, SIGNAL(clicked(bool)), parent(), SLOT(onShowClose(bool)));connect(ui.faceBtn, SIGNAL(clicked(bool)), parent(), SLOT(onEmotionBtnClicked(bool)));connect(ui.sendBtn, SIGNAL(clicked(bool)), this, SLOT(onSendBtnClicked(bool)));ui.msgWidget->setShowSkinControl(ui.skinLabel);
}void TalkWindow::onSetEmotionBtnStatus()
{ui.faceBtn->setChecked(false);
}void TalkWindow::setWindowName(const QString& name)
{ui.nameLabel->setText(name);
}void TalkWindow::setWindowSignName(const QString& name)
{ui.signLabel->setText(name);
}void TalkWindow::onSignalWindowclosed()
{close();
}void TalkWindow::onSendBtnClicked(bool)
{ui.textEdit->clear();ui.textEdit->delteAllEmotionImage();MsgWidgetItem* msgItem = new MsgWidgetItem(this);int count = ui.msgLayout->count();ui.msgLayout->insertWidget(count - 1, msgItem);
}void TalkWindow::addEmotionImage(int emotionNum)
{ui.textEdit->setFocus();ui.textEdit->addEmotionUrl(emotionNum);
}void TalkWindow::setSendBtnMenu()
{QMenu* menu = new QMenu(this);menu->setWindowFlags(menu->windowFlags() | Qt::FramelessWindowHint);menu->setAttribute(Qt::WA_TranslucentBackground);menu->setObjectName("senMenu");m_sendAction = menu->addAction(QStringLiteral("按Enter键,发送消息"), this, SLOT(onEnterAction()));m_ctrlSendAction = menu->addAction(QStringLiteral("按Enter+Ctrl键,发送消息"), this, SLOT(onEnterCtrlAction()));QActionGroup* actiongroup = new QActionGroup(this);m_sendAction->setCheckable(true);m_ctrlSendAction->setCheckable(true);m_sendAction->setChecked(true);actiongroup->addAction(m_sendAction);actiongroup->addAction(m_ctrlSendAction);ui.sendBtn->setMenu(menu);
}void TalkWindow::onEnterAction()
{m_sendAction->setChecked(true);}void TalkWindow::onEnterCtrlAction()
{m_ctrlSendAction->setChecked(true);
}
EmotionWindow.cpp
const int emotionColumn = 14;
const int emotionRow = std::ceil(170 / 14);EmotionWindow::EmotionWindow(QWidget *parent): QWidget(parent)
{setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow);setAttribute(Qt::WA_TranslucentBackground);setAttribute(Qt::WA_DeleteOnClose);ui.setupUi(this);initControl();
}EmotionWindow::~EmotionWindow()
{}void EmotionWindow::initControl()
{CommonUtils::loadStyleSheet(this, "EmotionWindow");for (int row = 0; row < emotionRow; row++){for (int column = 0; column < emotionColumn; column++){EmotionLabelItem* label = new EmotionLabelItem(this);label->setEmotionName(row * emotionColumn + column);connect(label, &EmotionLabelItem::emotionClicked, this, &EmotionWindow::addEmotion);ui.gridLayout->addWidget(label, row, column);}}
}void EmotionWindow::addEmotion(int emotionNum)
{hide();emit signalEmotionWindowHide();emit signalEmotionItemClicked(emotionNum);
}void EmotionWindow::paintEvent(QPaintEvent *event)
{QStyleOption opt;opt.init(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);__super::paintEvent(event);
}void EmotionWindow::showEvent(QShowEvent *event)
{setFocus();__super::showEvent(event);
}void EmotionWindow::focusOutEvent(QFocusEvent *event)
{QWidget* widget = qApp->widgetAt(QCursor::pos());if (widget != this && widget != ui.emotionWidget && widget != ui.topWidget){hide();emit signalEmotionWindowHide();}__super::focusOutEvent(event);
}
//QMsgTextEdit.cpp
QMsgTextEdit::QMsgTextEdit(QWidget *parent): QTextEdit(parent)
{}QMsgTextEdit::~QMsgTextEdit()
{delteAllEmotionImage();
}void QMsgTextEdit::delteAllEmotionImage()
{for (auto itor = m_emotionMap.constBegin(); itor != m_emotionMap.constEnd(); ++itor){delete itor.key();}m_emotionMap.clear();
}void QMsgTextEdit::addEmotionUrl(int emotionNum)
{const QString&& imageName = QString(":/TalkWindowShell/Resources/emotion/%1.png").arg(emotionNum);const QString&& flagName = QString("apng-%1-apng").arg(imageName);insertHtml(QString("<img src='%1'/>").arg(flagName));if (m_listEmotionUrl.contains(imageName))return;elsem_listEmotionUrl.append(imageName);QMovie* apngMovie = new QMovie(imageName, "apng", this);apngMovie->setCacheMode(QMovie::CacheNone);m_emotionMap.insert(apngMovie, flagName);connect(apngMovie, SIGNAL(frameChanged(int)), this, SLOT(onEmotionImageFrameChange(int)));apngMovie->start();
}void QMsgTextEdit::onEmotionImageFrameChange(int frame)
{QMovie* movie = qobject_cast<QMovie*>(sender());document()->addResource(QTextDocument::ImageResource, QUrl(m_emotionMap.value(movie)), movie->currentPixmap());setLineWrapColumnOrWidth(lineWrapColumnOrWidth());
}
结尾
其实,看代码篇,有点繁琐,因权限问题,我不能将工程文件上传,需要的,可以加我QQ。需要的可以加我QQ:3246214072。今天我只是先上传已做好的部分,后面看情况,会不断的完善这个聊天窗口界面。感谢广大网友的多多支持~