整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Python入坑系列-pyside6桌面编程之掌握控

Python入坑系列-pyside6桌面编程之掌握控件类使用技巧

过本文章,可以掌握以下内容:

  1. Pyside6控件类的属性与方法
  2. Pyside6的控件为什么看不到实现过程
  3. Pyside6如何查看相关类的属性和方法作用

对于一个Python小白来说,在学习Pyside6的控件时,照着网上的一些示例,可以将很快将控件运行出来。但在看控件python源代码时,却很是迷惑,本文就以QWidget为例,进行展开解读。

QWidget python源代码

如上图是QWidget部分Python源代码,你能看懂多少?

  1. 大部分方法都包含self参数,其作用是什么?
  2. 为什么方法体很多都是空实现,用pass或者简单返回,并未看到具体实现,为何能正常使用方法?
  3. 定义的枚举和属性都是none,为何能使用枚举类,以及枚举类的枚举值在哪?

一、Pyside6类的属性与方法

要了解控件大部分方法为什么都包含self参数,只需要了解Python类、实例的属性和方法即可。

实例属性与类属性

类的对象,就是类的一个实例。类的实例属性被对象所有,包含在每个对象之中,不同的对象之间,互不干扰。类的类属性被类所有,被包含在类中,是所有的类对象共享。一般情况下,实例属性会在__init__ 方法中声明并初始化,并且使用self 来绑定。而类属性是在类作用域中被声明,并且不使用self 来绑定。

python类、实例与属性关系

实例方法,类方法,静态方法

Python 类中有三种方法:

  • 实例方法:属于对象,方法中都有一个self 参数(代表对象本身)。实例方法只能由对象调用,不能通过类名访问。实例方法中可以访问实例属性和类属性。
  • 类方法:属于类,方法中都有一个cls 参数(代表类本身)。类方法即可以通过类名访问,也可以通过对象访问,类方法中只能访问类属性,不能访问实例属性。定义类方法需要用到装饰器@classmethod
  • 静态方法:没有self 参数,也没有cls 参数。因此,在静态方法中,既不能访问类属性,也不能访问实例属性。静态方法可以使用类名访问,也可以使用对象访问。定义静态方法需要用到装饰器@staticmethod

注意:Python 解释器在构造类与对象时,类是先于对象产生的。因此,类属性与类方法是先于实例属性与实例方法产生的。所以当类方法产生时,还没有实例属性,因此,类方法中不能访问实例属性。

专有方法

以双下划线__开头且结尾的方法__xxx__,就是专有方法,也称魔法方法。这些方法都被Python 赋予了特殊的含义,用户可以根据需要,来实现这些方法。比如QWidget类重写了Python object的方法:

  • __delattr__:Python 中的一个特殊方法,用于自定义删除对象属性的行为。当你使用执行del obj.attribute语句删除对象的属性时,__delattr__ 方法会被调用,
  • __init__:负责初始化实例,在实例创建之后调用。它是一个实例方法,用于设置实例属性和执行其他初始化操作
  • __new__:负责创建实例,在实例化对象时首先调用。它是一个静态方法,返回类的一个新实例
  • __repr__:返回对象的字符串表示,通常用于调试
  • __setattr__:用于设置对象的属性值,在赋值时自动调用

二、Pyside6的调用过程

在开发Pyside6的时候,很多源代码只包含方法名、pass 关键字和空的枚举类,那pyside6的代码在实例化以及调用方法时,整个过程是怎样的呢。

在 PySide6 中,Python和Qt的C++库之间的关联是通过绑定技术实现的。具体来说,PySide6使用Shiboken,这是一种绑定生成工具,它自动将C++类和函数映射到Python。通过这种方式,PySide6可以在Python中使用Qt的功能。关键技术概念:

  • Shiboken:这是一个自动化工具,用于将 C++ 代码绑定到Python。Shiboken分析Qt 的 C++头文件,生成相应的 Python 绑定代码。这使得我们可以在 Python 中使用 Qt 的 C++ 类和方法。
  • 类型转换:Shiboken 处理C++和Python类型之间的转换。对于每个C++类型,Shiboken生成相应的Python类型包装器,并处理两者之间的数据转换。
  • 方法和属性绑定:Shiboken生成的绑定代码将C++类的方法和属性映射到Python类。这包括普通方法、虚方法、信号和槽。

在 PySide6中,staticMetaObject是一个静态属性,存在于所有继承自QObject的类中。它的主要作用是提供对Qt元对象系统(Meta-Object System)的访问。这个元对象系统在 Qt 中用于实现信号与槽机制、属性系统以及其他反射(reflection)功能。

元对象系统(Meta-Object System)

Qt 的元对象系统是一种运行时类型信息系统,提供以下功能:

  • 信号与槽机制:用于对象之间的通信。
  • 动态属性系统:允许在运行时查询和操作对象的属性。
  • 反射:允许在运行时查询类的元数据(例如类名、方法列表等)。

staticMetaObject 的作用

staticMetaObject 是一个包含类的元数据的对象,提供了对以下内容的访问:

  • 类名:对象的类名。
  • 信号和槽:类中定义的信号和槽。
  • 属性:类中定义的属性。
  • 方法:类中定义的方法。

staticMetaObject在PySide6中提供了对Qt元对象系统的访问,允许在运行时查询类的元数据。它是实现动态属性访问、信号与槽机制以及反射功能的基础,极大地增强了代码的灵活性和动态特性。

三、正确使用Pyside6控件类

如何正确使用Pyside6的控件,我们需要了解Qt for Python相关文档

访问QT官网地址

访问官网:https://doc.qt.io/qtforpython-6/search.html,选择对应pyside的版本。

QT官网

搜索控件类

比如想了解Qwidget类,在上面搜索框中输入关键字回车。

控件类文档

查看控件类信息

基于上面搜索结果,点击进去,可以看到类的详细信息,包括类的继承关系、属性、方法、枚举类、信号。可以通过右边列表快速定位属性和方法

查找控件类

针对枚举类,拷贝Python源代码到界面搜索,即可看到使用方法,如Qwidget类定义的RenderFlag=None,可以搜索RenderFlag,就可以知道有哪些枚举值。

枚举类

、前言

随着移动互联网的盛行,现在手机APP大行其道,每个人的手机没有十几个APP都不好意思说自己是现代人,各种聊天、购物、直播、小视频等APP,有个陌生人社交的APP叫探探,本人用过几次,当然不是去为了找对象,而是纯粹为了好玩研究下他的U设计和软件逻辑流程等,其中有个雷达控件,单击以后可以搜索附近的异性进行配对,这个雷达控件的效果蛮好的,于是手痒琢磨着用Qt来实现一个,毕竟自己写了150多个控件了,已经上瘾了,对各种效果都如鱼得水,看到各种效果都不自然的想到编码思路等。
这个控件的核心其实就是外围的那个扫描圈和发散的扫描线,中间变大变小恢复正常的圆形头像,外围的扫描圈采用锥形渐变颜色,通过透明度控制形成扫描效果,核心方法就是drawPie,至于扩散圈,需要识别到单击以后将扩散圈存入队列,因为可能会单击多次,产生多个扩散圈,至于中间头像的动态效果,采用三个QPropertyAnimation来实现,一个负责变大,一个负责变小,一个负责恢复正常,然后三个动画加入到QSequentialAnimationGroup动画序列中,按照顺序执行。

二、实现的功能

  • 1:可设置中间图像
  • 2:可设置图像的边框宽度+边框颜色,产生圆形图像效果
  • 3:可设置扫描线的最大半径
  • 4:可设置扫描线的边框宽度
  • 5:可设置扩散圈的线条宽度
  • 6:可设置扫描线的每次移动的步长
  • 7:可设置扩散圈的每次移动的步长
  • 8:可设置扫描线的颜色
  • 9:可设置扩散圈的颜色

三、效果图

四、头文件代码

#ifndef SCANTANTAN_H
#define SCANTANTAN_H

/**
 * 探探雷达控件 作者:东门吹雪(QQ:709102202) 整理:feiyangqingyun(QQ:517216493) 2019-10-01
 * 1:可设置中间图像
 * 2:可设置图像的边框宽度+边框颜色,产生圆形图像效果
 * 3:可设置扫描线的最大半径
 * 4:可设置扫描线的边框宽度
 * 5:可设置扩散圈的线条宽度
 * 6:可设置扫描线的每次移动的步长
 * 7:可设置扩散圈的每次移动的步长
 * 8:可设置扫描线的颜色
 * 9:可设置扩散圈的颜色
 */

