Qt 图形视图框架 大数据量时的区域预览

时间:2023-02-01 18:24:34
Qt 图形视图框架 大数据量时的区域预览

背景:
使用图形视图框架实现大数据量的item显示

1.左侧及右侧下角为两个view,二者使用的为同一个scene,这样做的目的是当左侧的视图区域进行放大缩小、拖拽移动时,右侧也会联动放大缩小、拖拽移动
2.右侧的淡蓝色框选中的区域会显示在左侧视图区域(框可以移动,因此可以局部框选),且右侧淡蓝色的框是可以改变大小的

问题:
1.如何实现右侧的淡蓝色框?(框支持四个角拖拽放大或缩小)
2.如何高效实现二者的联动?

10 个解决方案

#1


把左边的那个render到一个pixmap上面,又点的就显示pixmap.
QPixmap QPixmap::grabWindow(WId window, int x = 0, int y = 0, int width = -1, int height = -1)
大概使用这样的函数,但是不一定一定是这个函数,Qt里面捕获图像的函数很多,你得测试一下,哪个可以满足你的需求.
我这里只是提供思路,毕竟代码很复杂,还得你自己来写.

如果需要鼠标事件,算一下缩放之后相对位置,发送到左边的那部分上.

#2


补充一下相关函数,估计还有其它方式.
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ))

发送消息
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)

#3


引用 2 楼 n7zj0x8 的回复:
补充一下相关函数,估计还有其它方式.
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ))

发送消息
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)


您的意思是每次左侧的改变都通过类似保存图片然后在右侧再显示这样的做法?这个思路我考虑过,但是项目中可能错在左侧视图节点的各种编辑(插入删除排序等等),这样的话每次都保存图片再在右侧加载,可能会出现效率问题,所以想的是通过左右两个view公用一个scene来保持二者的同步

#4


引用 2 楼 n7zj0x8 的回复:
补充一下相关函数,估计还有其它方式.
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ))

发送消息
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)


但是如果使用两个view的话,右侧的淡蓝色框不知道该怎么弄?请教一下您这边有好点的思路吗?

#5


不是存成图片哦,只是保存图像数据,是不一样的.

不过不得不承认,两个view,能更好的解决这个问题. 能直接render到两个view上面再好不过了.

至于蓝色框缩放问题,先算出蓝色框在右侧上的位置比例.包括xy的比例,宽高的比例.
这个比例带入到左侧的view上进行计算,就可以知道框选部分在左侧的范围.
然后移动滚动条就可以把框选的部门移动到中心显示.

#6


引用 5 楼 n7zj0x8 的回复:
不是存成图片哦,只是保存图像数据,是不一样的.

不过不得不承认,两个view,能更好的解决这个问题. 能直接render到两个view上面再好不过了.

至于蓝色框缩放问题,先算出蓝色框在右侧上的位置比例.包括xy的比例,宽高的比例.
这个比例带入到左侧的view上进行计算,就可以知道框选部分在左侧的范围.
然后移动滚动条就可以把框选的部门移动到中心显示.


首先谢谢你前面提供的思路,我现在碰到的问题是:如何在右侧区域画出这个蓝色的框?想过画一个大的矩形item,然后设置item透明并且设置淡蓝色填充,但这样的存在的问题就是,当吧这个Item添加到scene上时,两个view都会看到这个item,而需求是只在一侧,所以这个 方案是不可行的。另一个思路是添加一个widiget上去,同样也会有前面碰到的问题,考虑了许久,还没有想到好的解决办法(如何弄一个矩形框出来),您这边有好的思路吗?

#7


如果右边框选的部分刚好占满左边的图,item是可以使用的.
因为你在左侧框选的时候,右侧都是同步的显示框选的部分.那么左侧是看不到那个item的.
通常情况下只会有一个控件有焦点,当左侧view获得焦点的时候,把那个item隐藏掉.当右侧获得焦点的时候再显示出来.
这样存在的问题就是左侧获得焦点右侧就不显示蓝色框了.

还有widget的放到view上,这样就只会有一个view上有,你说同样的问题,我不是很懂.
我觉得加一个Widget是可以解决的. 当然你可能要继承来重写一下,让它可以拖动大小.
在你的鼠标点击到view上的时候,显示出来, 鼠标移动的时候改变Widget的大小.

