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);
  1. 選擇更平滑的圖像縮放算法。
    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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章