#include <QWidget>

class QSequentialAnimationGroup;

#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif

class QDESIGNER_WIDGET_EXPORT ScanTanTan : public QWidget
#else
class ScanTanTan : public QWidget
#endif

{
    Q_OBJECT
    Q_PROPERTY(QPixmap image READ getImage WRITE setImage)
    Q_PROPERTY(int imageBorderWidth READ getImageBorderWidth WRITE setImageBorderWidth)
    Q_PROPERTY(QColor imageBorderColor READ getImageBorderColor WRITE setImageBorderColor)

    Q_PROPERTY(int scanRadius READ getScanRadius WRITE setScanRadius)
    Q_PROPERTY(int scanWidth READ getScanWidth WRITE setScanWidth)
    Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth)

    Q_PROPERTY(int scanStep READ getScanStep WRITE setScanStep)
    Q_PROPERTY(int ringStep READ getRingStep WRITE setRingStep)

    Q_PROPERTY(QColor scanColor READ getScanColor WRITE setScanColor)
    Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor)

public:
    struct RingData {
        int radius;     //半径
        float width;    //画笔粗细
        int alpha;      //透明度
    };

    explicit ScanTanTan(QWidget *parent=0);

protected:
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);
    void drawScan(QPainter *painter);
    void drawRing(QPainter *painter);
    void drawImage(QPainter *painter);

private slots:
    void changeScan();
    void changeRing();
    void updateImage(const QVariant &value);
    double twoPtDistance(const QPointF &pt1, const QPointF &pt2);

private:
    QPixmap image;          //中间图片
    int imageBorderWidth;   //图片边框宽度
    QColor imageBorderColor;//图片边框颜色

    int scanRadius;         //扫描线最大半径
    int scanWidth;          //扫描线边框宽度
    int ringWidth;          //扩散圈线条宽度

    int scanStep;           //扫描线每次移动的步长
    int ringStep;           //扩散圈每次移动的步长

    QColor scanColor;       //扫描线颜色
    QColor ringColor;       //扩散圈颜色

    bool isPressed;         //鼠标是否按下
    int ringRadius;         //扩散圈半径
    int imageRadius;        //图片半径
    int scanDeg;            //当前扫描线角度

    //扩散圈集合,鼠标可能按下多次则产生多个扩散圈,用队列存起来
    QList<RingData> rings;
    //动画组合,用于中间图片的变大放小
    QSequentialAnimationGroup *animationGroup;

public:
    QPixmap getImage()          const;
    int getImageBorderWidth()   const;
    QColor getImageBorderColor()const;

    int getScanRadius()         const;
    int getScanWidth()          const;
    int getRingWidth()          const;

    int getScanStep()           const;
    int getRingStep()           const;

    QColor getScanColor()       const;
    QColor getRingColor()       const;

    QSize sizeHint()            const;
    QSize minimumSizeHint()     const;

public Q_SLOTS:
    //设置图片+图片边框宽度+图片边框颜色
    void setImage(const QPixmap &image);
    void setImageBorderWidth(int imageBorderWidth);
    void setImageBorderColor(const QColor &imageBorderColor);

    //设置扫描线最大半径+扫描线边框宽度+扩散圈线条宽度
    void setScanRadius(int scanRadius);
    void setScanWidth(int scanWidth);
    void setRingWidth(int ringWidth);

    //设置扫描线步长+扩散圈步长
    void setScanStep(int scanStep);
    void setRingStep(int ringStep);

    //设置扫描线颜色+扩散圈颜色
    void setScanColor(const QColor &scanColor);
    void setRingColor(const QColor &ringColor);
};

#endif // SCANTANTAN_H


【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:「链接」

五、核心代码

void ScanTanTan::paintEvent(QPaintEvent *)
{
    int width=this->width();
    int height=this->height();
    int side=qMin(width, height);

    //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);

    //绘制扫描线
    drawScan(&painter);
    //绘制扩散圈
    drawRing(&painter);
    //绘制中间图片
    drawImage(&painter);
}

