Python开发之QT解决无边框界面拖动卡屏问题(附带源码)

顾言
顾言
发布时间:2026-10-14| 3人浏览过
原创

本文解析QT无边框窗口拖动时出现花屏的原因,并提供两种解决方案。重点介绍通过自定义DragShadow类实现类似系统拖动的虚线框效果,代码兼容Qt5及以上版本,并补充实线框模式的修改方法,附带完整源码下载。

1.简介

许多初学QT的开发者常遇到一个问题:为什么无边框窗口在拖动时会出现花屏现象?

这是因为在拖动过程中,程序不断调用move()函数强制QT重绘界面。当界面资源较大或渲染复杂时,图形尚未绘制完成,坐标却已改变,从而导致画面撕裂或花屏。

2.如何解决

参考QQ、浏览器等主流软件,拖动它们时会出现一个跟随鼠标的虚线框,而非实时重绘整个窗口。

如图所示,在白色背景下,拖出的虚线框显示为黑色。

而在黑色背景下,拖出的虚线框则显示为白色。

显然,这个虚线框的颜色是根据当前桌面像素点颜色进行取反处理得出的(即 255 - currentRGB)。实现这一效果主要有两种方法:

1) 调用Windows底层库来实现

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 )
{
   #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=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.针对实线框补充 对于某些Windows系统设置,实现的是实线框效果,如下图所示:

若希望获得这种实线框效果,只需将上述代码中paintEvent(QPaintEvent *)函数内的 i+=2 修改为 i++ 即可。

修改后的效果如下所示:

上述两种不同效果的Demo源码地址如下所示:

http://xiazai.jb51.net/202105/yuanma/DragTest_jb51.rar

以上就是QT解决无边框界面拖动卡屏问题的详细内容,更多关于QT无边框界面的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。