36.QT-解决无边框界面拖动卡屏问题(附带源码)
1.简介
- 看到很多才学QT的人都会问为啥无边框拖动为啥会花屏?
那是因为你每次拖动的过程中都一直在调用move()函数让QT重新绘制界面,如果资源过大,就会导致当前图形还未绘制完,便又重新改变坐标了,从而导致花屏.
2.如何解决
我们参考其它软件,比如QQ,浏览器等,可以看到我们如果在拖动它们的时候,会出现一个虚线框.
- 如下图所示,可以看到在白色背景下,拖出的虚线框是黑色的

- 而在黑色背景时,拖出的虚线框是白色的

显然这个虚线框会根据当前桌面的像素点而去取反(也就是255-currentRGB).
解决的过程有两种方法:
- 1) 调用win库来实现
- 2) 自己动手写一个
既然我们已经知道它的实现过程.那我们还是自己动手写一个,只需要写一个虚线框类即可
3.虚线框类代码
DragShadow.h
#ifndef DRAGSHADOW_H
#define DRAGSHADOW_H
#include <QtGui>
class DragShadow : public QWidget
{
Q_OBJECT
private:
QImage m_image;
protected:
bool getInvertColor(int x, int y, QColor &color);
void paintEvent(QPaintEvent *);
void showEvent( QShowEvent * event );
public:
explicit DragShadow(QWidget *parent = );
void setSizePos(int x, int y, int w, int h);
void setPos(int x,int y );
void setPos(QPoint pos );
signals: public slots: };
#endif // DRAGSHADOW_H
DragShadow.cpp
#include "DragShadow.h"
DragShadow::DragShadow(QWidget *parent) :
QWidget(NULL)
{
setWindowFlags(Qt::FramelessWindowHint|Qt::Tool);
setAttribute(Qt::WA_TranslucentBackground);
}
void DragShadow::setSizePos(int x, int y, int w, int h)
{
if(w%==)
w+=;
if(h%==)
h+=;
this->setGeometry(x,y,w,h);
}
void DragShadow::setPos(int x,int y )
{
this->move(x,y);
this->update();
}
void DragShadow::setPos(QPoint pos )
{
this->move(pos);
this->update();
}
void DragShadow::showEvent( QShowEvent * event )
{
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
m_image = QPixmap::grabWindow(QApplication::desktop()->winId()).toImage();
#else
QScreen *screen = QGuiApplication::primaryScreen();
m_image = screen->grabWindow(0).toImage();
#endif
}
void DragShadow::paintEvent(QPaintEvent *)
{
int LineCount=;
QColor color;
QPainter painter(this);
painter.setBrush(Qt::NoBrush);
QPen pen(Qt::SolidLine);
pen.setColor(Qt::black);
pen.setWidthF();
painter.setPen(pen);
painter.drawPoint(,); for(int current=;current<LineCount;current++)
{
for(int i=current;i<(this->width()-current);i+=) //x
{
this->getInvertColor(this->x()+i,this->y()+current,color);
pen.setColor(color);
painter.setPen(pen);
painter.drawPoint(i,current); //draw top
this->getInvertColor(i+this->x(),this->height()-current-+this->y(),color);
pen.setColor(color);
painter.setPen(pen);
painter.drawPoint(i,this->height()-current-); //draw bottom
}
for(int i=current;i<(this->height()-current);i+=) //y
{
this->getInvertColor(current+this->x(),i+this->y(),color);
pen.setColor(color);
painter.setPen(pen);
painter.drawPoint(current,i); //draw left
this->getInvertColor(this->width()-current-+this->x(),i+this->y(),color);
pen.setColor(color);
painter.setPen(pen);
painter.drawPoint(this->width()-current-,i); //draw right
}
}
}
bool DragShadow::getInvertColor(int x, int y, QColor &color)
{
int ret=m_image.valid(x,y);
if(ret)
{
QRgb rgb = m_image.pixel(x,y);
color.setRgb(rgb);
color.setRed(-color.red());
color.setBlue(-color.blue());
color.setGreen(-color.green());
}
else
{
color.setRed();
color.setBlue();
color.setGreen();
}
return ret;
}
4.测试UI界面如下图所示
5.拖动时的效果图如下所示

6.针对实线框补充
对于有些不同的windows系统设置,实现的是实线框,如下图所示:

如果想要这种效果,就将上面代码的paintEvent(QPaintEvent *)函数的i+=2改为i++即可.
修改后效果如下所示:
上面的两个不同效果的demo源码地址如下所示:
https://download.csdn.net/download/qq_37997682/10955602
36.QT-解决无边框界面拖动卡屏问题(附带源码)的更多相关文章
- Qt——透明无边框Widget的bug
Experience 最近在封装一些类的时候,打算做一个窗口框架,能实现拖动.缩放.最大最小化.基本样式等功能,可不慎遇见一件无比蛋疼的事情,QWidget最小化后再恢复正常界面,最小化按钮居然仍处于 ...
- WPF 解决无边框产生的相关问题
原文:WPF 解决无边框产生的相关问题 最大化: 在设置WindowStyle="None" AllowsTransparency="True"后,最大化会覆盖 ...
- qt 5 小练习 创建无边框界面
我们大家都知道QT5 自带的界面不是那么美观,并且每个软件我们都发现他们的边框是自定义的,所以我决定写一篇这样的博文,也许已经有许许多多篇大牛写的论文了,但我还是想写一篇记录自己的学习QT的历程 首先 ...
- 让Qt的无边框窗口支持拖拽、Aero Snap、窗口阴影等特性
环境:Desktop Qt 5.4.1 MSVC2013 32bit 需要的库:dwmapi.lib .user32.lib 需要头文件:<dwmapi.h> .<windowsx. ...
- Qt5:无边框窗口拖动
在窗口程序中,无边框窗口程序一般需要特殊处理才能拖动 Qt中,要实现无边框窗口的拖动,需要重新实现 mousePressEvent 和 mouseMoveEvent 俩虚函数 void Widget: ...
- winform无边框窗口拖动
无边框的窗口想拖动,只需要在置顶的容器上添加对应的mousedown 和 mousemove 事件就可以实现了.代码如下: //拖动窗口 private Point mPoint = new Poin ...
- Delphi无边框Form拖动
用Delphi做登陆窗口,如果使用无边框Form,想要拖动窗口,可以在某个控件的OnMouseDown事件中写下以下代码 ReleaseCapture; Perform(WM_SYSCOMMAND, ...
- WPF无边框可拖动窗体
下面主要记录下创建无边框窗体,并且可以拖动.这种窗体主要用于弹出小窗体时. <Window x:Class="WpfApplication1.MainWindow" xmln ...
- C#中无边框窗体拖动
//定义一个bool变量标识是否拖动窗体 private bool isMove = false; //记录鼠标的位置 private Point point; 定义的变量 /// <summa ...
随机推荐
- dedecms 后台可以上传mp4,但无法选择
原文链接 找到 /include/dialog/select_media.php 找到rmvb,在其后面加 “|mp4” 即可. 1
- python 用正则处理日志实例
前提: 了解正则基本语法 import re with open('top10_xiaozhuang_net.log','r') as f1: #读取日志文件 subject=f1.rea ...
- 2003server r2 + sql 2000 sp4 环境配置
由于工作需求需要配置一个windows 2003 server r2 + sql 2000 sp4的环境: 一.2003server准备系统: msdn 下载 分清x86还是x64 一共有两个cd准备 ...
- victory-native的使用
Victory用于构建交互数据可视化的可组合React组件的生态系统 想写又不想写,真尴尬...
- Three.js学习笔记02
1.改变相机的位置,让物体移动 通过下面的代码改变相机的位置: camera.position.x =camera.position.x +1; 将相机不断的沿着x轴移动1个单位,也就是相机向右移动. ...
- 流媒体协议(二):RTMP协议
一.概念与摘要 RTMP协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和互动内容).RTMP提供了一套全双工的可靠的多路复用消息服务,类似于TCP协议[ ...
- [Swift]LeetCode421. 数组中两个数的最大异或值 | Maximum XOR of Two Numbers in an Array
Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...
- [Swift]LeetCode795. 区间子数组个数 | Number of Subarrays with Bounded Maximum
We are given an array A of positive integers, and two positive integers L and R (L <= R). Return ...
- [Swift]LeetCode819. 最常见的单词 | Most Common Word
Given a paragraph and a list of banned words, return the most frequent word that is not in the list ...
- Docker 删除所有无名称的镜像(悬空镜像)
我们在build镜像的过程中,可能会产生一些临时的不具有名称也没有作用的镜像他们的名称一般都是<none>,我们可以执行下面的命令将其清除掉: docker rmi $(docker im ...