1. 程式人生 > >36.QT-解決無邊框界面拖動卡屏問題(附帶源碼)

36.QT-解決無邊框界面拖動卡屏問題(附帶源碼)

mil eight lac drag left 界面 的人 else 動手

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源碼還在上傳中,等下提供下載地址哦.

如果覺得不錯,點個贊唄~

36.QT-解決無邊框界面拖動卡屏問題(附帶源碼)