void ScanTanTan::drawScan(QPainter *painter)
{
    painter->save();

    //锥形渐变颜色,通过透明度控制形成扫描效果
    QConicalGradient conicalGradient(0, 0, scanDeg);
    QColor color=scanColor;
    color.setAlpha(50);
    conicalGradient.setColorAt(0, color);
    color.setAlpha(0);
    conicalGradient.setColorAt(1, color);

    //设置画笔画刷
    QPen pen;
    pen.setWidth(scanWidth);
    pen.setBrush(conicalGradient);
    painter->setPen(pen);
    painter->setBrush(conicalGradient);

    //绘制饼圆
    QRect rect(-scanRadius, -scanRadius, scanRadius * 2, scanRadius * 2);
    painter->drawPie(rect, scanDeg * 16, 360 * 16);

    painter->restore();
}

void ScanTanTan::drawRing(QPainter *painter)
{
    painter->save();
    painter->setBrush(Qt::NoBrush);

    //绘制所有扩散圈,扩散圈其实就是个没有背景颜色的圆形
    for (int i=0; i < rings.count(); i++) {
        RingData ring=rings.at(i);
        int radius=ring.radius;
        float width=ring.width;
        int alpha=255 - ring.alpha;
        QColor color=ringColor;
        color.setAlpha(alpha);

        QPen pen;
        pen.setWidthF(width);
        pen.setColor(color);
        painter->setPen(pen);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    }

    painter->restore();
}

void ScanTanTan::drawImage(QPainter *painter)
{
    painter->save();

    //设置圆形遮罩路径,产生圆形头像效果
    QPainterPath path;
    path.addEllipse(QPoint(0, 0), imageRadius, imageRadius);
    painter->setClipPath(path);

    //绘制图片
    QRect rect(-imageRadius, -imageRadius, imageRadius * 2, imageRadius * 2);
    painter->drawPixmap(rect, image);

    //绘制图片边缘圆形
    QPen pen;
    pen.setWidth(imageBorderWidth);
    pen.setColor(imageBorderColor);
    painter->setPen(pen);
    painter->setBrush(Qt::NoBrush);

    //以下两种方法二选一,其实绘制360度的圆弧=绘制无背景的圆形
    //painter->drawArc(rect, 0, 360 * 16);
    painter->drawEllipse(rect);

    painter->restore();
}

六、控件介绍

  1. 超过160个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
  2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
  3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.13的任何Qt版本,支持mingw、msvc、gcc等编译器,支持任意操作系统比如windows+linux+mac+嵌入式linux等,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
  4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
  5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
  6. 每个控件默认配色和demo对应的配色都非常精美。
  7. 超过130个可见控件,6个不可见控件。
  8. 部分控件提供多种样式风格选择,多种指示器样式选择。
  9. 所有控件自适应窗体拉伸变化。
  10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
  11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
  12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
  13. 所有控件最后生成一个动态库文件(dll或者so等),可以直接集成到qtcreator中拖曳设计使用。
  14. 目前已经有qml版本,后期会考虑出pyqt版本,如果用户需求量很大的话。
  15. 自定义控件插件开放动态库使用(永久免费),无任何后门和限制,请放心使用。
  16. 目前已提供26个版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
  17. 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
  18. Qt入门书籍推荐霍亚飞的《Qt Creator快速入门》《Qt5编程入门》,Qt进阶书籍推荐官方的《C++ GUI Qt4编程》。
  19. 强烈推荐程序员自我修养和规划系列书《大话程序员》《程序员的成长课》《解忧程序员》,受益匪浅,受益终生!
  20. SDK地址:https://gitee.com/feiyangqingyun/QUCSDK

原文链接:https://www.cnblogs.com/feiyangqingyun/p/11632586.html

【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:Qt资料领取(视频教程+文档+代码+项目实战)

、前言

