自学内容网 自学内容网

开源控件:Qt/C++自定义异形窗口和颜色选择器 【工程源码联系博主索要】

使用 Qt 和 C++ 实现一个异形窗口和自定义颜色选择器的过程。


在这里插入图片描述
在这里插入图片描述

1. CustomShapeWidgetUi

该类实现了一个具有自定义形状和颜色选择功能的窗口。

构造函数 CustomShapeWidgetUi
CustomShapeWidgetUi::CustomShapeWidgetUi(const QString &imagePath, QDialog *parent)
    : QDialog(parent), backgroundPixmap(imagePath), ui(new Ui::CustomShapeWidgetUi)
{
    ui->setupUi(this);
    
    // 设置窗口无边框,透明背景
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_TranslucentBackground);
    
    // 设置窗口形状
    setWindowShape(imagePath);
    resize(backgroundPixmap.size());  // 调整窗口大小为图片大小

    // 设置颜色选择器的响应
    connect(ui->colorPicker, &CustomColorPicker::colorChanged, [=](QColor color) {
        ui->colorEdit->setText(color.name());
    });
    
    // 设置关闭和确认按钮的功能
    connect(ui->cancelButton, &QToolButton::clicked, this, &QDialog::reject);
    connect(ui->okButton, &QToolButton::clicked, this, &QDialog::accept);
}
  • 无边框和透明背景Qt::FramelessWindowHint 移除窗口边框,Qt::WA_TranslucentBackground 设置背景透明,配合异形窗口实现。
  • 形状设置:调用 setWindowShape,根据图片的非透明区域设置窗口形状。
  • 颜色选择colorChanged 信号和槽函数更新 colorEdit 显示颜色的十六进制值。
  • 按钮功能:关闭按钮和确认按钮使用 rejectaccept 信号关闭对话框。
重写 paintEvent
void CustomShapeWidgetUi::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(0, 0, backgroundPixmap);
    QWidget::paintEvent(event);  // 调用基类的 paintEvent 保持设计师元素的绘制
}

使用 QPainter 绘制背景图片,并调用基类的 paintEvent 保持其他 UI 元素的正常绘制。

setWindowShape 方法
void CustomShapeWidgetUi::setWindowShape(const QString &imagePath)
{
    QPixmap pixmap(imagePath);
    QRegion region;

    // 根据图片的透明区域生成 QRegion
    for (int y = 0; y < pixmap.height(); ++y) {
        for (int x = 0; x < pixmap.width(); ++x) {
            if (QColor(pixmap.toImage().pixel(x, y)).alpha() > 0) {
                region += QRegion(x, y, 1, 1);
            }
        }
    }
    setMask(region);
}

这里通过遍历图片像素点,判断每个像素的透明度,以生成自定义窗口形状的 QRegion,并将该 QRegion 应用到窗口的遮罩 (setMask) 上。


2. CustomColorPicker

CustomColorPicker 类实现了一个自定义颜色选择器。

构造函数 CustomColorPicker
CustomColorPicker::CustomColorPicker(QWidget *parent)
    : QWidget(parent), brightness(255), updatingBrightness(false)
{
    setFixedSize(220, 220);  // 设置控件大小
    color = QColor::fromHsv(0, 255, brightness);
    hueSatPoint = QPoint(0, height());
}
  • 固定大小:颜色选择器被设置为 220x220。
  • 初始颜色:默认颜色设置为最大亮度的红色,亮度设为 255。
  • 位置初始化hueSatPoint 定位到左下角。
paintEvent 方法
void CustomColorPicker::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    // 绘制色相-饱和度选择区域
    QImage hueSatImage(width() - 30, height(), QImage::Format_RGB32);
    for (int x = 0; x < hueSatImage.width(); ++x) {
        for (int y = 0; y < hueSatImage.height(); ++y) {
            int hue = static_cast<int>((360.0 * x) / hueSatImage.width());
            int saturation = static_cast<int>((255.0 * (hueSatImage.height() - y)) / hueSatImage.height());
            QColor tempColor = QColor::fromHsv(hue, saturation, brightness);
            hueSatImage.setPixelColor(x, y, tempColor);
        }
    }
    painter.drawImage(0, 0, hueSatImage);

    // 绘制亮度滑条
    QLinearGradient gradient(0, 0, 0, height());
    gradient.setColorAt(0, QColor::fromHsv(color.hue(), color.saturation(), 255));
    gradient.setColorAt(1, QColor::fromHsv(color.hue(), color.saturation(), 0));
    painter.fillRect(width() - 20, 0, 20, height(), gradient);

    // 绘制选中点指示器
    painter.setPen(QPen(Qt::black, 2));
    painter.setBrush(Qt::NoBrush);
    painter.drawRect(hueSatPoint.x() - 10, hueSatPoint.y() - 10, 20, 20);

    // 绘制亮度滑条上的指示器
    int brightnessY = height() - (brightness * height() / 255);
    painter.drawRect(width() - 20, brightnessY - 5, 20, 10);
}
  • 色相-饱和度区域:通过 QImage 绘制 2D 色相-饱和度区域,亮度保持不变。
  • 亮度滑条:设置渐变颜色,用当前色相和饱和度生成亮度变化效果。
  • 指示器:指示器在色相-饱和度区域和亮度滑条上,展示当前选中的颜色。
鼠标事件处理
void CustomColorPicker::mousePressEvent(QMouseEvent *event) {
    if (event->x() < width() - 30) {
        hueSatPoint = event->pos();
        updatingBrightness = false;
        updateColorFromHueSat();
    } else {
        updatingBrightness = true;
        updateColorFromBrightness(event->y());
    }
}

void CustomColorPicker::mouseMoveEvent(QMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
        if (updatingBrightness) {
            updateColorFromBrightness(event->y());
        } else if (event->x() < width() - 30) {
            hueSatPoint = event->pos();
            updateColorFromHueSat();
        }
    }
}
  • 点击:判断点击的位置,是色相-饱和度区域还是亮度滑条。
  • 拖动:在点击的区域内拖动时,更新相应的颜色。
更新颜色的方法
void CustomColorPicker::updateColorFromHueSat()
{
    int hue = static_cast<int>((360.0 * hueSatPoint.x()) / (width() - 30));
    int saturation = static_cast<int>((255.0 * (height() - hueSatPoint.y())) / height());
    hue = qBound(0, hue, 359);
    saturation = qBound(0, saturation, 255);

    color.setHsv(hue, saturation, brightness);
    emit colorChanged(color);
    update();
}

void CustomColorPicker::updateColorFromBrightness(int y)
{
    brightness = qBound(0, 255 * (height() - y) / height(), 255);
    color.setHsv(color.hue(), color.saturation(), brightness);
    emit colorChanged(color);
    update();
}
  • 色相和饱和度更新:根据 hueSatPoint 计算色相和饱和度,确保其在合理范围内 (qBound)。
  • 亮度更新:根据鼠标在亮度滑条上的位置更新亮度。


原文地址:https://blog.csdn.net/chenai886/article/details/143769389

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!