欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

36.QT-解决无边框界面拖动卡屏问题(附带源码)

程序员文章站 2023-09-07 16:55:00
1.简介 看到很多才学QT的人都会问为啥无边框拖动为啥会花屏? 那是因为你每次拖动的过程中都一直在调用move()函数让QT重新绘制界面,如果资源过大,就会导致当前图形还未绘制完,便又重新改变坐标了,从而导致花屏. 2.如何解决我们参考其它软件,比如QQ,浏览器等,可以看到我们如果在拖动它们的时候, ......

1.简介

  • 看到很多才学qt的人都会问为啥无边框拖动为啥会花屏?

那是因为你每次拖动的过程中都一直在调用move()函数让qt重新绘制界面,如果资源过大,就会导致当前图形还未绘制完,便又重新改变坐标了,从而导致花屏.


2.如何解决
我们参考其它软件,比如qq,浏览器等,可以看到我们如果在拖动它们的时候,会出现一个虚线框.

  • 如下图所示,可以看到在白色背景下,拖出的虚线框是黑色的

36.QT-解决无边框界面拖动卡屏问题(附带源码)

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

36.QT-解决无边框界面拖动卡屏问题(附带源码)

显然这个虚线框会根据当前桌面的像素点而去取反(也就是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界面如下图所示
36.QT-解决无边框界面拖动卡屏问题(附带源码)

 

5.拖动时的效果图如下所示

36.QT-解决无边框界面拖动卡屏问题(附带源码)

 

6.针对win10系统的补充
大家都知道win10拖动的话,实现的是实线框,如下图所示:

36.QT-解决无边框界面拖动卡屏问题(附带源码)

如果想要这种效果,就将上面代码的paintevent(qpaintevent *)函数的i+=2改为i++即可.

修改后效果如下所示:
36.QT-解决无边框界面拖动卡屏问题(附带源码)

(ps:在win7下用这个实线框感觉挺别扭的)

 

 

上面的两个不同效果的demo源码地址如下所示: