QGraphicsProxyWidget paintEvent(from 1+1 =2)

 

标题不好取,起源于CSDN中看到有网友提问:如果将一个QWidget同时显示在 QGraphicsView 和其他和view同级的普通的Widget中。

QGraphicsProxyWidget

QGraphicsProxyWidget 是为将 QWidget 嵌入到 QGraphicsScene 中而引入的代理。

  • 将 event 在二者之间进行传递
  • 基于整数的 QWidget 的坐标和基于浮点数的 QGraphicsScene 坐标间的变换
QWidget 是如何嵌入的?

我们知道一个 QWidget 只能在一个地方出现,而同一个 scene 却可以在多个 view 中出现。这是怎么做的呢?多个 view 中出现的会是同一个 QWidget 么?

嵌入 QWidget ,可以先构建 QGraphicsProxyWidget,对其 setWidget(),然后添加到 scene 中;也可以直接调用 QGraphicsScene的成员 addWidget()

这个过程中对 QWidget 做了哪些动作呢?

可以看看源码:qgraphicsproxywidget.cpp

void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow)

我们只看部分代码片段。

确保:被嵌入的是 顶级QWidget,或者是被嵌入QWidget 对象的子对象

if (!newWidget->isWindow()) {
QWExtra *extra = newWidget->parentWidget()->d_func()->extra;
if (!extra || !extra->proxyWidget) {
qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p "
"which is not a toplevel widget, and is not a child of an embedded widget", newWidget);
return;
}
}

将该 QGraphicsProxyWidget 注册到 QWidget 的 QWidgetPrivate 成员中

// Register this proxy within the widget's private.
// ### This is a bit backdoorish
QWExtra *extra = newWidget->d_func()->extra;
if (!extra) {
newWidget->d_func()->createExtra();
extra = newWidget->d_func()->extra;
}
QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;
if (*proxyWidget) {
if (*proxyWidget != q) {
qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"
"; already embedded", newWidget);
}
return;
}
*proxyWidget = q;

设置属性,使其不再屏幕上显示,并且不会在 close 是被自动删除

newWidget->setAttribute(Qt::WA_DontShowOnScreen);
newWidget->ensurePolished();
// Do not wait for this widget to close before the app closes ###
// shouldn't this widget inherit the attribute?
newWidget->setAttribute(Qt::WA_QuitOnClose, false);
q->setAcceptHoverEvents(true);

安装事件过滤器

// Hook up the event filter to keep the state up to date.
newWidget->installEventFilter(q);
QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));paintpaint 与 paintEvent

QGraphicsProxyWidget 是 QGraphicsItem 的派生类,可知其显示的内容也是在 paint 函数中进行绘制的。

去掉无关紧要的部分,可以看出,此处调用的是 QWidget 的 render 成员,进而调用 QWidget 的 paintEvent 成员

void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_D(QGraphicsProxyWidget);
const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect();
d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect);
}

看一下从 QWidget::render 到 QWidget::paintEvent 的调用关系

QWidget::render()
QWidgetPrivate::render()

QWidgetPrivate::drawWidget()

//事件系统
QCoreApplication::sendSpontaneousEvent()
QCoreApplication::notifyInternal()
QApplication::notify()
QApplicationPrivate::notify_helper()
QWidget::event()

QWidget::paintEvent()repaint 与 update

顺便看一下从 QWidget::repaint 到 QWidgetPrivate::drawWidget

QWidget::repaint()
QWidgetBackingStore::markDirty()

//事件系统
QCoreApplication::sendEvent()
QCoreApplication::notifyInternal()
QApplication::notify()
QApplicationPrivate::notify_helper()
QWidget::event()

QWidgetPrivate::syncBackingStore()
QWidgetBackingStore::sync()
QWidgetPrivate::drawWidget()
...

以及 QWidget::update 与 事件的发送

QWidget::update()
QWidgetBackingStore::markDirty()
QCoreApplication::postEvent()双缓冲?

QWidget 的实现采用的双缓冲方式,上面提到的 QWidgetBAckingStore 类应该与此有关了。

可以看一下 QWidgetBackingStore::sync() 的部分代码(和 QGraphicsProxyWidget 有关部分)

 