代码行数统计主要用来统计项目中的所有文件的代码行数,其中包括空行、注释行、代码行,可以指定过滤拓展名,比如只想统计.cpp的文件,也可以指定文件或者指定目录进行统计。写完这个工具第一件事情就是统计了一下自己写过的最大的项目大概多少行代码,看下是不是传说中的一行代码一块钱,这个最大的项目从2010年开始的,到现在差不多快10年了,是自己在现在公司写过的最大的项目,一直在升级更新完善,途中重构过两次,大的结构改动,统计了下好像有15W行左右的代码,纯代码大概在10W,其余是空行和注释行,着实把自己吓了一跳,还算是中型项目了,然后又统计了下自定义控件的所有代码,我勒个去,总代码23W行,纯代码17W行呢,哎呀我去!

开源地址:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo

二、实现的功能

  • 1:可分别统计代码行/空行/注释行
  • 2:支持指定过滤拓展名
  • 3:支持指定文件或者指定目录进行统计
  • 4:分步显示统计结果,不卡主界面
  • 5:分别展示每个统计过的文件的大小/总行数/代码行数等

三、效果图

四、头文件代码

#ifndef FRMCOUNTCODE_H
#define FRMCOUNTCODE_H

#include <QWidget>

namespace Ui {
class frmCountCode;
}

class frmCountCode : public QWidget
{
    Q_OBJECT

public:
    explicit frmCountCode(QWidget *parent=0);
    ~frmCountCode();

private:
    Ui::frmCountCode *ui;
    QStringList listFile;

private:
    void initForm();
    bool checkFile(const QString &fileName);
    void countCode(const QString &filePath);
    void countCode(const QStringList &files);
    void countCode(const QString &fileName, int &lineCode, int &lineBlank, int &lineNotes);

private slots:
    void on_btnOpenFile_clicked();
    void on_btnOpenPath_clicked();
    void on_btnClear_clicked();
};

#endif // FRMCOUNTCODE_H


【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:Qt资料领取(视频教程+文档+代码+项目实战)

五、核心代码

#pragma execution_character_set("utf-8")

#include "frmcountcode.h"
#include "ui_frmcountcode.h"
#include "qfile.h"
#include "qtextstream.h"
#include "qfiledialog.h"
#include "qfileinfo.h"
#include "qdebug.h"

frmCountCode::frmCountCode(QWidget *parent) : QWidget(parent), ui(new Ui::frmCountCode)
{
    ui->setupUi(this);
    this->initForm();
    on_btnClear_clicked();
}

frmCountCode::~frmCountCode()
{
    delete ui;
}

void frmCountCode::initForm()
{
    QStringList headText;
    headText << "文件名" << "类型" << "大小" << "总行数" << "代码行数" << "注释行数" << "空白行数" << "路径";
    QList<int> columnWidth;
    columnWidth << 130 << 50 << 70 << 80 << 70 << 70 << 70 << 150;

    int columnCount=headText.count();
    ui->tableWidget->setColumnCount(columnCount);
    ui->tableWidget->setHorizontalHeaderLabels(headText);
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
    ui->tableWidget->horizontalHeader()->setHighlightSections(false);
    ui->tableWidget->verticalHeader()->setDefaultSectionSize(20);
    ui->tableWidget->verticalHeader()->setHighlightSections(false);

    for (int i=0; i < columnCount; i++) {
        ui->tableWidget->setColumnWidth(i, columnWidth.at(i));
    }

    //设置前景色
    ui->txtCount->setStyleSheet("color:#17A086;");
    ui->txtSize->setStyleSheet("color:#CA5AA6;");
    ui->txtRow->setStyleSheet("color:#CD1B19;");
    ui->txtCode->setStyleSheet("color:#22A3A9;");
    ui->txtNote->setStyleSheet("color:#D64D54;");
    ui->txtBlank->setStyleSheet("color:#A279C5;");

    //设置字体加粗
    QFont font;
    font.setBold(true);
    if (font.pointSize() > 0) {
        font.setPointSize(font.pointSize() + 1);
    } else {
        font.setPixelSize(font.pixelSize() + 2);
    }

    ui->txtCount->setFont(font);
    ui->txtSize->setFont(font);
    ui->txtRow->setFont(font);
    ui->txtCode->setFont(font);
    ui->txtNote->setFont(font);
    ui->txtBlank->setFont(font);

#if (QT_VERSION > QT_VERSION_CHECK(4,7,0))
    ui->txtFilter->setPlaceholderText("中间空格隔开,例如 *.h *.cpp *.c");
#endif
}

bool frmCountCode::checkFile(const QString &fileName)
{
    if (fileName.startsWith("moc_") || fileName.startsWith("ui_") || fileName.startsWith("qrc_")) {
        return false;
    }

    QFileInfo file(fileName);
    QString suffix="*." + file.suffix();
    QString filter=ui->txtFilter->text().trimmed();
    QStringList filters=filter.split(" ");
    return filters.contains(suffix);
}

void frmCountCode::countCode(const QString &filePath)
{
    QDir dir(filePath);
    foreach (QFileInfo fileInfo , dir.entryInfoList()) {
        if (fileInfo.isFile()) {
            QString strFileName=fileInfo.fileName();
            if (checkFile(strFileName)) {
                listFile << fileInfo.filePath();
            }
        } else {
            if(fileInfo.fileName()=="." || fileInfo.fileName()=="..") {
                continue;
            }

            //递归找出文件
            countCode(fileInfo.absoluteFilePath());
        }
    }
}

void frmCountCode::countCode(const QStringList &files)
{
    int lineCode;
    int lineBlank;
    int lineNotes;
    int count=files.count();
    on_btnClear_clicked();
    ui->tableWidget->setRowCount(count);

    quint32 totalLines=0;
    quint32 totalBytes=0;
    quint32 totalCodes=0;
    quint32 totalNotes=0;
    quint32 totalBlanks=0;

    for (int i=0; i < count; i++) {
        QFileInfo fileInfo(files.at(i));
        countCode(fileInfo.filePath(), lineCode, lineBlank, lineNotes);
        int lineAll=lineCode + lineBlank + lineNotes;

        QTableWidgetItem *itemName=new QTableWidgetItem;
        itemName->setText(fileInfo.fileName());

        QTableWidgetItem *itemSuffix=new QTableWidgetItem;
        itemSuffix->setText(fileInfo.suffix());

        QTableWidgetItem *itemSize=new QTableWidgetItem;
        itemSize->setText(QString::number(fileInfo.size()));

        QTableWidgetItem *itemLine=new QTableWidgetItem;
        itemLine->setText(QString::number(lineAll));

        QTableWidgetItem *itemCode=new QTableWidgetItem;
        itemCode->setText(QString::number(lineCode));

        QTableWidgetItem *itemNote=new QTableWidgetItem;
        itemNote->setText(QString::number(lineNotes));

        QTableWidgetItem *itemBlank=new QTableWidgetItem;
        itemBlank->setText(QString::number(lineBlank));

        QTableWidgetItem *itemPath=new QTableWidgetItem;
        itemPath->setText(fileInfo.filePath());

        itemSuffix->setTextAlignment(Qt::AlignCenter);
        itemSize->setTextAlignment(Qt::AlignCenter);
        itemLine->setTextAlignment(Qt::AlignCenter);
        itemCode->setTextAlignment(Qt::AlignCenter);
        itemNote->setTextAlignment(Qt::AlignCenter);
        itemBlank->setTextAlignment(Qt::AlignCenter);

        ui->tableWidget->setItem(i, 0, itemName);
        ui->tableWidget->setItem(i, 1, itemSuffix);
        ui->tableWidget->setItem(i, 2, itemSize);
        ui->tableWidget->setItem(i, 3, itemLine);
        ui->tableWidget->setItem(i, 4, itemCode);
        ui->tableWidget->setItem(i, 5, itemNote);
        ui->tableWidget->setItem(i, 6, itemBlank);
        ui->tableWidget->setItem(i, 7, itemPath);

        totalBytes  +=fileInfo.size();
        totalLines  +=lineAll;
        totalCodes  +=lineCode;
        totalNotes  +=lineNotes;
        totalBlanks +=lineBlank;

        if (i % 100==0) {
            qApp->processEvents();
        }
    }

    //显示统计结果
    listFile.clear();
    ui->txtCount->setText(QString::number(count));
    ui->txtSize->setText(QString::number(totalBytes));
    ui->txtRow->setText(QString::number(totalLines));
    ui->txtCode->setText(QString::number(totalCodes));
    ui->txtNote->setText(QString::number(totalNotes));
    ui->txtBlank->setText(QString::number(totalBlanks));

    //计算百分比
    double percent=0.0;
    //代码行所占百分比
    percent=((double)totalCodes / totalLines) * 100;
    ui->labPercentCode->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
    //注释行所占百分比
    percent=((double)totalNotes / totalLines) * 100;
    ui->labPercentNote->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
    //空行所占百分比
    percent=((double)totalBlanks / totalLines) * 100;
    ui->labPercentBlank->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
}

