Qt 鼠標懸浮按鈕上出現浮窗效果


操作:

  鼠標hover於Btn(or other widget),在指定位置顯示想要的widget(或其他控件窗口)

  

方法:重載以下幾個api

  void paintEvent(QPaintEvent *);    //由於重載QPushbutton,normal, hover, pressed 按鈕的狀態需要重新設定
  void enterEvent(QEvent*event);    //鼠標進入的時候發送信號顯示 diy widget
  void leaveEvent(QEvent*event);    //鼠標離開的時候發送信號隱藏 diy widget

實現:

類原型:

//構造的時候需要將normal,hover, pressed的狀態的圖片,其他多余的為擴展,taskPix為任務圖標類似QQ消息右上角的小紅點,當然也可以自己畫
class MyBtn :public QPushButton {
  Q_OBJECT
  public:
  MyBtn(QWidget *parent, QString Text, QPixmap NorPix, QPixmap HoverTipsPix, QPixmap PressedTaskpix, QPixmap TaskPix);
  void init();
  void SetTaskCounts(int counts) { TaskCounts = counts; }
  void setCurrenPix(QPixmap pix) { CurrenPix = pix; }
  QTimer *pTimer;              //鼠標進入的時候,需要計時器100ms去將獲取全局的鼠標位置發給需要顯示的Widget


protected:

  void paintEvent(QPaintEvent *);
  void enterEvent(QEvent*event);
  void leaveEvent(QEvent*event);
  bool eventFilter(QObject *obj, QEvent *event);     //可能要用到的過濾,

private:
  int TaskCounts;
  QPixmap TaskPix;
  QPixmap NorPix;
  QPixmap HoverPix;
  QPixmap PressPix;
  QPixmap CurrenPix;

  QLabel *TipsLbl;     //需要顯示的wigdet  其中構造的Text是放在這里
  QWidget *TipsWgt;    //需要顯示的widget  
  QGridLayout *TipsLyt;
public slots:
  void slot_showWgt(QPoint);
  void slot_updateTasks(int tasks);  //隨着消息的變動更新 Taskcounts
signals:
  void sig_showWgt(QPoint);     //發送消息通知要顯示的widget
  void sig_hideWgt();       //發送消息通知要隱藏的widget
};

 

 

//構造這里初始化基本的數據
MyBtn::MyBtn(QWidget *parent, QString Text, QPixmap NormalPix, QPixmap HoverTipsPix, QPixmap PressedTaskpix, QPixmap TasksPix) :
QPushButton(parent)
{
  init();

  NorPix = NormalPix;
  CurrenPix = NormalPix;
  HoverPix = HoverTipsPix;
  PressPix = PressedTaskpix;
  PressPix = NorPix;
  TaskPix = TasksPix;
  TipsLbl->setText(Text);
}

void MyBtn::init()
{
  pTimer = new QTimer(this);
  TaskCounts = 0;

  TipsWgt = new QWidget;
  TipsLbl = new QLabel(TipsWgt);
  TipsLyt = new QGridLayout(TipsWgt);
  TipsLyt->addWidget(TipsLbl);


  TipsWgt->setWindowFlags(Qt::FramelessWindowHint);
  TipsWgt->setStyleSheet("background-color: transparent");
  TipsWgt->setAutoFillBackground(false);
  TipsWgt->setAttribute(Qt::WA_TranslucentBackground);
  TipsLbl->setStyleSheet("QLabel{border-image: url(:/SprintPlot/image/menuWhatis.png);color:white;}");
  TipsLbl->resize(80, 40);
  QPixmap pix(":/SprintPlot/image/menuWhatis.png");
  TipsLbl->setFixedSize(pix.size());
  TipsLbl->setAlignment(Qt::AlignCenter);
  TipsWgt->resize(80, 40);

  connect(this, &MyBtn::sig_showWgt, this, &MyBtn::slot_showWgt);
}

//繪畫事件,即重點,把需要的效果重新畫出來包括數據
void MyBtn::paintEvent(QPaintEvent *event)
{
  QPainter painter(this);

  painter.drawPixmap(QRect(this->rect().x() + this->width() / 4 - 3, this->rect().y()+10, 24, 24), CurrenPix);
  painter.setPen(Qt::white);
  if (TaskCounts > 99)
  {
    painter.drawPixmap(QRect(QPoint(this->x() + 20, 0), QSize(22, 22)), TaskPix);
    painter.drawText(QRect(QPoint(this->x() + 22, 2), QSize(18, 18)), Qt::AlignVCenter, QString::number(99) + "+");
  }
  else if (TaskCounts)

  {  
    painter.drawPixmap(QRect(QPoint(this->x()+ 20, 0), QSize(18, 18)), TaskPix);
    painter.drawText(QRect(QPoint(this->x() + 23, 3), QSize(12, 12)), Qt::AlignCenter, QString::number(TaskCounts));
  }
  else

  {
    update();
  }
}

//鼠標進入事件這里獲取鼠標的坐標

void MyBtn::enterEvent(QEvent *event)

{
  CurrenPix = HoverPix;
  pTimer->stop();
  QPoint oPoint = this->mapToGlobal(QPoint(this->x() - 90, 0));
  emit sig_showWgt(oPoint);
}

//鼠標離開事件這里獲取鼠標的全局坐標,注意需要轉換成小部件的坐標的時候需要調整
void MyBtn::leaveEvent(QEvent *event)
{
  CurrenPix = NorPix;
  pTimer->start(100);
  TipsWgt->hide();
}

 //事件篩選,根據自己需求自己篩吧

bool MyBtn::eventFilter(QObject *target, QEvent *event)
{

  if (target == this&&event->type() == QEvent::Enter)
  {
    CurrenPix = HoverPix;
  }
  else if (target == this&&event->type() == QEvent::MouseButtonPress)
  {
    CurrenPix = PressPix;
  }
  else if (target == this&&event->type() == QEvent::Leave)
  {
    CurrenPix = NorPix;
  }
  else

  {
    return true;
  }

  return QPushButton::eventFilter(target, event);
}

//在自定義位置顯示自定義的Wgt

void MyBtn::slot_showWgt(QPoint oPoint)
{
  TipsWgt->move(oPoint);
  TipsWgt->show();
}

//更新Btn上的task數量
void MyBtn::slot_updateTasks(int tasks)
{
  TaskCounts = tasks;
}

  效果截圖:

    

 

注意如果要鼠標進入浮窗不消失的話,需要自己實現這個浮窗,重寫enterevent()判斷全局鼠標位置

然后在確定是不是要隱藏窗口,類似於QQ的資料卡。有問題可以博客私聊回復。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM