操作:

  鼠标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. (转)GitHub中PR(Pull request)操作 - 请求合并代码

    转:https://www.jianshu.com/p/b365c743ec8d 前言 本文尽量使用图形工具介绍如何向开源项目提交 Pull Request,一次亲身经历提交 PR 1.fork 项目 ...

  2. iOS环境搭建

    Xcode安装 一定要在App Store上下载XCode . git config常用配置 设置lg命令 查看分支图 git config --global alias.lg "log - ...

  3. Python 代码控制Windows定时关机

    为了在规定时间内实现电脑关机,我使用python编写了几行代码,最简单的实现了关机操作,后续再进行其它功能的添加(操作页面,取消等) import os,time #获取命令行输入的关机时间 inpu ...

  4. 【C++进阶:移位运算符的用法】

    数据在计算机中以补码存储 移位运算符:<<  左移运算符 >>  右移运算符 一丶 << 左移运算符 移位规则:左边抛弃,右边补零 int num=10; num& ...

  5. ubuntu 安装java1.8

    1.进入官网下载页面http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.选择需要的版本,进入下载页面 下载 jdk ...

  6. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_08 Map集合_3_Map接口中的常用方法

    这个方法比较特殊,它的返回值是V他也就是Vlaue get remove containsKey: put value没有重复的所以v1返回的是null key值有重复,所以会返回被替换的值,范冰冰1 ...

  7. Jenkins简介&邮箱配置

    一.Jenkins基本介绍: Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.--摘自百科 二 ...

  8. Python高效率遍历文件夹寻找重复文件

    前言 为什么要写这篇文章呢...主要还是业务中有个需求,遍历一个将近200w数据的文件夹,大部分还都是视频文件那种,但是这玩意用的次数还不多,做文件夹index也不是很ok,所以写了一个脚本来处理这个 ...

  9. 学习《Oracle PL/SQL 实例讲解 原书第5版》----创建账户

    通过readme.pdf创建student账户. 以下用sys账户登录时都是sysdba. 一.PL/SQL 登录oracle. SYS/123  AS SYSDBA 账户名:sys:密码:123:作 ...

  10. 第一个spring boot应用

    前提 首先要确保已经安装了java和maven: $ java -version java version "1.8.0_102" Java(TM) SE Runtime Envi ...