#8


如果右边框选的部分刚好占满左边的图,item是可以使用的.
因为你在右侧框选的时候,左侧都是同步的显示框选的部分.那么左侧是看不到那个item的.

通常情况下只会有一个控件有焦点,当左侧view获得焦点的时候,把那个item隐藏掉.当右侧获得焦点的时候再次显示出来.
这样存在的问题就是左侧获得焦点,右侧就不能显示蓝色框了.

还有widget的放到view上,这样就只会有一个view上有,你说同样的问题,我不是很懂.
我觉得加一个Widget是可以解决的. 当然你可能要继承来重写一下,让它可以拖动大小.
在你的鼠标点击到view上的时候,显示出来, 鼠标移动的时候改变Widget的大小.

#9


引用 7 楼 n7zj0x8 的回复:
如果右边框选的部分刚好占满左边的图,item是可以使用的.
因为你在左侧框选的时候,右侧都是同步的显示框选的部分.那么左侧是看不到那个item的.
通常情况下只会有一个控件有焦点,当左侧view获得焦点的时候,把那个item隐藏掉.当右侧获得焦点的时候再显示出来.
这样存在的问题就是左侧获得焦点右侧就不显示蓝色框了.

还有widget的放到view上,这样就只会有一个view上有,你说同样的问题,我不是很懂.
我觉得加一个Widget是可以解决的. 当然你可能要继承来重写一下,让它可以拖动大小.
在你的鼠标点击到view上的时候,显示出来, 鼠标移动的时候改变Widget的大小.


确实如您所说,右边蓝色框中的内容会在右侧全部显示(蓝色框的边界对应于左侧窗口的大小)。单是需求为右侧的蓝色框为一直存在的,因此无法通过判断焦点在哪个view中去隐藏。

对于加载一个wideget,我想的是,widget自身已经支持窗口大小的改变,为什么还要重写widget?求解答一下疑惑

#10


你右侧widget,要支持鼠标移动到它边缘的时候,可以拖动大小,对吧.
Widget单个窗口虽然支持,边缘拖动大小,但是设置了父窗口,就不行了.
所以 虽然 Widget可以通过Resize来改变大小, 但是它不支持鼠标移动到边缘的时候拖动大小.这个得你手动实现,
包括你鼠标点击到Widget上,之后应该还可以移动Widget的位置吧,这个也得手动实现.

#1


把左边的那个render到一个pixmap上面,又点的就显示pixmap.
QPixmap QPixmap::grabWindow(WId window, int x = 0, int y = 0, int width = -1, int height = -1)
大概使用这样的函数,但是不一定一定是这个函数,Qt里面捕获图像的函数很多,你得测试一下,哪个可以满足你的需求.
我这里只是提供思路,毕竟代码很复杂,还得你自己来写.

如果需要鼠标事件,算一下缩放之后相对位置,发送到左边的那部分上.

#2


补充一下相关函数,估计还有其它方式.
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ))

发送消息
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)

#3


引用 2 楼 n7zj0x8 的回复:
补充一下相关函数,估计还有其它方式.
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ))

发送消息
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)


您的意思是每次左侧的改变都通过类似保存图片然后在右侧再显示这样的做法?这个思路我考虑过,但是项目中可能错在左侧视图节点的各种编辑(插入删除排序等等),这样的话每次都保存图片再在右侧加载,可能会出现效率问题,所以想的是通过左右两个view公用一个scene来保持二者的同步

#4


引用 2 楼 n7zj0x8 的回复:
补充一下相关函数,估计还有其它方式.
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ))

发送消息
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)


但是如果使用两个view的话,右侧的淡蓝色框不知道该怎么弄?请教一下您这边有好点的思路吗?

#5


不是存成图片哦,只是保存图像数据,是不一样的.

不过不得不承认,两个view,能更好的解决这个问题. 能直接render到两个view上面再好不过了.

至于蓝色框缩放问题,先算出蓝色框在右侧上的位置比例.包括xy的比例,宽高的比例.
这个比例带入到左侧的view上进行计算,就可以知道框选部分在左侧的范围.
然后移动滚动条就可以把框选的部门移动到中心显示.

#6


引用 5 楼 n7zj0x8 的回复:
不是存成图片哦,只是保存图像数据,是不一样的.

不过不得不承认,两个view,能更好的解决这个问题. 能直接render到两个view上面再好不过了.

至于蓝色框缩放问题,先算出蓝色框在右侧上的位置比例.包括xy的比例,宽高的比例.
这个比例带入到左侧的view上进行计算,就可以知道框选部分在左侧的范围.
然后移动滚动条就可以把框选的部门移动到中心显示.


首先谢谢你前面提供的思路,我现在碰到的问题是:如何在右侧区域画出这个蓝色的框?想过画一个大的矩形item,然后设置item透明并且设置淡蓝色填充,但这样的存在的问题就是,当吧这个Item添加到scene上时,两个view都会看到这个item,而需求是只在一侧,所以这个 方案是不可行的。另一个思路是添加一个widiget上去,同样也会有前面碰到的问题,考虑了许久,还没有想到好的解决办法(如何弄一个矩形框出来),您这边有好的思路吗?

#7


如果右边框选的部分刚好占满左边的图,item是可以使用的.
因为你在左侧框选的时候,右侧都是同步的显示框选的部分.那么左侧是看不到那个item的.
通常情况下只会有一个控件有焦点,当左侧view获得焦点的时候,把那个item隐藏掉.当右侧获得焦点的时候再显示出来.
这样存在的问题就是左侧获得焦点右侧就不显示蓝色框了.

还有widget的放到view上,这样就只会有一个view上有,你说同样的问题,我不是很懂.
我觉得加一个Widget是可以解决的. 当然你可能要继承来重写一下,让它可以拖动大小.
在你的鼠标点击到view上的时候,显示出来, 鼠标移动的时候改变Widget的大小.

#8


如果右边框选的部分刚好占满左边的图,item是可以使用的.
因为你在右侧框选的时候,左侧都是同步的显示框选的部分.那么左侧是看不到那个item的.

通常情况下只会有一个控件有焦点,当左侧view获得焦点的时候,把那个item隐藏掉.当右侧获得焦点的时候再次显示出来.
这样存在的问题就是左侧获得焦点,右侧就不能显示蓝色框了.

还有widget的放到view上,这样就只会有一个view上有,你说同样的问题,我不是很懂.
我觉得加一个Widget是可以解决的. 当然你可能要继承来重写一下,让它可以拖动大小.
在你的鼠标点击到view上的时候,显示出来, 鼠标移动的时候改变Widget的大小.

#9


引用 7 楼 n7zj0x8 的回复:
如果右边框选的部分刚好占满左边的图,item是可以使用的.
因为你在左侧框选的时候,右侧都是同步的显示框选的部分.那么左侧是看不到那个item的.
通常情况下只会有一个控件有焦点,当左侧view获得焦点的时候,把那个item隐藏掉.当右侧获得焦点的时候再显示出来.
这样存在的问题就是左侧获得焦点右侧就不显示蓝色框了.

还有widget的放到view上,这样就只会有一个view上有,你说同样的问题,我不是很懂.
我觉得加一个Widget是可以解决的. 当然你可能要继承来重写一下,让它可以拖动大小.
在你的鼠标点击到view上的时候,显示出来, 鼠标移动的时候改变Widget的大小.


确实如您所说,右边蓝色框中的内容会在右侧全部显示(蓝色框的边界对应于左侧窗口的大小)。单是需求为右侧的蓝色框为一直存在的,因此无法通过判断焦点在哪个view中去隐藏。

对于加载一个wideget,我想的是,widget自身已经支持窗口大小的改变,为什么还要重写widget?求解答一下疑惑

#10


你右侧widget,要支持鼠标移动到它边缘的时候,可以拖动大小,对吧.
Widget单个窗口虽然支持,边缘拖动大小,但是设置了父窗口,就不行了.
所以 虽然 Widget可以通过Resize来改变大小, 但是它不支持鼠标移动到边缘的时候拖动大小.这个得你手动实现,
包括你鼠标点击到Widget上,之后应该还可以移动Widget的位置吧,这个也得手动实现.