Qt如何寫一個三秒自動消失提示窗,適用於窗體和tableView中
#include <QDateTime>
#include "QTimer"
#include "QAbstractItemModel"
class QVBoxLayout;
class GlodonTableView;
class QModelIndex;
class QLabel;
class QPropertyAnimation;
class ToolTipParam
{
public:
ToolTipParam() :
m_sizeMinTip(80, 60),
m_sizeMaxTip(0, 0),
m_sizeArrow(19, 9),
m_nRowHeight(20),
m_nTimeFadeOut(1000),
m_nTimeRemain(3000),
m_fontText(QFont("Microsoft YaHei", 12, QFont::Normal)),
m_colorText(Qt::black),
m_sizeIcon(16, 16),
m_pParentWidget(NULL),
m_strIconPath("xxx.png"),
m_strText(QString(""))
{
}
ToolTipParam & operator = (const ToolTipParam & param)
{
m_strIconPath = param.m_strIconPath;
m_nRowHeight = param.m_nRowHeight;
m_strText = param.m_strText;
m_fontText = param.m_fontText;
m_colorText = param.m_colorText;
m_nTimeRemain = param.m_nTimeRemain;
m_nTimeFadeOut = param.m_nTimeFadeOut;
m_sizeArrow = param.m_sizeArrow;
m_sizeMinTip = param.m_sizeMinTip;
m_sizeMaxTip = param.m_sizeMaxTip;
m_sizeIcon = param.m_sizeIcon;
m_pParentWidget = param.m_pParentWidget;
return *this;
}
QString m_strIconPath; // 圖示路徑
QSize m_sizeIcon; // 圖示尺寸
QString m_strText; // 文字
QFont m_fontText; // 字型
QColor m_colorText; //文字顏色
int m_nRowHeight; // 文字行高
int m_nTimeRemain; // 停留時間(毫秒)
int m_nTimeFadeOut; // 淡出時間(毫秒)
QSize m_sizeArrow; // layout的外邊距
QSize m_sizeMinTip; // tip控制元件的大小
QSize m_sizeMaxTip; // tip的換行大小
QWidget *m_pParentWidget; // 被指向的widget(父窗體)
};
class ToolTipWidget : public QWidget
{
Q_OBJECT
public:
static void showToolTip(QWidget * pParent, const QString &strShowText); //使用時直接呼叫這個介面就可以
static void tableViewShowToolTip(QWidget *pTableView, const QModelIndex& oIndex, const QString& strShowText, bool bIsTableView = false); //tableView可以直接呼叫該靜態方法
static void closeTip(QWidget * pParent = nullptr); //關閉提示
virtual void ImmediateCloseTip(); // 立即關閉,並銷燬
virtual QPoint calcPosOfpParentWidget(); //
bool isStartFadeOut(); // 判斷是否開始漸變退出
void tipShowLocal(); //tip出現的位置,父窗體的上方
void startTimer(void); //
void initUI();
void initConnect();
QPainterPath buildRoundRectTip(); //畫圓角提示框
void stopTime();
~ToolTipWidget();
protected:
virtual void showEvent(QShowEvent * pEvent);
virtual void paintEvent(QPaintEvent * pEvent);
virtual void mouseReleaseEvent(QMouseEvent *pEvent);
virtual bool eventFilter(QObject *pObj, QEvent *pEvent);
virtual void enterEvent(QEvent *pEvent);
virtual void leaveEvent(QEvent *pEvent);
private:
explicit ToolTipWidget(ToolTipParam & oTipParam, QWidget *pParent = nullptr, const QModelIndex oIndex = QModelIndex(), bool bIsShowTotalQty = false);
protected slots:
void slotCloseTimer();
void slotFadeout();
void slotMoveTimer();
private:
static ToolTipParam m_TipParam;
QLabel *m_pLabelIco; // 圖示
QLabel *m_pLabelText; // 內容文字區
QVBoxLayout *m_pLayoutLeft;
QVBoxLayout *m_pLayoutRight;
QTimer *m_pTimerClose; // 關閉定時器
QTimer *m_pTimerMovePos; // 移動定時器
QPropertyAnimation *m_pAnimFadeOut; // 窗體逐漸消失效果
QPoint m_ptThisCenter;
bool m_bStartFadeOut;
static QDateTime m_CloseDataTime;
static QPointer<ToolTipWidget> m_QPointerTip;
QModelIndex m_oIndex;
bool m_bTableViewShow;
};
#include "QWidget"
#include "QRect"
#include "QBoxLayout"
#include "QLabel"
#include "QPropertyAnimation"
#include "QPainter"
#include "QLineEdit"
#include "QPointer"
#include "QApplication"
#include "QAbstractItemModel"
static const QString s_strLabelText = QString("<p style=\"line-height:%1px\">%2</p>");
QPointer<ToolTipWidget> ToolTipWidget::m_QPointerTip;
QDateTime ToolTipWidget::m_CloseDataTime = QDateTime::fromTime_t(0);
ToolTipParam ToolTipWidget::m_TipParam;
ToolTipWidget::ToolTipWidget(ToolTipParam & oTipParam, QWidget *pParent /*= nullptr*/,
const QModelIndex oIndex /*= QModelIndex()*/
, bool bIsShowTotalQty /*= false*/) :
m_pLabelIco(NULL),
m_pLabelText(NULL),
m_pTimerClose(NULL),
m_pAnimFadeOut(NULL),
m_bStartFadeOut(false),
m_oIndex(oIndex),
m_bTableViewShow(bIsShowTotalQty),
QWidget(pParent)
{
m_TipParam = oTipParam;
initUI();
installEventFilter(pParent);
initConnect();
}
ToolTipWidget::~ToolTipWidget()
{
}
void ToolTipWidget::mouseReleaseEvent(QMouseEvent *pEvent)
{
//點tip就直接讓它關了
if (pEvent->button() == Qt::LeftButton)
{
closeTip();
}
}
void ToolTipWidget::paintEvent(QPaintEvent * pEvent)
{
QWidget::paintEvent(pEvent);
if (!m_TipParam.m_pParentWidget)
return;
m_ptThisCenter = m_TipParam.m_pParentWidget->mapToGlobal(m_TipParam.m_pParentWidget->rect().center());
QPainterPath path;
// 畫圓角tip
path = this->buildRoundRectTip();
QPainter * painter = new QPainter(this);
painter->begin(this);
painter->setRenderHint(QPainter::Antialiasing); // 圓角處反鋸齒,讓其圓滑;
if (!m_bTableViewShow)
{
QColor c_CurColor = QColor(QString("255 255 255 255"));
painter->setPen(QPen(c_CurColor, 1, Qt::SolidLine));
painter->fillPath(path, QBrush(c_CurColor));
}
else
{
this->move(calcPosOfpParentWidget());
painter->setPen(QPen(QColor(199, 199, 199), 1, Qt::SolidLine));
painter->fillPath(path, QBrush(QColor(231, 231, 231)));
}
painter->drawPath(path);
painter->end();
}
bool ToolTipWidget::eventFilter(QObject *pObj, QEvent *pEvent)
{
auto eType = pEvent->type();
if (eType == QEvent::Resize
|| eType == QEvent::WindowStateChange
|| eType == QEvent::Move
|| eType == QEvent::ParentChange
|| eType == QEvent::Paint
|| eType == QEvent::DragMove)
{
this->show();
this->update();
}
if (eType == QEvent::Hide)
{
this->hide();
}
if (eType == QEvent::Resize)
{
tipShowLocal();
}
if (eType == QEvent::Move)
{
tipShowLocal();
}
// 錯誤提示所在的控制元件隱藏時,錯誤提示直接銷燬
if (pObj == m_TipParam.m_pParentWidget)
{
if (pEvent->type() == QEvent::Hide)
ImmediateCloseTip();
}
return QWidget::eventFilter(pObj, pEvent);
}
void ToolTipWidget::enterEvent(QEvent *pEvent)
{
if (m_pTimerClose) //滑鼠懸停停止計時,窗體不消失
{
m_pTimerClose->stop();
}
QWidget::enterEvent(pEvent);
}
void ToolTipWidget::leaveEvent(QEvent *pEvent)
{
if (m_pTimerClose) //滑鼠離開重新計時
{
m_pTimerClose->start(m_TipParam.m_nTimeRemain);
}
QWidget::leaveEvent(pEvent);
}
void ToolTipWidget::showEvent(QShowEvent * pEvent)
{
if (!m_TipParam.m_pParentWidget)
return;
if (!m_TipParam.m_sizeMinTip.isEmpty())
this->setMinimumSize(m_TipParam.m_sizeMinTip);
if (!m_TipParam.m_sizeMaxTip.isEmpty())
this->setMaximumSize(m_TipParam.m_sizeMaxTip);
QString strTemp = m_TipParam.m_strText;
QString sBody = s_strLabelText.arg(m_TipParam.m_nRowHeight).arg(m_TipParam.m_strText);
m_pLabelText->setText(sBody);
int nTitleWidth = m_pLabelText->fontMetrics().width(strTemp);
if (nTitleWidth < (this->maximumWidth() - 100))
{
m_pLayoutRight->setContentsMargins(0, 4, 15, 12);
m_pLabelText->setWordWrap(false);
m_pLabelText->adjustSize();
if (!m_bTableViewShow)
{
this->setFixedSize(m_pLabelText->width(), m_pLabelText->height() );
}
else
{
this->setFixedSize(m_pLabelText->width() , m_pLabelText->height());
}
}
else
{
m_pLayoutLeft->setContentsMargins(0, 2, 0, 0);
m_pLayoutRight->setContentsMargins(0, 4, 15, 12);
m_pLabelText->setMinimumWidth(this->maximumWidth());
this->setMinimumWidth(this->maximumWidth() );
m_pLabelText->adjustSize();
if (m_pLabelText->size().height() > 60)
{
adjustSize();
}
else
{
if (!m_bTableViewShow)
{
this->setFixedSize(m_pLabelText->width(), m_pLabelText->height());
}
else
{
this->setFixedSize(m_pLabelText->width(), m_pLabelText->height());
}
}
}
if (!m_bTableViewShow)
{
QPixmap pixIco;
pixIco.load(m_TipParam.m_strIconPath);
if (!m_TipParam.m_sizeIcon.isEmpty())
{
pixIco = pixIco.scaled(m_TipParam.m_sizeIcon.width(), m_TipParam.m_sizeIcon.height(), Qt::KeepAspectRatio);
}
m_pLabelIco->setPixmap(pixIco);
}
QWidget::showEvent(pEvent);
}
QPainterPath ToolTipWidget::buildRoundRectTip()
{
QPainterPath oPath;
if (!m_TipParam.m_sizeArrow.isValid() || !m_TipParam.m_pParentWidget)
{
return oPath;
}
int nHeight = m_TipParam.m_sizeArrow.height();
QRect oOuterRect = this->rect();
QRect oInnerRect;
if (!m_bTableViewShow)
{
oInnerRect = oOuterRect - QMargins(nHeight, nHeight, nHeight, nHeight);
oPath.addRoundedRect(oInnerRect, 5, 5); // 新增圓角矩形
}
else
{
oInnerRect = oOuterRect - QMargins(nHeight, nHeight, nHeight, nHeight + 10);
oPath.addRoundedRect(oInnerRect, 0, 0);
}
return oPath;
}
void ToolTipWidget::stopTime()
{
if (m_pTimerClose)
m_pTimerClose->stop();
if (m_pTimerMovePos)
m_pTimerMovePos->stop();
m_CloseDataTime = QDateTime::currentDateTime();
this->close();
this->deleteLater();
}
void ToolTipWidget::slotCloseTimer()
{
m_pTimerClose->stop();
m_bStartFadeOut = true;
m_pAnimFadeOut->start();
}
void ToolTipWidget::slotMoveTimer()
{
QPoint ptThisCenter = m_TipParam.m_pParentWidget->mapToGlobal(m_TipParam.m_pParentWidget->rect().center());
if (ptThisCenter != m_ptThisCenter)
{
stopTime();
}
}
void ToolTipWidget::slotFadeout()
{
if (m_pTimerMovePos)
m_pTimerMovePos->stop();
this->close();
this->deleteLater();
}
void ToolTipWidget::ImmediateCloseTip()
{
this->stopTime();
}
QPoint ToolTipWidget::calcPosOfpParentWidget()
{
QPoint pt(0, 0);
if (!m_TipParam.m_pParentWidget)
return pt;
int nCounWidth = m_TipParam.m_pParentWidget->width()*0.5;//當前單元格的列寬
int nTooltipHeight = -this->height()* 0.5 ; //提示框的高度
QPoint ptGlobalOwnerCenter = m_TipParam.m_pParentWidget->mapToGlobal(m_TipParam.m_pParentWidget->rect().center());
pt = QPoint(ptGlobalOwnerCenter.x(), ptGlobalOwnerCenter.y());
pt += QPoint(nCounWidth, nTooltipHeight);
return pt;
}
void ToolTipWidget::showToolTip(QWidget * pParentWidget, const QString &strText)
{
ToolTipWidget * pTip = NULL;
assert(pParentWidget);
if (!pParentWidget)
return;
if (!m_QPointerTip.isNull() && m_QPointerTip.data() && pParentWidget == m_QPointerTip.data()->parent()
&& strText.compare(m_TipParam.m_strText) == 0
&& !m_QPointerTip->isStartFadeOut())
{
//窗體還沒有退出直接使用原來的
return;
}
__int64 llDuration = m_CloseDataTime.msecsTo(QDateTime::currentDateTime()); //第一次與第二次彈出窗體的間隔時間
if (llDuration < 500)
{
pTip = ToolTipWidget::m_QPointerTip;
return;
}
if (!ToolTipWidget::m_QPointerTip.isNull())
{
ToolTipWidget::m_QPointerTip->ImmediateCloseTip();
}
ToolTipParam param = m_TipParam;
param.m_pParentWidget = pParentWidget;
param.m_strText = strText;
pTip = new ToolTipWidget(param, pParentWidget);
ToolTipWidget::m_QPointerTip = pTip;
pTip->tipShowLocal();
pTip->show();
pTip->startTimer(); //show之後啟動定時器
}
void ToolTipWidget::startTimer(void)
{
if (!m_TipParam.m_pParentWidget)
{
return;
}
m_pAnimFadeOut->setDuration(m_TipParam.m_nTimeFadeOut);
if (m_pTimerClose)
{
m_pTimerClose->start(m_TipParam.m_nTimeRemain);
}
if (m_pTimerMovePos)
{
m_pTimerMovePos->start();
}
}
//對應的單元格
void ToolTipWidget::tableViewShowToolTip(QWidget *editor, const QModelIndex& oIndex, const QString& strTotalQtyExpr, bool bIsShowTotalQtyExpr/*=false*/)
{
if (editor == nullptr || !oIndex.isValid())
return;
ToolTipWidget * pTip = NULL;
if (!m_QPointerTip.isNull() && m_QPointerTip.data() && editor == m_QPointerTip.data()->parent()
&& strTotalQtyExpr.compare(m_TipParam.m_strText) == 0
&& !m_QPointerTip->isStartFadeOut())
{
//文字相同、父窗體相同、窗體還沒有退出直接使用原來的。
return;
}
__int64 llDuration = m_CloseDataTime.msecsTo(QDateTime::currentDateTime()); //第一次與第二次彈出窗體的間隔時間
if (llDuration < 100)
{
pTip = ToolTipWidget::m_QPointerTip;
return;
}
if (!ToolTipWidget::m_QPointerTip.isNull())
{
ToolTipWidget::m_QPointerTip->ImmediateCloseTip();
}
ToolTipParam param = m_TipParam;
param.m_colorText = QColor(100, 100, 100, 0);
param.m_pParentWidget = editor;
param.m_strText = strTotalQtyExpr;
pTip = new ToolTipWidget(param, editor, oIndex, bIsShowTotalQtyExpr);
ToolTipWidget::m_QPointerTip = pTip;
pTip->show();
pTip->startTimer(); //show之後啟動定時器
}
void ToolTipWidget::closeTip(QWidget * pParent)
{
if (!ToolTipWidget::m_QPointerTip.isNull())
{
//傳進來的父不為空,且不是當前氣泡的父時,不關閉當前氣泡
if (pParent && pParent != ToolTipWidget::m_QPointerTip.data()->parent())
return;
ToolTipWidget::m_QPointerTip->ImmediateCloseTip();
}
}
void ToolTipWidget::tipShowLocal()
{
QWidget* pParentWidget = this->parentWidget();
QSize oSzParentWidget = pParentWidget->size();
int nParentWidgetX = oSzParentWidget.width();
int nParentWidgetY = oSzParentWidget.height();
QPoint oPtRightBottomParentWidget = pParentWidget->mapToGlobal(QPoint(nParentWidgetX, nParentWidgetY));
//獲取父窗體的左下角座標
QPoint oPtLeftBottom = oPtRightBottomParentWidget - QPoint(oSzParentWidget.width(), 0);
int nLeftBottomX = oPtLeftBottom.x();
int nLeftBottomY = oPtLeftBottom.y();
//移動到父窗體的頂上中部的位置
int nTipWidth = this->width();
nLeftBottomX = nLeftBottomX + nParentWidgetX / 2 - nTipWidth;
nLeftBottomY = nLeftBottomY - nParentWidgetY - 2;
this->move(nLeftBottomX, nLeftBottomY);
}
bool ToolTipWidget::isStartFadeOut()
{
return m_bStartFadeOut;
}
void ToolTipWidget::initUI()
{
this->setMaximumHeight(25);
this->setWindowFlags(Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint | Qt::ToolTip);
this->setAttribute(Qt::WA_TranslucentBackground);
QVBoxLayout * layoutMain = new QVBoxLayout();
layoutMain->setSpacing(0);
if (m_bTableViewShow)
{
layoutMain->setContentsMargins(m_TipParam.m_sizeArrow.height(),
m_TipParam.m_sizeArrow.height(),
m_TipParam.m_sizeArrow.height(),
m_TipParam.m_sizeArrow.height());
this->setLayout(layoutMain);
}
else
{
layoutMain->setContentsMargins(m_TipParam.m_sizeArrow.height() + 12,
m_TipParam.m_sizeArrow.height() + 8,
m_TipParam.m_sizeArrow.height() + 8,
m_TipParam.m_sizeArrow.height());
}
this->setLayout(layoutMain);
QHBoxLayout * layoutContent = new QHBoxLayout();
layoutContent->setSpacing(6);
layoutMain->addLayout(layoutContent);
m_pLayoutLeft = new QVBoxLayout();
m_pLabelIco = new QLabel(this);
m_pLayoutLeft->setContentsMargins(0, 2, 0, 0);
m_pLayoutLeft->addWidget(m_pLabelIco);
m_pLayoutLeft->addStretch();
m_pLayoutRight = new QVBoxLayout();
m_pLayoutRight->setContentsMargins(0, 0, 15, 0);
m_pLayoutRight->setSpacing(0);
m_pLayoutRight->addSpacing(-6);
m_pLabelText = new QLabel();
m_pLabelText->setObjectName(QStringLiteral("LabelText"));
m_pLabelText->adjustSize();
QPalette pa;
pa.setColor(QPalette::WindowText, m_TipParam.m_colorText);
m_pLabelText->setPalette(pa);
m_pLabelText->setWordWrap(true);
if (!m_bTableViewShow)
m_pLabelText->setAlignment(Qt::AlignTop);
else
m_pLabelText->setAlignment(Qt::AlignCenter);
m_pLabelText->setAttribute(Qt::WA_TransparentForMouseEvents, true);
m_pLayoutRight->addWidget(m_pLabelText);
layoutContent->addLayout(m_pLayoutLeft, 0);
layoutContent->addLayout(m_pLayoutRight, 1);
// 關閉定時器設定
m_pTimerClose = new QTimer(this);
m_pTimerMovePos = new QTimer(this);
m_pTimerMovePos->setInterval(200);
// 漸隱效果動畫設定
m_pAnimFadeOut = new QPropertyAnimation(this, "windowOpacity");
m_pAnimFadeOut->setStartValue(1);
m_pAnimFadeOut->setEndValue(0);
m_pAnimFadeOut->setEasingCurve(QEasingCurve::Linear);
}
void ToolTipWidget::initConnect()
{
connect(m_pTimerClose, SIGNAL(timeout()), this, SLOT(slotCloseTimer()));
connect(m_pTimerMovePos, SIGNAL(timeout()), this, SLOT(slotMoveTimer()));
connect(m_pAnimFadeOut, SIGNAL(finished()), this, SLOT(slotFadeout()));
}
相關文章
- c# 窗體自適應C#
- vb窗體中控制元件自動隨窗體變化大小(原始碼)控制元件原始碼
- rust druid編寫第一個窗體RustUI
- VB中實現窗體自動隱藏 (轉)
- C/C++ Qt MdiArea 多窗體元件應用C++QT元件
- C# 如何重複呼叫父窗體中的子窗體C#
- Qt入門(14)——父視窗部件和子視窗部件QT
- Qt視窗居中QT
- QT視窗類QT
- QT分局管理:堆疊窗體(三)QT
- WPF和js互動 呼叫窗體中的方法JS
- 自動感知窗體的關閉事件事件
- Qt 無邊框、透明、可移動、的個性窗體案例詳解QT
- jQuery子窗體如何取得父窗體的元素jQuery
- Qt之設定窗體居中顯示QT
- 寫了個基於 MacOS + iTerm2 自動開啟視窗執行命令的工具Mac
- 【QT】QT如何讓視窗放置在螢幕正中間QT
- Qt中設定視窗居中顯示QT
- 怎麼在thread中開啟一個窗體thread
- Qt的視窗背景及視窗風格統一與煥膚QT
- C++ Qt開發:MdiArea多窗體元件C++QT元件
- Qt程式設計技巧 窗體居中顯示QT程式設計
- 如何關閉 Windows 7 視窗自動排列功能?Windows
- 一個窗體佈局的問題
- qt 視窗預設居中QT
- qt視窗居中顯示QT
- Qt TCP (小型聊天視窗)QTTCP
- 設定Windows應用程式啟動窗體Windows
- Qt+ECharts開發筆記(二):Qt視窗動態調整大小,使ECharts跟隨Qt視窗大小變換QTEcharts筆記
- Go Qt5 建立空白視窗、視窗居中及關閉視窗事件GoQT事件
- WPF中webview2滑鼠移動窗體WebView
- 一個問題——在MDI窗體中新增控制元件後顯示子窗體控制元件
- Qt 把窗體顯示在螢幕的中心QT
- 如何編寫簡單的應用window視窗程式
- js如何在子視窗中關閉父視窗JS
- Qt如何讓彈出的視窗居中顯示QT
- Javascript自動關閉視窗(轉)JavaScript
- Qt 佈局管理 - 停靠視窗QT