void frmCountCode::countCode(const QString &fileName, int &lineCode, int &lineBlank, int &lineNotes)
{
    lineCode=lineBlank=lineNotes=0;
    QFile file(fileName);
    if (file.open(QFile::ReadOnly)) {
        QTextStream out(&file);
        QString line;
        bool isNote=false;
        while (!out.atEnd()) {
            line=out.readLine();

            //移除前面的空行
            if (line.startsWith(" ")) {
                line.remove(" ");
            }

            //判断当前行是否是注释
            if (line.startsWith("/*")) {
                isNote=true;
            }

            //注释部分
            if (isNote) {
                lineNotes++;
            } else {
                if (line.startsWith("//")) {    //注释行
                    lineNotes++;
                } else if (line.isEmpty()) {    //空白行
                    lineBlank++;
                } else {                        //代码行
                    lineCode++;
                }
            }

            //注释结束
            if (line.endsWith("*/")) {
                isNote=false;
            }
        }
    }
}

void frmCountCode::on_btnOpenFile_clicked()
{
    QString filter=QString("代码文件(%1)").arg(ui->txtFilter->text().trimmed());
    QStringList files=QFileDialog::getOpenFileNames(this, "选择文件", "./", filter);
    if (files.size() > 0) {
        ui->txtFile->setText(files.join("|"));
        countCode(files);
    }
}

void frmCountCode::on_btnOpenPath_clicked()
{
    QString path=QFileDialog::getExistingDirectory(this, "选择目录", "./",  QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if (!path.isEmpty()) {
        ui->txtPath->setText(path);
        listFile.clear();
        countCode(path);
        countCode(listFile);
    }
}

void frmCountCode::on_btnClear_clicked()
{
    ui->txtCount->setText("0");
    ui->txtSize->setText("0");
    ui->txtRow->setText("0");

    ui->txtCode->setText("0");
    ui->txtNote->setText("0");
    ui->txtBlank->setText("0");

    ui->labPercentCode->setText("0%");
    ui->labPercentNote->setText("0%");
    ui->labPercentBlank->setText("0%");
    ui->tableWidget->setRowCount(0);
}


六、控件介绍

  1. 超过160个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
  2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
  3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.13的任何Qt版本,支持mingw、msvc、gcc等编译器,支持任意操作系统比如windows+linux+mac+嵌入式linux等,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
  4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
  5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
  6. 每个控件默认配色和demo对应的配色都非常精美。
  7. 超过130个可见控件,6个不可见控件。
  8. 部分控件提供多种样式风格选择,多种指示器样式选择。
  9. 所有控件自适应窗体拉伸变化。
  10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
  11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
  12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
  13. 所有控件最后生成一个动态库文件(dll或者so等),可以直接集成到qtcreator中拖曳设计使用。
  14. 目前已经有qml版本,后期会考虑出pyqt版本,如果用户需求量很大的话。
  15. 自定义控件插件开放动态库使用(永久免费),无任何后门和限制,请放心使用。
  16. 目前已提供32个版本的dll,其中qt_5_7_0_mingw530_32这个版本会一直保证最新的完整的。
  17. 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
  18. Qt入门书籍推荐霍亚飞的《Qt Creator快速入门》《Qt5编程入门》,Qt进阶书籍推荐官方的《C++ GUI Qt4编程》。
  19. 强烈推荐程序员自我修养和规划系列书《大话程序员》《程序员的成长课》《解忧程序员》,受益匪浅,受益终生!
  20. SDK地址:https://gitee.com/feiyangqingyun/QUCSDK https://github.com/feiyangqingyun/qucsdk

原文链接:https://www.cnblogs.com/feiyangqingyun/p/11669523.html

【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:「链接」