36.QT-解决无边框界面拖动卡屏问题(附带源码)
程序员文章站
2023-09-07 16:55:00
1.简介 看到很多才学QT的人都会问为啥无边框拖动为啥会花屏? 那是因为你每次拖动的过程中都一直在调用move()函数让QT重新绘制界面,如果资源过大,就会导致当前图形还未绘制完,便又重新改变坐标了,从而导致花屏. 2.如何解决我们参考其它软件,比如QQ,浏览器等,可以看到我们如果在拖动它们的时候, ......
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 = 0); 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%2==0) w+=1; if(h%2==0) h+=1; 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 ) { m_image = qpixmap::grabwindow(qapplication::desktop()->winid()).toimage(); }
void dragshadow::paintevent(qpaintevent *) { int linecount=4; qcolor color; qpainter painter(this); painter.setbrush(qt::nobrush); qpen pen(qt::solidline); pen.setcolor(qt::black); pen.setwidthf(1); painter.setpen(pen); painter.drawpoint(0,0);
for(int current=0;current<linecount;current++) { for(int i=current;i<(this->width()-current);i+=2) //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-1+this->y(),color); pen.setcolor(color); painter.setpen(pen); painter.drawpoint(i,this->height()-current-1); //draw bottom } for(int i=current;i<(this->height()-current);i+=2) //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-1+this->x(),i+this->y(),color); pen.setcolor(color); painter.setpen(pen); painter.drawpoint(this->width()-current-1,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(255-color.red()); color.setblue(255-color.blue()); color.setgreen(255-color.green()); } else { color.setred(0); color.setblue(0); color.setgreen(0); } return ret; }
4.测试ui界面如下图所示
5.拖动时的效果图如下所示
6.针对win10系统的补充
大家都知道win10拖动的话,实现的是实线框,如下图所示:
如果想要这种效果,就将上面代码的paintevent(qpaintevent *)函数的i+=2改为i++即可.
修改后效果如下所示:
(ps:在win7下用这个实线框感觉挺别扭的)
上面的两个不同效果的demo源码地址如下所示:
上一篇: Vue学习之路第二十篇:Vue生命周期函数-组件创建期间的4个钩子函数
下一篇: 新买的杯子