QT 使用QPixmap自定义光标 缩放图像模糊问题

QT中定义光标可以使用 Qt::CursorShape 预定义 的光标,也可以使用 QBitmap 和 QPixmap 自己绘制光标。QBitmap 只有黑白2色,QPixmap可以绘制彩色光标。使用QPixmap绘制光标时会出现光标边界模糊的情况,尤其是显示器设置缩放比例时,光标更是模糊。

出现模糊的原因有2个:

  1. QPixmap 投射到屏幕时自动进行了缩放,出现了图像缩放失真;
  2. 缩放时默认采用的算法导致图像信息丢失;

解决办法:

  1. 获取屏幕的缩放比例。

    复制代码
     // 获取主屏幕的缩放比例
     qreal screenRatio = QGuiApplication::primaryScreen()->devicePixelRatio();
     qreal width = 32;
     qreal height = 32;
     // 创建位图,根据屏幕缩放比例调整图形大小
     QPixmap pixmap(width*screenRatio, height*screenRatio);
     pixmap.fill(Qt::transparent);
     pixmap.setDevicePixelRatio(screenRatio);
  2. 选择更平滑的图像缩放算法。

    复制代码
     QPainter painter(&pixmap);
     painter.setRenderHint(QPainter::Antialiasing);
     // 出现缩放时选择更平滑的缩放算法 
     painter.setRenderHint(QPainter::SmoothPixmapTransform);

完整的自定义光标代码:

复制代码
/**
 * @brief 绘制光标
 * @param width 光标宽带
 * @param height 光标高度
 */
void AdjustPoint::createCursor(qreal angleOffset)
{
    qreal width = 32;
    qreal height = 32;
    // 创建位图,根据屏幕缩放比例调整图形大小
    QPixmap pixmap(width*screenRatio, height*screenRatio);
    pixmap.fill(Qt::transparent);
    pixmap.setDevicePixelRatio(screenRatio);
    // 绘制
    QPainter painter(&pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
    painter.setRenderHint(QPainter::VerticalSubpixelPositioning);
    painter.setRenderHint(QPainter::LosslessImageRendering);
    qreal winWidth = 20;
    qreal winHeight = 8;
    painter.setViewport((width - winWidth) / 2,(height - winHeight) / 2,
                        winWidth,winHeight);
    painter.setWindow(-winWidth / 2,-winHeight / 2,winWidth,winHeight);
    // 旋转光标图像到指定位置
    painter.rotate(cursorAngle + angleOffset);
    QPen pen(Qt::NoPen);
    painter.setPen(pen);
    QBrush brush(Qt::SolidPattern);
    brush.setColor(QColor(borderColor));
    painter.setBrush(brush);
    painter.drawPath(createArrowPath(winHeight+2, winWidth+1));

    brush.setColor(QColor(cursorColor));
    painter.setBrush(brush);
    painter.drawPath(createArrowPath(winHeight, winWidth));

    painter.end();

    // 创建光标,并设置
    QCursor customCursor(pixmap);
    setCursor(customCursor);
}

QPainterPath AdjustPoint::createArrowPath(qreal winHeight, qreal winWidth)
{
    QPainterPath path;
    qreal x1 = -winWidth / 2;
    qreal x2 = x1 + winHeight / 2;
    qreal x3 = -x2;
    qreal x4 = -x1;
    qreal y1 = -winHeight / 2;
    qreal y2 = -winHeight * 1 /8;
    qreal y3 = -y2;
    qreal y4 = -y1;
    path.moveTo(x1, 0);
    path.lineTo(x2,y1);
    path.lineTo(x2, y2);
    path.lineTo(x3, y2);
    path.lineTo(x3,y1);
    path.lineTo(x4, 0);
    path.lineTo(x3, y4);
    path.lineTo(x3, y3);
    path.lineTo(x2, y3);
    path.lineTo(x2, y4);
    path.lineTo(x1, 0);

    path.closeSubpath();

    return path;
}
相关推荐
galaxy_strive1 小时前
绘制饼图详细过程
开发语言·c++·qt
委婉待续12 小时前
Qt的学习(一)
开发语言·qt·学习
笨笨马甲12 小时前
Qt Quick Layout功能及架构
开发语言·qt
feiyangqingyun13 小时前
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
c++·qt·udp·gb28181
jllws113 小时前
Qt学习及使用_第1部分_认识Qt---学习目的及技术准备
qt·c++框架
到点就困告14 小时前
海康工业相机SDK二次开发(VS+QT+海康SDK+C++)
数码相机·qt·海康
唐墨1231 天前
android与Qt类比
android·开发语言·qt
道剑剑非道1 天前
QT开发技术【ffmpeg + QAudioOutput】音乐播放器 完善
开发语言·qt·ffmpeg
不惑_1 天前
用 PyQt5 打造一个可视化 JSON 数据解析工具
开发语言·qt·json
誰能久伴不乏1 天前
Qt 开发中的父类与父对象的区别和父对象传递:如何选择 `QWidget` 或 `QObject`?
java·开发语言·qt