for (int i = 0; i < dirtyWidgets.size(); ++i) {
...
#ifndef QT_NO_GRAPHICSVIEW
if (tlw->d_func()->extra->proxyWidget) {
resetWidget(w);
continue;
}
#endif
...
}
...
#ifndef QT_NO_GRAPHICSVIEW
if (tlw->d_func()->extra->proxyWidget) {
updateStaticContentsSize();
dirty = QRegion();
const QVector<QRect> rects(toClean.rects());
for (int i = 0; i < rects.size(); ++i)
tlw->d_func()->extra->proxyWidget->update(rects.at(i));
return;
}
#endif

从这儿可以猜到,一旦为一个QWidget对应QWidgetPrivate 设置了 proxyWidget,其自身的绘制行为将会很很大的不同

转载于:https://www.cnblogs.com/zhaifd/archive/2013/06/03/3116154.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Asterisk使用数据库配置方法

安装&#xff1a; 1、安装 unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel &#xff0c;为了使asterisk支持数据库存储&#xff08;必须先安装&#xff09; 2、安装 mysql 并设置好 C_INCLUDE_PATH 和 LD_LIBRARY_PATH 3、从 http://www.asterisk.org/downloads 下载…

linux文件系统_Linux的文件系统简介

inux操作系统的本质可以说就是文件系统的集合&#xff0c;文件系统既包含文件的数据也包含文件系统的结构。在Linux文件系统中&#xff0c;EXT2文件系统、虚拟文件系统、/proc文件系统是三个具有代表性的文件系统。/proc文件系统是一个伪文件系统&#xff0c;它只存在内存当中&…

matlab如何测两点的角度_根据2点经纬度,计算方位角,以及计算2条线的夹角

以真北为0度起点&#xff0c;由东向南向西顺时针旋转360度&#xff0c;主要是用于控制象限。根据2点经纬度&#xff0c;计算方位角[csharp]////// 给定2点&#xff0c;获得经纬度/// /// 起点经纬度&#xff0c;都是以度为单位/// 终点经纬度&#xff0c;都是以度为单位/// pri…

VMWare 环境下devstack创建虚拟机报错及修改nova-api返回数据得条目

1、在生产环境中&#xff0c; 由于某个tenant下创建了有1300条得security-group通过查询nova得数据库可以看出确实有1300条得存在&#xff0c;但是通过curl调用的时候发现返回得数目只有1000条 可以通过修改nova.conf文件得osapi_max_limit 项修改返回得条目限制&#xff0c;默…

使用数据库保存Asterisk sip账号信息(odbc方式)

在默认情况下&#xff0c;Asterisk的配置文件都保存在/etc/asterisk目录中&#xff0c;以ini文件的格式保存。我们也可以使用数据库来保存大多数Asterisk配置信息。 Asterisk使用数据库保存配置信息有两种方法&#xff1a;静态和动态&#xff0c;对于不经常修改的配置数据&…

删除按钮_汪涵拜师学艺第七篇:往来单位查询删除按钮和新增判断的设计!

老师好&#xff01;大家好&#xff01;我叫汪涵&#xff1a;今天给大家分享往来单位查询删除按钮和新增判断的设计&#xff01;在开始具体内容之前&#xff0c;请让我先分享我们的价值观&#xff1a;用自律和勤奋来改变命运&#xff0c;不走捷径&#xff0c;有爱心&#xff0c;…

python requests https_解决python的requests模块访问私有SSL证书产生的报错问题

如题访问部分私有SSL证书网站时报如下错误requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)测试环境kali linux 1.1.0Python 2.7.8python-openssl 0.13-2deb7u1requests 2.3.0测试代码#/usr/bin/python#codingutf-8imp…

Ubuntu 12.04(32位)安装Oracle 11g(32位)全过程以及几乎所有问题的解决办法

这两天在Ubuntu上安装Oracle把人折腾毁了&#xff0c;即使照着网上的教程来&#xff0c;还是出了很多问题。好在最后终于搞定了。写出来总结一下&#xff0c;免得以后忘了。 标题注明32位是因为网上教程几乎全是以64位安装为例的&#xff0c;32位系统下照着做是绝对会安装失败的…

dio设置自定义post请求_Flutter Dio简单二次封装和自定义Header

话不多说自己看代码封装的比较简单&#xff0c;比较适合入门学习Dio。import package:dio/dio.dart;import Api.dart;/** 封装 restful 请求** GET、POST、DELETE、PATCH* 主要作用为统一处理相关事务&#xff1a;* - 统一处理请求前缀&#xff1b;* - 统一打印请求信息&#x…

解决asterisk sip呼叫 488 no acceptable here

这两天实验了一下asterisk static realtime方案&#xff0c;将sip.conf的信息保存到mysql数据库里。但是呼叫的时候&#xff0c;总是 报 488 no acceptable here。 这是我的sip.conf文件&#xff0c;数据库里和sip.conf文件一模一样&#xff0c;但是就是不行。 [general] c…

怎么安装python3.6.5_Centos7 安装Python3.6.5

一、centos7 安装 Python3.6.5教程1、在安装Python之前&#xff0c;需要先安装一些后面遇到的依赖问题(如果有依赖问题&#xff0c;按照提示安装)&#xff1a;yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-d…

关于浏览器模式和文本模式的困惑

什么是浏览器模式和文本模式&#xff1f; 经常使用IE开发者工具的同学&#xff0c;肯定见过浏览器模式和文本模式&#xff0c;对于这两个名词&#xff0c;综合相关文档解释如下&#xff1a; 浏览器模式&#xff08;Browser Mode&#xff09;&#xff0c;用于切换IE针对该网页的…

mysql 关联索引_mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?...

情况描述&#xff1a;在MySQL的user表中&#xff0c;对a,b,c三个字段建立联合索引&#xff0c;那么查询时使用其中的2个作为查询条件&#xff0c;是否还会走索引&#xff1f;根据查询字段的位置不同来决定&#xff0c;如查询a, a,b a,b,c a,c 都可以走索引的&#…

A20 看门狗

前言 说到看门狗&#xff0c;应该不会陌生&#xff0c;看门狗说白了就是一个定时器&#xff0c;但是它有一个非常重要的功能就是复位系统。在A20里&#xff0c;看门狗的操作非常简单&#xff0c;只有两个寄存器&#xff0c;不需要操作时钟相关的东西&#xff0c;系统起来后可以…

python拼接大量ts文件_Python爬取.ts文件,合并为mp4

目标&#xff1a;爬影视网站ts文件到本地&#xff0c;合并成mp4文件下载ts文件本着不重复造轮子的精神(好吧其实是我懒)&#xff0c;想用迅雷批量下载爬取&#xff0c;但是迅雷提供的通配符过于简单无法构造URL&#xff0c;只能自己写脚本如下&#xff1a;# -*- coding: utf-8 …

android学习笔记之ProgressDialog的使用

在很多PC软件或手机软件中&#xff0c;我们都会看见 “加载中...” 类似的对话框&#xff0c;当然&#xff0c;在android应用程序中也是如此。如果我们想在android应用程序中使用这样的效果&#xff0c;那么就需要用到ProgressDialog。首先&#xff0c;我们来看一下ProgressDia…

asterisk 互联问题

asterisk A 和asterisk B互联。 A下面有账户1001&#xff0c;B下面有账户2001 当1001呼叫2001时&#xff0c;B的sip.conf里不能有1001。 当2001呼叫1001时&#xff0c;A的sip.conf里不能有2001。 否则&#xff0c;呼叫无法呼叫成功。 下面为截图 实际和在振铃时&#xff0…

清除python shell中的内容_如何使用python脚本定时清空文件内容?

我们一直在对大家强调关于python脚本的使用&#xff0c;但是有部分同学提出疑问&#xff0c;就是关于上期跟大家说的shell脚本没有实质性的使用效果&#xff0c;如果在实际应用里&#xff0c;要怎么使用这个脚本&#xff0c;它又能实现什么效果&#xff0c;其实针对这个内容&am…

ACCESS中不支持left join解决方案

今天在做基于 access数据库项目中,做外连接时,发现Access不支持两个以上的 left join 在网上查一下,有哥们说每个 left join 要加 () 在修改之前(不能执行,ms sql 里执行以通过) select table1.fildes1, table1.fildes2,table2.fildes1, table2.fildes2,table3.fildes…

docker mysql主从_使用docker 实现MySQL主从同步/读写分离

1. 利用 docker 实现 mysql 主从同步 / 读写分离为了保证数据的完整和安全&#xff0c;mysql 设计了主从同步&#xff0c;一个挂掉还可以用另个。最近重构论坛&#xff0c;想来改成主从吧。担心失误&#xff0c;就先拿 docker 练练手。通过本文实际你会操作到。mysql 的主从同步…