操作:

  鼠标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);
}

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

void MyBtn::slot_updateTasks(int tasks)
{
  TaskCounts = tasks;
}

  效果截图:

    

注意如果要鼠标进入浮窗不消失的话,需要自己实现这个浮窗,重写enterevent()判断全局鼠标位置

然后在确定是不是要隐藏窗口,类似于QQ的资料卡。有问题可以博客私聊回复。

Qt 鼠标悬浮按钮上出现浮窗效果的更多相关文章

  1. Java基础 awt Button 鼠标放在按钮上背景颜色改变,鼠标离开背景颜色恢复

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

  2. js 鼠标放到图片上放大某一部分效果

    动图效果: 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  3. Qt实现自定义按钮的三态效果

    好久之前做的一个小软件,好长时间没动过了,在不记录下有些细节可能都忘了,这里整理下部分功能的实现. 按钮的三态,指的是普通态.鼠标的停留态.点击态,三态是界面交互非常基本的一项功能,Qt中如果使用的是 ...

  4. 【C#/WPF】用System.Timers.Timer计时器做浮窗广告

    需求:鼠标静止一段时间后,显示浮窗广告. 思路:界面XAML写好一个专门显示浮窗广告的Canvas,先设为不可见Visibility=”Collapsed”,然后用System.Timers.Time ...

  5. Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮

    前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)/动态显示和隐藏NavigationBar 在某些特殊定制的版本中要求 ...

  6. CSS鼠标悬浮DIV后显示DIV外的按钮

    昨天写样式遇到个问题,如何让鼠标悬浮DIV后,显示DIV外的按钮,可以点击到按钮. 效果如下: 问题: 在DIV hover时候将按钮设为display: block,这是很直接的想法,但是这有个问题 ...

  7. 在TableView上添加悬浮按钮

    如果直接在TableVIewController上贴Button的话会导致这个会随之滚动,下面解决在TableView上实现位置固定悬浮按钮的两种方法: 1.在view上贴tableView,然后将悬 ...

  8. Duilib 鼠标在某控件例如按钮上悬停后,对目标控件操作

    其实对WM_MOUSEHOVER消息的处理,因为WindowImplBase基类中对此消息未处理,所以在自己的窗口类中实现: .h文件中加入 LRESULT OnMouseHover( UINT uM ...

  9. GUI编程笔记(java)08:GUI通过鼠标移动到按钮上更改背景色案例

    首先我们看看源代码如下: package cn.itcast_06; import java.awt.Button; import java.awt.Color; import java.awt.Fl ...

随机推荐

  1. 《SQL Server 2012 T-SQL基础》读书笔记 - 7.进阶查询

    Chapter 7 Beyond the Fundamentals of Querying window function是什么呢?就是你SELECT出来一个结果集,然后对于每一行,你都想给它对应一个 ...

  2. HDU 5073 Galaxy (数学)

    Galaxy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Su ...

  3. mysql-c++连接

    1.mysql-c++连接MySQL :: Download Connector/C++ https://dev.mysql.com/downloads/connector/cpp/ 1-1VS201 ...

  4. Vue实战:音乐播放器(一) 页面效果

    先看一下效果图 首页 歌单详情页 歌手列表 歌手详情页 排行页面 榜单的详情页(排序样式) 搜索页面 搜索结果 播放器内核 歌词自动滚动 播放列表 用户中心

  5. malloc函数分配内存失败的常见原因

    malloc()函数分配内存失败的常见原因:  1. 内存不足.  2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏.下次再使用malloc()函数申请内存 ...

  6. 07 oracle 非归档模式 inactive/active/current redo log损坏的恢复

    在非归档模式下缺失Redo Log后的恢复 将之前的归档模式修改为非归档 SQL> shutdown immediate; SQL> startup mount SQL> alter ...

  7. android window(四)WindowToken

    在WindowManagerService中有两种常见的Token,WindowToken,和AppWindowToken. WindowToken http://androidxref.com/6. ...

  8. idea下载和设置自动翻译(有道)

    1:下载 点击file,点击settings,找到plugins,之后所搜translation并下载,他会自动从新启动idea 2:设置translation 3:这个应用ID和秘钥需要在有道智云去 ...

  9. 【转载】研发应该懂的binlog知识(下)

    引言 这篇是<研发应该懂的binlog知识(上)>的下半部分.在本文,我会阐述一下binlog的结构,以及如何使用java来解析binlog.不过,话说回来,其实严格意义上来说,研发应该还 ...

  10. ./configure 配置文件时出错checking for g++... no

    checking for g++... no checking for c++... no checking for gpp... no checking for aCC... no 缺少C++编译器 ...