操作:

  鼠标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. k8s上的基础概念和术语

    kubernetes基本概念和术语   kubeernetes中的大部分概念如Node,Pod,Replication Controller ,Serverce等都可以看作一种“资源对象”,几乎所有的 ...

  2. 【运维相关】MongoDB那些坑

    前言 某个早期技术债务项目线上有一个mongoDB服务,用途很简单,存一些文件而已.不过用户那边突然报个bug说上边的图片丢失了,起初没当回事认为是代码遇到错了,直到后来看了用户详细的bug复现后,登 ...

  3. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_12_练习_文件复制

    谁用字节可以读取任何文件. 读取后再写入到D盘去.这就是一个文件的复制. 怎么由C盘到D盘.这里要借助流技术 需要创建两个流,一个读取一个写入 图片复制过来了. 看一下图片的字节数.whilte循环要 ...

  4. jt获取鼠标指针的位置

    屏幕 screenX和screenY属性表示鼠标在整个显示屏的位置,从屏幕(而不是浏览器)的左上角开始计算的. 页面 pageX和pageY属性表示鼠标指针在这个页面的位置.页面的顶部可能在可见区域之 ...

  5. 字符串 字符数组, pcha string 之间的相互转化, 很重要。 很蛋疼

    http://www.cnblogs.com/del88/p/5448981.html Delphi字符串.PChar与字符数组之间的转换 来自:http://my.oschina.net/kaven ...

  6. Selenium WebDriver 数据驱动测试框架

    Selenium WebDriver 数据驱动测试框架,以QQ邮箱添加联系人为示例,测试框架结构如下图,详细内容请阅读吴晓华编著<Selenium WebDiver 实战宝典>: Obje ...

  7. Python解决NameError: name 'reload' is not defined的问题

    遇到这个问题,对于 Python 2.X: import sys reload(sys) sys.setdefaultencoding("utf-8") 对于 Python 3.3 ...

  8. python 列表、字典多排序问题

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/justin051/article/det ...

  9. DevOps的前世今生

    From今日头条:https://www.toutiao.com/a6534660729453150723/?tt_from=weixin&utm_campaign=client_share& ...

  10. 027 (H5*) react01

    目录 正文 1:创建Vue项目 1: 全局安装 vue-cli cnpm install --global vue-cli 2: 创建一个基于 webpack 模板的新项目 vue init webp ...