(一)Qt实现自定义控件的两种方式---提升法

系列文章目录

(一)Qt实现自定义控件的两种方式—提升法
(二)Qt实现自定义控件的两种方式—插件法



前言

在使用Qt设计师进行窗口设计时,我们会通过拖拽使用设计师中的原生控件来进行界面的开发,但有时候那些标准窗口部件无法满足我们的需求,这时候就需要我们进行自定义控件的使用。本系列文章主要讲述了使用提升法及插件法来实现自定义控件的使用,如有错误之处,欢迎大家批评指正。

项目效果

请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、提升一个Qt设计师界面类

(1)新建界面类

1.鼠标点击项目文件夹,右键Add New…
请添加图片描述

2.选择Qt设计师界面类请添加图片描述

3.这里我选择了Widget,点击下一步请添加图片描述

4.设置好自己的类名,点击下一步,直至完成
请添加图片描述

5.这边我要自定义的是一个图片开关,所以选择了在ui界面上添加了一个label,修改控件名称并调整合适大小
请添加图片描述

(2)添加资源文件

1.鼠标点击项目文件夹,右键Add New…,选择Qt Resource File,点击Choose…
请添加图片描述

2.设置好名称,点击下一步请添加图片描述3.可以看到要生成的文件为image.qrc,点击完成
请添加图片描述4.如图步骤,添加需要的png图片为资源文件
请添加图片描述

(3)初始化ui界面label样式

1.选中label控件,找到属性中的styleSheet,添加资源,选择image,点击OK
请添加图片描述

2.选择资源文件,这边选择checkoff.png,点击OK
请添加图片描述

3.看到出现下列界面(有效样式表),点击OK请添加图片描述

4.这里将label的文本置空,同时修改控件的objectName请添加图片描述

(4)主界面进行提升

1.回到widget.ui,界面中添加一个widget控件,修改名称后选中控件,右键提升为…请添加图片描述

2.如图,新建提升的类,这里输入前面添加的ui界面设计师类名,点击添加请添加图片描述

3.勾选中刚刚添加的ImageSwitch类,选择提升请添加图片描述

4.这里可以看到widget_switch控件已经成功提升为ImageSwitch类
请添加图片描述

5.这边已经可以进行编译运行,可以看到程序运行后就会出现之前添加的默认关闭的一个图片,这里我们可以重写ImageLabel类的鼠标按下事件来实现图片的切换。
主要代码如下:

void ImageSwitch::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<"event:"<<event;
    if(switchFlag)
    {
        switchFlag = !switchFlag;
        ui->lb_switch->setStyleSheet("image: url(:/imageswitch/checkoff.png);");
    }
    else
    {
        switchFlag = !switchFlag;
        ui->lb_switch->setStyleSheet("image: url(:/imageswitch/checkon.png);");
    }
}

二、提升一个C++类

(1)新建C++类

1.鼠标点击项目文件夹,右键Add New…,选择C++ Class,点击Choose…
请添加图片描述

2.这里输入类名,并选择你需要的Base class,这里我的是QWidget,点击下一步
请添加图片描述

(2)主界面进行提升

1.主界面widget.ui添加一个widget控件,修改名称后选中控件,右键提升为…,新建提升的类,点击添加
请添加图片描述

2.勾选中刚刚添加的Battery类,选择提升
请添加图片描述

3.这里可以看到widget_battery控件已经成功提升为Battery类
请添加图片描述

4.这里添加的C++类是不带ui界面的,所以需要自己在Battery类中使用代码来实现各种效果,本例中重写了paintEvent事件来进行界面的变化,该类实例来自feiyangqingyun大佬的Gitee主页,更多详情可点击进入大佬的Gitee进行查看下载,非常的nice。

主要代码如下:

void Battery::paintEvent(QPaintEvent *)
{
    //绘制准备工作,启用反锯齿
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //绘制边框
    drawBorder(&painter);
    //绘制背景
    drawBg(&painter);
    //绘制头部
    drawHead(&painter);
}

void Battery::drawBorder(QPainter *painter)
{
    painter->save();

    double headWidth = width() / 15;
    double batteryWidth = width() - headWidth;

    //绘制电池边框
    QPointF topLeft(borderWidth, borderWidth);
    QPointF bottomRight(batteryWidth, height() - borderWidth);
    batteryRect = QRectF(topLeft, bottomRight);

    painter->setPen(QPen(borderColorStart, borderWidth));
    painter->setBrush(Qt::NoBrush);
    painter->drawRoundedRect(batteryRect, borderRadius, borderRadius);

    painter->restore();
}

void Battery::drawBg(QPainter *painter)
{
    if (value == minValue) {
        return;
    }

    painter->save();

    QLinearGradient batteryGradient(QPointF(0, 0), QPointF(0, height()));
    if (currentValue <= alarmValue) {
        batteryGradient.setColorAt(0.0, alarmColorStart);
        batteryGradient.setColorAt(1.0, alarmColorEnd);
    } else {
        batteryGradient.setColorAt(0.0, normalColorStart);
        batteryGradient.setColorAt(1.0, normalColorEnd);
    }

    int margin = qMin(width(), height()) / 20;
    double unit = (batteryRect.width() - (margin * 2)) / 100;
    double width = currentValue * unit;
    QPointF topLeft(batteryRect.topLeft().x() + margin, batteryRect.topLeft().y() + margin);
    QPointF bottomRight(width + margin + borderWidth, batteryRect.bottomRight().y() - margin);
    QRectF rect(topLeft, bottomRight);

    painter->setPen(Qt::NoPen);
    painter->setBrush(batteryGradient);
    painter->drawRoundedRect(rect, bgRadius, bgRadius);

    painter->restore();
}

void Battery::drawHead(QPainter *painter)
{
    painter->save();

    QPointF headRectTopLeft(batteryRect.topRight().x(), height() / 3);
    QPointF headRectBottomRight(width(), height() - height() / 3);
    QRectF headRect(headRectTopLeft, headRectBottomRight);

    QLinearGradient headRectGradient(headRect.topLeft(), headRect.bottomLeft());
    headRectGradient.setColorAt(0.0, borderColorStart);
    headRectGradient.setColorAt(1.0, borderColorEnd);

    painter->setPen(Qt::NoPen);
    painter->setBrush(headRectGradient);
    painter->drawRoundedRect(headRect, headRadius, headRadius);

    painter->restore();
}

总结

本文主要讲述了提升法来进行自定义控件的实现,并分别讲述了Qt设计师界面类以及不带界面的C++类来进行提升的方法,提升法还是比较简单的,很多时候想要实现各种控件效果还是需要使用代码,这里就要求熟悉对各事件的基本处理,以便于实现你想要的效果。

本项目完整代码百度网盘链接:https://pan.baidu.com/s/1lWUL-ziW-aRahKrV0ge9sQ
提取码:xxcj

下一篇:(二)Qt实现自定义控件的两种方式—插件法


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考博客:Qt编写项目作品大全

下面是一段用汇编语言实现的模拟琴键的代码,使用数字键1~8模拟琴键1~1(高音),并通过PC扬声器发出相应的音调: ``` .MODEL SMALL .STACK 100H .DATA NOTE1 DB 0C9H ;音调1的频率值 NOTE2 DB 0D1H ;音调2的频率值 NOTE3 DB 0D9H ;音调3的频率值 NOTE4 DB 0E1H ;音调4的频率值 NOTE5 DB 0E9H ;音调5的频率值 NOTE6 DB 0F1H ;音调6的频率值 NOTE7 DB 0F9H ;音调7的频率值 NOTE8 DB 101H ;音调8的频率值 .CODE MAIN PROC MOV AX, @DATA MOV DS, AX ;初始化数据段寄存器 MOV DX, 61H MOV AL, 0B6H OUT DX, AL ;初始化PC扬声器控制寄存器 WAIT: IN AL, 60H CMP AL, 31H JE PLAY1 CMP AL, 32H JE PLAY2 CMP AL, 33H JE PLAY3 CMP AL, 34H JE PLAY4 CMP AL, 35H JE PLAY5 CMP AL, 36H JE PLAY6 CMP AL, 37H JE PLAY7 CMP AL, 38H JE PLAY8 JMP WAIT PLAY1: MOV AL, NOTE1 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY2: MOV AL, NOTE2 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY3: MOV AL, NOTE3 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY4: MOV AL, NOTE4 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY5: MOV AL, NOTE5 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY6: MOV AL, NOTE6 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY7: MOV AL, NOTE7 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY8: MOV AL, NOTE8 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT MAIN ENDP END MAIN ``` 在这段代码中,我们使用了8254芯片控制PC扬声器的工作频率,通过按下数字键1~8来选择不同的音调,同时使用了循环来不断等待键盘输入。注意,这段代码只能在实模式下运行,而且需要在DOS或类DOS操作系统下运行。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值