Qt 5.7 released



  • Qt 5.7 released

    Published Thursday June 16th, 2016
    6 Comments on Qt 5.7 released
    Posted in Biz Circuit & Dev Loop, News, Qt, Releases

    I’m very happy to announce that Qt 5.7 is now available. It’s been only 3 months since we released Qt 5.6, so one might expect a rather small release with Qt 5.7. But apart from the usual bug fixes and performance improvements, we have managed to add a whole bunch of new things to this release.

    Updated licensing

    Before going into the content and all the cool new features, I should mention the changes to our licensing that have been implemented with Qt 5.7.

    Qt has always been available as Free Software, and will continue to be so in the future. Qt is being developed as an open source project, The Qt Company is fully committed to this, and in addition, the agreement with the KDE Free Qt Foundation legally ensures this.

    With Qt 5.7, we are slightly adjusting our licensing of the Open Source version to bring it more in line with the philosophy of the Free Software movement. From this version onwards, Qt will not be available under LGPL version 2.1 anymore. Instead, Qt will be licensed under two main licenses: LGPL version 3 (and GPL version 2) for all almost all frameworks and libraries, and GPL version 3 for our tools like e.g. Qt Creator. In addition, we’re open sourcing some formerly closed Qt add-ons and tools under GPL version 3.

    Please check our our licensing pages or the licensing FAQ for all details around this. You can also have a look at my blog post from January where I announced this change.

    Unifying Qt for Application Development

    The license change gives us a unique opportunity to unify our Qt for Application Development offering between the Open Source and Commercial versions. Starting with Qt 5.7, both packages come with exactly the same content.

    This means that all the parts of Qt for Application Development that previously have been available only to commercial users are now available in the Open Source package as well.

    This includes the following modules:

    Qt Charts (GPLv3)
    Qt Data Visualization (GPLv3)
    Qt Virtual Keyboard (GPLv3)
    Qt Purchasing (LGPLv3)
    Qt Quick 2D renderer (GPLv3)
    The only exception is the Qt Quick Compiler where we need some more time to finish the required changes to be able to support this feature in the Open Source Edition.

    Qt Virtual Keyboard - Now available for GPL Qt users as well!
    Qt Virtual Keyboard – Now available under GPL!

    Qt Charts
    Qt Charts

    C++11

    It has been possible to use a C++11 compliant compiler together with Qt (and thus use C++11 in your application) for many releases. But Qt itself didn’t make use of it except for some integration points in our API.

    With Qt 5.6 being a long-term release that we will support for three years, we have taken the opportunity with Qt 5.7 to start modernizing our own code base. As one of the core strengths of Qt comes from it being a C++ framework, we want to follow the progress of modern C++ more closely.

    Starting with Qt 5.7, we will require a C++11 compliant compiler to build and use Qt. This allows us to use many of the new features in Qt itself, and renew our codebase using features such as constexpr, move semantics, range-for and auto. These efforts are well under way and will continue throughout the next versions.

    Apart from adding previously commercial-only modules to the Open Source version, we also have quite a bit of new content in Qt 5.7.

    Qt 3D

    We want to provide you the tools to create the required WOW-effect to amaze your end users. Modern UIs in many areas require the integration of 3D graphics, or even creating the whole user experience in three dimensions. In past years we’ve been improving our developer offering to make it easier for you to add this dimension into your UIs. With Qt 5.7, we are bringing in the Qt 3D module. This module has been available as a Technology Preview for two releases now, and I’m happy to announce that it has now reached the state where it is becoming a fully supported member of the Qt family!

    Qt 3D complements the 3D GUI offering of Qt consisting of integration to OpenGL, Qt Canvas 3D, and Qt Data Visualization modules. Qt 3D provides you with a 3D engine, that comes with both C++ and QML APIs. It makes it a lot easier to embed and handle 3D content within Qt Applications. In general, Qt 3D is much more than just a renderer, it serves as an extensible 3D framework for all kind of simulations. The architecture and most of the development on Qt 3D over the past years has been done by our partner KDAB, a huge thanks goes to them for their work. For a proper introduction, please see the guest blog post from Sean Harmer from KDAB.

    Qt Quick Controls 2

    Qt 5.7 also comes with a fully supported version of our new Qt Quick Controls, the library of QML-based UI controls. Qt Quick Controls 1 were targeted at the desktop, and came with all the bells and whistles required for desktop applications. This implied an overhead that often made them too slow for usage on embedded devices.

    Qt Quick Controls 2 solve these issues. They have been built from the ground up with performance and memory consumption in mind. So while they are fully usable on the desktop, they have slightly more limited functionality and e.g. don’t come with native styling integration. But they are vastly faster, and use a lot less memory than the old controls, making them ideal for many embedded and mobile solutions. Qt Quick Controls 1 are still part of the offering and a suitable API for desktop development. For instance, the Qt Quick Layouts work nicely with both of the control sets.

    Architecturally, Qt Quick Controls are based on templates that allow you to create your completely own set of controls ground-up. They also come with a flexible system that allows the rapid creation of custom styles and user experiences. In addition, the existing controls come with three predefined styles:

    Default style – a simple and minimal all-around style that offers the maximum performance
    Material style – a style based on the Google Material Design Guidelines
    Universal style – a style based on the Microsoft Universal Design Guidelines
    For a good overview, more details and a teaser video, please see the blog post from J-P Nurmi.

    New functionality in existing modules

    A lot of new functionality has been added to existing modules, and this blog can’t cover them all. Some of the highlights are:

    Qt Core

    Qt uses poll() instead of select() in it’s event loop allowing for more than 1024 file descriptors
    Qt now uses std::atomic for it’s atomic classes
    Qt Gui

    NEON optimizations for image scaling in Qt Gui
    Optimized the OpenGL function wrappers in Qt for size and speed
    Qt QML and Quick

    JIT support for WinRT, and 64bit ARM platforms in Qt QML, leading to much better QML performance on these platforms
    The debugger now supports debugging multiple QJSEngine instances at the same time
    Improved profiler and inspector integration
    Qt WebEngine

    Qt WebEngine is now based on Chromium 49 and can now print to PDF
    Support for DRM-protected HTML5 video in WebEngine
    Qt NFC

    Support for Android
    For all the details, please have a look at our New Features page and the Changes file for Qt 5.7.

    Qt for Device Creation

    Also Qt for Device creation has received an update and does now ship with Qt 5.7. In this release, we added out of the box support for a set of new hardware:

    The NVIDIA DRIVE CX boards (Tegra X1, 64 bit ARM)
    The Rasberry Pi 3 (32 bit mode)
    i.MX7 based devices (without GPU, uses the Linux framebuffer and the Qt Quick 2D renderer)
    Microsoft Windows is now a fully supported as a host platform for developing for embedded Linux. While Qt for Device Creation 5.7 does no longer support Windows Embedded, we now have full support for QNX, including pre-built binaries.

    To read more about changes in Qt for Device Creation, please see the separate blog post.

    Qt Creator 4.0

    Qt 5.7 ships with Qt Creator 4.0, more precisely with the new Qt Creator 4.0.2 version. Qt Creator 4.0 is a full development environment for all desktop, mobile and embedded development and now with version 4, we’ve especially emphasized the designer-developer workflow with the integration of Qt Quick Designer visual layout editor and the new Qt Quick Controls 2. Together, they provide a really nice way to rapidly create touch-based UIs for your embedded and mobile applications. Check out the separate video about the workflow from this blog post.

    Qt Creator 4.0 also comes with a set of nice new features, such as Clang integration and extended QML profiler, please find the details from the Qt Creator 4.0 blog post. For the updates regarding Qt 4.0.2, please see the change files.

    New Technology previews

    In addition, Qt 5.7 also adds a couple of new modules as Technology Previews.

    The first one is the Qt Wayland Compositor. The module makes it very easy to create your own Wayland Compositor. This is especially useful for embedded devices that require multi process support. The module has existed as unsupported technology for some time, but has had issues in both the API and implementation. With Qt 5.7, we’ve invested a lot of time and effort to clean up implementation and stabilize the API. It now comes with a full QML API and an improved C++ API with a lot of convenience. We also added a convenience API to create Wayland extensions and use them from both QML and C++. You can read more about it from the blog post from Paul.

    The next new module is Qt SCXML. It’s a completely new module that makes it very easy to integrate SCXML based state machines into Qt. It builds directly on top of the Qt Statemachine framework and extends it with with both a SCXML to C++ compiler and a runtime that allows loading SCXML based state machines.

    Qt Gamepad is another nice small addition. It makes it possible to ingrate gamepad support into both C++ and QML applications. It currently supports Windows, Linux, Android and iOS.

    With Qt for Device Creation, we’re also introducing the first preview of Qt-based Over-the-Air (OTA) updates mechanism. For an overview of this crucial IoT-technology, please see the blog post from Gatis.

    Finally, Qt 5.7 also includes a technology preview of the new Qt SerialBus module that allows you to use Qt APIs for device bus communications and protocols. It’s a generic API, but with this version it includes implementations for CAN and Modbus.

    Go and get it

    Finally, I’d like to give my thanks to everybody who has helped create this release. Again, a special thanks goes to KDAB for its tremendous work on Qt 3D.

    You can get Qt 5.7 from your Qt Account or the download page on qt.io.

    For an overview of the Qt 5.7, you can take a look at the release page, or for more details check the change files and known issues.

    Enjoy the release and have a great, Qt-filled summer!



  • 谢谢realfan大大的分享~~~



  • @realfan 有没有网盘分流?

    我要 window + android 的。


 

走马观花

最近的回复

  • F

    @QQ-690D15264BFFE58B6C76CFE35B63FCF1共享一下自己编译的Qt库 中说:

    SourceForge 上不去了。。。。。不知道大家能不能用我传上去的东西了。。。

    SF好了。。。。。。。。。
    不知道哪里来的强。。。。。。。。

    read more
  • 简介 自绘方案 QPainter QWidget+QPainter 示例 QQuickPaintedItem+QPainter 示例 关于QPainter Qml Canvas Qml Shapes QOpenGLWidget / QOpenGLWindow Qml SceneGraph Qml QQuickFrameBufferObject Qml ShaderEffect QVulkanWindow 简介

    本文是《Qml组件化编程》系列文章的第七篇,涛哥会罗列Qt中的所有自绘方案,并提供一些案例和说明。

    Qt自带的组件,外观都是固定的,一般可以通过qss/Qml style等方式进行定制。

    如果要实现外观特殊的组件,就需要自己绘制了。

    注:文章主要发布在涛哥的博客知乎专栏-涛哥的Qt进阶之路

    自绘方案

    Qt中的自绘方案有这么一些:

    QWidget+QPainter / QQuickPaintedItem+QPainter Qml Canvas Qml Shapes QOpenGLWidget / QOpenGLWindow Qml QQuickFrameBufferObject Qml SceneGraph Qml ShaderEffect QVulkanWindow

    (GraphicsView和QWidget的绘制类似,就不讨论了)

    QPainter

    QPainter是一个功能强大的画笔,QWidget中的各种控件如QPushButton、QLable等都是用QPainter画出来的。

    (QWidget的控件在绘制时,还增加了qss样式表,让UI定制变得更加方便。)

    QWidget+QPainter 示例

    QWidget中使用QPainter的方法,是重载paintEvent事件,这里示例绘制一个进度条:

    预览

    //MainWindow.h #pragma once #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); protected: void paintEvent(QPaintEvent *event) override; void timerEvent(QTimerEvent *event) override; private: QList<QColor> mColorList; int mCurrent = 0; }; //MainWindow.cpp #include "MainWindow.h" #include <QPainter> #include <QtMath> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { resize(400, 300); mColorList << QColor(51, 52, 54) << QColor(75, 85, 86) << QColor(87, 103, 103) << QColor(95, 119, 121) << QColor(101, 132, 134) << QColor(104, 146, 145) << QColor(104, 158, 158) << QColor(101, 169, 168) << QColor(92, 182, 180) << QColor(79, 194, 191); //每秒触发60次定时器,即刷新率60FPS startTimer(1000 / 60); } MainWindow::~MainWindow() { } void MainWindow::timerEvent(QTimerEvent *) { mCurrent =(mCurrent + 3) % 360; update(); } void MainWindow::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing); //原点x坐标 qreal a = 100; //原点y坐标 qreal b = 100; //半径 qreal r = 80; //每个小圆的半径递增值 qreal roffset = 2; //每个小圆的角度递增值 qreal angleOffset = 30; qreal currentangle = mCurrent ; for (int i = 0; i < mColorList.length(); i++) { qreal r0 = i * roffset; qreal angle = currentangle + i * angleOffset; qreal x0 = r * cos(qDegreesToRadians(angle)) + a; qreal y0 = r * sin(qDegreesToRadians(angle)) + b; painter.setPen(mColorList[i]); painter.setBrush(QBrush(mColorList[i])); painter.drawEllipse(x0 - r0, y0 - r0, 2 * r0, 2 * r0); } } QQuickPaintedItem+QPainter 示例

    QQuickPaintedItem继承自QQuickItem,而QQuickItem就是Qml中的Item。

    QQuickPaintedItem通过重载paint函数,就可以使用QPainter绘制。

    自定义的QQuickPaintedItem子类需要注册到Qml中才能使用,注册类型或者注册实例都可以,具体可以参考《 Qml组件化编程5-Qml与C++交互》

    这里示例QQuickPaintedItem 中使用 QPainter绘制一个阴阳八卦:

    预览

    //PBar.h #pragma once #include <QQuickPaintedItem> class PBar : public QQuickPaintedItem { Q_OBJECT public: PBar(QQuickItem *parent = nullptr); void paint(QPainter *painter) override; void timerEvent(QTimerEvent *event) override; private: QList<QColor> mColorList; int mCurrent = 0; }; //PBar.cpp #include "PBar.h" #include <QPainter> #include <QtMath> PBar::PBar(QQuickItem *parent) : QQuickPaintedItem (parent) { mColorList << QColor(51, 52, 54) << QColor(75, 85, 86) << QColor(87, 103, 103) << QColor(95, 119, 121) << QColor(101, 132, 134) << QColor(104, 146, 145) << QColor(104, 158, 158) << QColor(101, 169, 168) << QColor(92, 182, 180) << QColor(79, 194, 191); //每秒触发60次定时器,即刷新率60FPS startTimer(1000 / 60); } void PBar::paint(QPainter *painter) { //原点x坐标 qreal a = 100; //原点y坐标 qreal b = 100; //半径 qreal r = 80; qreal r1 = r / 2; qreal r2 = r / 6; qreal currentangle = mCurrent; painter->save(); painter->setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing); //red 部分 { painter->setBrush(QBrush(QColor(128, 1, 1))); QPainterPath path(QPointF(a + r * cos(qDegreesToRadians( currentangle )), b - r * sin(qDegreesToRadians(currentangle )))); path.arcTo(a - r, b - r, r * 2, r * 2, currentangle, 180); path.arcTo(a + r1 * cos(qDegreesToRadians(currentangle + 180)) - r1, b - r1 * sin(qDegreesToRadians(currentangle + 180)) - r1, r1 * 2, r1 * 2, currentangle + 180, 180); path.arcTo(a + r1*cos(qDegreesToRadians(currentangle)) - r1, b - r1 * sin(qDegreesToRadians(currentangle)) - r1, r1 * 2, r1 * 2, currentangle + 180, -180 ); painter->drawPath(path); } //blue 部分 { painter->setBrush(QBrush(QColor(1, 1, 128))); QPainterPath path(QPointF(a + r * cos(qDegreesToRadians( currentangle )), b - r * sin(qDegreesToRadians(currentangle )))); path.arcTo(a - r, b - r, r * 2, r * 2, currentangle, -180); path.arcTo(a + r1 * cos(qDegreesToRadians(currentangle + 180)) - r1, b - r1 * sin(qDegreesToRadians(currentangle + 180)) - r1, r1 * 2, r1 * 2, currentangle + 180, 180); path.arcTo(a + r1*cos(qDegreesToRadians(currentangle)) - r1, b - r1 * sin(qDegreesToRadians(currentangle)) - r1, r1 * 2, r1 * 2, currentangle + 180, -180 ); painter->drawPath(path); } { // red 小圆 painter->setBrush(QBrush(QColor(128, 1, 1))); QPainterPath path; path.addEllipse(a + r1 * cos(qDegreesToRadians(currentangle)) - r2, b - r1 * sin(qDegreesToRadians(currentangle )) - r2, r2 * 2, r2 * 2); painter->drawPath(path); } { //blue 小圆 painter->setBrush(QBrush(QColor(1, 1, 128))); QPainterPath path; path.addEllipse(a + r1 * cos(qDegreesToRadians(180 + currentangle)) - r2, b - r1 * sin(qDegreesToRadians(180 + currentangle)) - r2, r2 * 2, r2 * 2); painter->drawPath(path); } painter->restore(); } void PBar::timerEvent(QTimerEvent *event) { (void)event; mCurrent =(mCurrent + 3) % 360; update(); } //main.cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include "PBar.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<PBar>("PBar", 1, 0, "PBar"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); } //main.qml import QtQuick 2.0 import QtQuick.Window 2.0 import PBar 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello PBar") PBar { anchors.fill: parent } } 关于QPainter

    QPainter底层使用CPU做光栅化渲染,这种方式在没有GPU的设备中能够很好地工作。

    (我的好友"Qt侠-刘典武"就是这方面的实战专家,他手上有将近150个精美的自绘组件,比官方还要多,有需要的同学可以联系他 QQ517216493)

    然而时代在飞速发展,很多设备都带上了GPU,QPainter在GPU设备上,将不能发挥GPU的全部实力。

    (刘典武也在积极跟进GPU绘制)

    这里提一下,有个叫QUItCoding的组织,开发了一套QNanoPainter,接口和QPainter一致,

    在大部分场景下都拥有不错的性能。其底层是基于nanovg的GPU加速。

    不过QNanoPainter并没有合并进Qt官方,具体原因不清楚, 有可能是因为性能并不是100%达标的。

    Qml Canvas

    Qml中提供了Canvas组件,接口和html中的Canvas基本一致,可以直接copy html中的Canvas代码(极少部分不能用)。

    当然QPainter实现的功能,也都可以移植到Canvas中。

    Canvas渲染性能并不太好,如果有性能要求,还是不要用Canvas了。

    这里示例绘制一个笑脸

    预览

    //main.qml import QtQuick 2.0 import QtQuick.Window 2.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello Canvas") Canvas { id: canvas anchors.fill: parent onPaint: { var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(75,75,50,0,Math.PI*2,true); // 绘制 ctx.moveTo(110,75); ctx.arc(75,75,35,0,Math.PI,false); // 口(顺时针) ctx.moveTo(65,65); ctx.arc(60,65,5,0,Math.PI*2,true); // 左眼 ctx.moveTo(95,65); ctx.arc(90,65,5,0,Math.PI*2,true); // 右眼 ctx.stroke(); } } } Qml Shapes

    Qt5.10开始,Qml增加了Quick.Shapes功能。这是目前官方提供的自绘途径中,兼顾性能和易用性的最佳选择。

    Shapes底层为GPU渲染(基于SceneGraph),QPainter能绘制的基础图元,都可以用Shapes实现。Shapes再配合上Qml中的

    属性绑定和属性动画,可以轻易实现各式各样的动态、酷炫的UI。

    (后续的自定义组件,涛哥将会优先使用Shapes。)

    这里示例实现一个任意圆角的Rectangle组件:

    预览

    // TRoundRect.qml import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Shapes 1.12 Shape { id: root //左上角是否圆角 property bool leftTopRound: true //左下角是否圆角 property bool leftBottomRound: true //右上角是否圆角 property bool rightTopRound: true //右下角是否圆角 property bool rightBottomRound: true //圆角半径 property real radius //颜色 property color color: "red" //多重采样抗锯齿 layer.enabled: true layer.samples: 8 //平滑处理 smooth: true //反走样抗锯齿 antialiasing: true ShapePath { fillColor: color startX: leftTopRound ? radius : 0 startY: 0 fillRule: ShapePath.WindingFill PathLine { x: rightTopRound ? root.width - radius : root.width y: 0 } PathArc { x: root.width y: rightTopRound ? radius : 0 radiusX: rightTopRound ? radius : 0 radiusY: rightTopRound ? radius : 0 } PathLine { x: root.width y: rightBottomRound ? root.height - radius : root.height } PathArc { x: rightBottomRound ? root.width - radius : root.width y: root.height radiusX: rightBottomRound ? radius : 0 radiusY: rightBottomRound ? radius : 0 } PathLine { x: leftBottomRound ? radius : 0 y: root.height } PathArc { x: 0 y: leftBottomRound ? root.height - radius : root.height radiusX: leftBottomRound ? radius : 0 radiusY: leftBottomRound ? radius : 0 } PathLine { x: 0 y: leftTopRound ? radius : 0 } PathArc { x: leftTopRound ? radius : 0 y: 0 radiusX: leftTopRound ? radius : 0 radiusY: leftTopRound ? radius : 0 } } }

    看一下TRoundRect的用法

    import QtQuick 2.0 import QtQuick.Controls 2.5 Rectangle { width: 800 height: 600 Rectangle { //背景红色,衬托一下 x: 10 width: 100 height: 160 color: "red" } TRoundRect { id: roundRect x: 40 y: 10 width: 200 height: 160 radius: 40 leftTopRound: lt.checked rightTopRound: rt.checked leftBottomRound: lb.checked rightBottomRound: rb.checked color: "#A0333666" //半透明色 } Grid { x: 300 y: 10 columns: 2 spacing: 10 CheckBox { id: lt text: "LeftTop" checked: true } CheckBox { id: rt text: "RightTop" checked: true } CheckBox { id: lb text: "LeftBottom" checked: true } CheckBox { id: rb text: "rightBottom" checked: true } } } QOpenGLWidget / QOpenGLWindow

    有的同学学习过OpenGL这类图形渲染API,Qt为OpenGL提供了便利的窗口和上下文环境。

    QOpenGLWidget用来在QWidget框架中集成OpenGL渲染,QOpenGLWindow用在Qml框架。

    使用方法都是子类重载下面三个函数:

    void initializeGL(); void paintGL(); void resizeGL(int w, int h);

    这里可以参考官方的示例:

    QOpenGLWidget示例

    QOpenGLWindow示例

    Qt对OpenGL系列的函数都做了封装,一般使用QOpenGLFunctions就够了,QOpenGLFunctions是基于OpenGL ES 2.0 API的跨平台实现,删减了个别API。

    相应的有一个未删减的OpenGLES2 的封装:QOpenGLFunctions_ES2。

    当然为了兼容所有OpenGL版本,Qt分别封装了相应的类

    预览

    有特殊版本需要的时候,可以把QOpenGLFunctions换成相应的类。

    还有一个OpenGL ES3.0的封装, QOpenGLExtraFunctions,可以在支持OpenGL ES 3.0的设备上使用。

    使用这些functions,一定要在有OpenGL上下文环境的地方,先调用一下initializeOpenGLFunctions。有些版本的init有返回值的,要注意判断并处理。

    Qml SceneGraph

    Qml基于GPU实现了一套渲染框架,这个框架就是SceneGraph。

    SceneGraph提供了很多GPU渲染相关的功能,以方便进行自绘制,都是以QSG开头的类,如下图所示:

    预览

    使用方式是在QQuickItem的子类中,重载updatePaintNode函数:

    QSGNode *TaoItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) { QSGSimpleRectNode *n = static_cast<QSGSimpleRectNode *>(node); if (!n) { n = new QSGSimpleRectNode(); n->setColor(Qt::red); } n->setRect(boundingRect()); return n; }

    在使用Qml框架的程序中,使用这些QSG功能,将自定义渲染直接加入SceneGraph框架的渲染流程,无疑是性能最优的。

    不过问题在于,这些QSG有点难以使用。需要有一定的OpenGL或DirectX相关图形学知识,并理解SceneGraph的节点交换机制,才能用好。

    而懂OpenGL的人,有更好的选择,就是直接使用OpenGL的API。下面的QQuickFrameBufferObject就是一种途径。

    Qml QQuickFrameBufferObject

    QQuickFramebufferObject继承于QQuickItem(Qml中将它当作一个Item就可以了),用来在一个framebuffer object(FBO)上做渲染,

    SceneGraph框架会将这个FBO渲染到屏幕上。

    使用的方式是,实现一个QQuickFramebufferObject::Renderer类。

    这个类里面始终是拥有OpenGL上下文环境的,内存也是被SceneGraph框架管理的,只要理解了渲染流程,用起来还是很方便的。

    涛哥在Qml中集成 视频播放器 和 3D模型渲染的时候,就使用了这个FBO。

    可以参考这两个例子:

    Qml渲染3D模型

    FFmpeg解码,Qml/OpenGL转码渲染

    Qml ShaderEffect

    学习过图形学的人,都应该听说过大名鼎鼎的Shadertoy

    只要一点奇妙的Shader代码,就能渲染出各种酷炫的效果。

    Qml中提供了ShaderEffect组件,就可以用来做ShaderToy那样的特效。

    可以参考qyvlik的代码仓库:

    qyvlik-ShaderToy.qml

    以及我很久以前写的例子:

    Tao-ShaderToy

    360能量球

    Qml中还有个神奇的ShaderEffectSource,可以用在普通Item的layer.effect中,

    比如这个例子,就用ShaderEffectSource做了倒影特效:

    倒影特效

    QVulkanWindow

    OpenGL的下一代,已经进化为vulkan了。

    Qt 5.10开始,也提供了vulkan的支持。

    涛哥水平有限,这次只提一下,就先不展开说了。

    转载声明

    文章出自涛哥的博客
    文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 © 涛哥

    联系方式 作者 武威的涛哥 开发理念 弘扬鲁班文化,传承工匠精神 博客 https://jaredtao.github.io github https://github.com/jaredtao 知乎 https://www.zhihu.com/people/wentao-jia 邮箱 jared2020@163.com 微信 xsd2410421 QQ 759378563

    请放心联系我,乐于提供咨询服务,也可洽谈商务合作相关事宜。

    打赏

    weixin
    zhifubao

    如果觉得涛哥写的还不错,还请为涛哥打个赏,您的赞赏是涛哥持续创作的源泉。

    read more
  • 简介 环境说明 QtCreator折叠全部代码 QtCreator属性生成 QtCreator注释代码 QtCreator代码片段 QtCreator代码格式化 QtCreator会话管理 结尾 简介

    本文是《Qt实用技能汇总》系列文章的第一篇,涛哥将教大家,一些QtCreator的实用技巧。

    工欲善其事,必先利其器。

    这个系列,全是干货!

    环境说明

    下文以Windows平台的QtCreator为参考,其它平台的菜单栏入口和快捷键 请以实际为准。

    QtCreator版本以Qt5.6.x及以上安装包所带的都行,再旧的版本不讨论。

    QtCreator折叠全部代码

    折叠全部代码,支持C++和Qml。操作方式为:

    光标焦点放在代码文本中,之后 菜单栏: 编辑->Advanced->Toggle Fold All

    预览

    这个功能没有快捷键

    QtCreator属性生成

    经常需要给自定义的QObject类写一些属性,QtCreator是可以自动生成get、set函数以及change信号的。

    只要写上Q_PROPERTY那一行,光标放在Q_PROPERTY上, 用右键菜单 -> Refactor -> Generate Missing Q_PROPERTY Memory 即可生成。

    也可以使用快捷键,光标放在Q_PROPERTY上,按Alt + Enter。

    预览

    QtCreator注释代码

    快捷键,注释当前行代码或者当前选中的多行代码

    Ctrl + /

    已经注释掉的,再按一次取消注释。

    QtCreator代码片段

    前面的Q_PROPERTY自动生成,其实就是一种代码片段。

    比如经常要写这样一段代码

    if (pObj) { delete pObj; pObj = nullptr; }

    其中的pObj出现了多次,在不同的地方只是pObj这个名字不同,其它if 和 delete操作一模一样。

    可以把这段代码封装成模板函数,也可以做成QtCreator的代码片段。(不建议定义宏, 不类型安全和不方便调试)

    模板是这样的:

    template<class T> safeDelete (T *pObj) { if (pObj) { delete pObj; pObj = nullptr; } }

    代码片段是在写代码时就把实际的代码生成出来了,模板是编译的时候才去生成。所以代码片段可以加快编译速度。

    代码片段是这么做的,在菜单的 工具->选项 弹出选项窗口,然后到文本编辑器->片段->下拉选C++

    预览

    添加一个片段,起名字叫safeD,并填上内容

    if ($$) { delete $$; $$ = nullptr; }

    预览

    写好后点击确定。再回到代码中,输入safeD,按回车就会自动补全前面的片段。

    光标出现在$$的地方,有一个高亮颜色,此时只要输入一个名字,按下回车键,后续的地方自动替换成输入的名字了。

    预览

    QtCreator代码格式化

    都9102年了,如果还有人跟你计较大括号要不要换行、指针符号靠左还是靠右这种问题,请用自动格式化工具怼他/她。

    QtCreator支持很多种格式化工具,涛哥用的是clang-format。VisualStudio 2017、2019、以及VSCode也支持clang-format

    的,都不需要额外安装任何插件。配置起来很简单,只要在项目pro文件同级目录下,放一个配置好的.clang-format的文件就行了。

    团队合作的时候,使用同一个.clang-format配置文件,大家的代码格式就都一致了。

    clang-format有默认的google、llvm等格式可选,也可以自定义。下面是一个涛哥使用的自定义配置文件,并做了详细的注释

    --- # 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto Language: Cpp # BasedOnStyle: WebKit # 访问说明符(public、private等)的偏移 AccessModifierOffset: -4 # 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行) AlignAfterOpenBracket: AlwaysBreak # 连续赋值时,对齐所有等号 AlignConsecutiveAssignments: false # 连续声明时,对齐所有声明的变量名 AlignConsecutiveDeclarations: false # 左对齐逃脱换行(使用反斜杠换行)的反斜杠 AlignEscapedNewlines: Right # 水平对齐二元和三元表达式的操作数 AlignOperands: true # 对齐连续的尾随的注释 AlignTrailingComments: true # 允许函数声明的所有参数在放在下一行 AllowAllParametersOfDeclarationOnNextLine: true # 允许短的块放在同一行 AllowShortBlocksOnASingleLine: false # 允许短的case标签放在同一行 AllowShortCaseLabelsOnASingleLine: false # 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All AllowShortFunctionsOnASingleLine: Empty # 允许短的if语句保持在同一行 AllowShortIfStatementsOnASingleLine: false # 允许短的循环保持在同一行 AllowShortLoopsOnASingleLine: false # 总是在定义返回类型后换行(deprecated) AlwaysBreakAfterDefinitionReturnType: None # 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数), # AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义) AlwaysBreakAfterReturnType: None # 总是在多行string字面量前换行 AlwaysBreakBeforeMultilineStrings: false # 总是在template声明后换行 AlwaysBreakTemplateDeclarations: true # false表示函数实参要么都在同一行,要么都各自一行 BinPackArguments: false # false表示所有形参要么都在同一行,要么都各自一行 BinPackParameters: false # 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效 BraceWrapping: # class定义后面 AfterClass: true # 控制语句后面 AfterControlStatement: true # enum定义后面 AfterEnum: true # 函数定义后面 AfterFunction: true # 命名空间定义后面 AfterNamespace: true # ObjC定义后面 AfterObjCDeclaration: false # struct定义后面 AfterStruct: true # union定义后面 AfterUnion: true # extern 定义后面 AfterExternBlock: true # catch之前 BeforeCatch: true # else 之前 BeforeElse: true # 缩进大括号 IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true # 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行) BreakBeforeBinaryOperators: All # 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似), # Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似), # Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom # 注:这里认为语句块也属于函数 BreakBeforeBraces: Allman # 继承列表的逗号前换行 BreakBeforeInheritanceComma: false # 在三元运算符前换行 BreakBeforeTernaryOperators: true # 在构造函数的初始化列表的逗号前换行 BreakConstructorInitializersBeforeComma: false # 初始化列表前换行 BreakConstructorInitializers: BeforeComma # Java注解后换行 BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true # 每行字符的限制,0表示没有限制 ColumnLimit: 160 # 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变 CommentPragmas: '^ IWYU pragma:' # 紧凑 命名空间 CompactNamespaces: false # 构造函数的初始化列表要么都在同一行,要么都各自一行 ConstructorInitializerAllOnOneLineOrOnePerLine: true # 构造函数的初始化列表的缩进宽度 ConstructorInitializerIndentWidth: 4 # 延续的行的缩进宽度 ContinuationIndentWidth: 4 # 去除C++11的列表初始化的大括号{后和}前的空格 Cpp11BracedListStyle: false # 继承最常用的指针和引用的对齐方式 DerivePointerAlignment: false # 关闭格式化 DisableFormat: false # 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental) ExperimentalAutoDetectBinPacking: false # 固定命名空间注释 FixNamespaceComments: true # 需要被解读为foreach循环而不是函数调用的宏 ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeBlocks: Preserve # 对#include进行排序,匹配了某正则表达式的#include拥有对应的优先级,匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前), # 可以定义负数优先级从而保证某些#include永远在最前面 IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' # 缩进case标签 IndentCaseLabels: true IndentPPDirectives: None # 缩进宽度 IndentWidth: 4 # 函数返回类型换行时,缩进函数声明或函数定义的函数名 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true # 保留在块开始处的空行 KeepEmptyLinesAtTheStartOfBlocks: true # 开始一个块的宏的正则表达式 MacroBlockBegin: '' # 结束一个块的宏的正则表达式 MacroBlockEnd: '' # 连续空行的最大数量 MaxEmptyLinesToKeep: 1 # 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All NamespaceIndentation: All # 使用ObjC块时缩进宽度 ObjCBlockIndentWidth: 4 # 在ObjC的@property后添加一个空格 ObjCSpaceAfterProperty: true # 在ObjC的protocol列表前添加一个空格 ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 19 # 在一个注释中引入换行的penalty PenaltyBreakComment: 300 # 第一次在<<前换行的penalty PenaltyBreakFirstLessLess: 120 # 在一个字符串字面量中引入换行的penalty PenaltyBreakString: 1000 # 对于每个在行字符数限制之外的字符的penalty PenaltyExcessCharacter: 1000000 # 将函数的返回类型放到它自己的行的penalty PenaltyReturnTypeOnItsOwnLine: 60 # 指针和引用的对齐: Left, Right, Middle PointerAlignment: Right #RawStringFormats: # - Delimiter: pb # Language: TextProto # BasedOnStyle: google # 允许重新排版注释 ReflowComments: false # 允许排序#include SortIncludes: true SortUsingDeclarations: true # 在C风格类型转换后添加空格 SpaceAfterCStyleCast: false # 模板关键字后面添加空格 SpaceAfterTemplateKeyword: true # 在赋值运算符之前添加空格 SpaceBeforeAssignmentOperators: true # 开圆括号之前添加一个空格: Never, ControlStatements, Always SpaceBeforeParens: ControlStatements # 在空的圆括号中添加空格 SpaceInEmptyParentheses: false # 在尾随的评论前添加的空格数(只适用于//) SpacesBeforeTrailingComments: 1 # 在尖括号的<后和>前添加空格 SpacesInAngles: false # 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格 SpacesInContainerLiterals: true # 在C风格类型转换的括号中添加空格 SpacesInCStyleCastParentheses: false # 在圆括号的(后和)前添加空格 SpacesInParentheses: false # 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响 SpacesInSquareBrackets: false # 标准: Cpp03, Cpp11, Auto Standard: Cpp11 # tab宽度 TabWidth: 4 # 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always UseTab: Never ...

    怎么使用呢?QtCreator中打开要格式化的代码文件,按快捷键 Ctrl + I 就是格式化当前行。

    Ctrl + A选中全部内容,再按Ctrl + I就是格式化全部。

    VS是把.clang-format文件放在和sln文件同级目录即可,快捷键一般是 先按Ctrl + K 再按Ctrl + D

    VSCode是打开的文件夹根目录有.clang-format即可,格式化一般在右键菜单。

    QtCreator会话管理

    QtCreator的"会话管理"和"最近使用"功能配合,是涛哥接触过的所有IDE/Editor中,管理项目最好用的,没有之一。

    包括VisualStudio、VSCode、AndroidStudio、XCode、Unity3D Editor等等,都只有"最近使用",没有"会话管理"。

    预览

    如上图,左边是会话列表,右边是最近使用列表。

    会话管理的最大用处是,同时打开多个Qt项目,以及快速切换并还原状态。

    涛哥用示例来说明:

    涛哥正在开发TaoQuick项目,这个项目包含两个不同路径下的pro项目, 每个项目分别有自己的子项目。

    预览

    当我正在调试TaoView.cpp文件,并且打了断点的时候,有小伙伴来问我关于另一个项目HelloCI的一些问题。

    这时候我需要把代码切换到HelloCI项目,有些人可能会想着再打开一个QtCreator,当然这样也行,就是

    窗口太多了容易搞混了。涛哥更信赖“会话管理”功能,切换到HelloCI这个会话,做了一些处理。

    完了之后,涛哥又切换回了TaoQuick这个会话,QtCreator就自动恢复到了刚才看的代码TaoView.cpp,而且断点也还在。

    又过了一段时间,涛哥需要重启一下电脑,重启后打开QtCreator,直接点开TaoQuick这个会话,又给我切换回

    刚才调试的TaoQuick.cpp文件了,项目结构展开和重启之前是一样的,只有断点没有了。

    简而言之,大家把平常用的多个相关的项目,放进一个会话里面,就可以放心地关掉QtCreator。下一次想打开的时候,只要点一下会话就可以了。

    预览

    结尾

    这次就分享这么多了,以上内容,大部分都可以在TaoQuick的代码仓库中看到

    https://github.com/jaredtao/taoquick

    转载声明

    文章出自涛哥的博客
    文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 © 涛哥

    联系方式 作者 涛哥 开发理念 弘扬鲁班文化,传承工匠精神 博客 https://jaredtao.github.io github https://github.com/jaredtao 知乎 https://www.zhihu.com/people/wentao-jia 邮箱 jared2020@163.com 微信 xsd2410421 QQ 759378563

    请放心联系我,乐于提供咨询服务,也可洽谈商务合作相关事宜。

    打赏

    weixin
    zhifubao

    如果觉得涛哥写的还不错,还请为涛哥打个赏,您的赞赏是涛哥持续创作的源泉。

    read more
  • 简介 先看预览图 新的渐变效果 条形进度条 圆形进度条 简介

    本文是《Qml组件化编程》系列文章的第六篇,涛哥将教大家,进度条组件的定制。

    顺便说一下,涛哥的TaoQuick项目正式开源了, 系列文章中的所有功能,包括动态换皮肤、切换多语言等等,都集成在了TaoQuick中,

    同时涛哥也在TaoQuick中使用了持续集成(CI)技术,目前已经能够自动编译、发布Windows和 Macos平台的软件包,可以在github的Release界面下载体验。

    互联网行业很流行的DevOps理念,在TaoQuick项目中得到了最佳的实践。

    (linux平台的发布工具linuxdeployqt暂时还有点问题,涛哥后续会搞定的)

    地址在这https://github.com/jaredtao/TaoQuick, 赶快去star吧。

    注:文章主要发布在涛哥的博客知乎专栏-涛哥的Qt进阶之路

    先看预览图

    预览

    新的渐变效果

    Qt 5.12 加入了新的渐变效果,一共180种,效果来自这个网站https://webgradients.com

    按照帮助文档的介绍,可以通过下面这两种方式使用

    Rectangle { y: 0; width: 80; height: 80 gradient: Gradient.NightFade } Rectangle { y: 0; width: 80; height: 80 gradient: "NightFade" }

    涛哥立即想到了,枚举不就是数字嘛

    Rectangle { y: 0; width: 80; height: 80 gradient: 1 } Rectangle { y: 0; width: 80; height: 80 gradient: 2 } Rectangle { y: 0; width: 80; height: 80 gradient: 3 }

    试了一下,这样也是可以啊,哈哈。

    于是涛哥就把180种渐变效果都拉出来看看。

    预览

    Qt只支持水平和垂直的渐变,其中有小部分是不能用的,所以只有165个能用。

    看一下展示全部渐变的Qml代码:

    import QtQuick 2.9 import QtQuick.Controls 2.5 Item { anchors.fill: parent GridView { id: g anchors.fill: parent anchors.margins: 20 cellWidth: 160 cellHeight: 160 model: 180 //这里的数据Model直接给个数字180 clip: true property var invalidList: [27, 39, 40, 45, 71, 74, 105, 111, 119, 130, 135, 141] //这几个是不能用的,看过运行报错后手动列出来的。 delegate: Item{ width: 160 height: 160 Rectangle{ width: 150 height: 150 anchors.centerIn: parent color: "white" radius: 10 Text { anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top anchors.topMargin: 2 text: index + 1 } Rectangle { width: 100 height: width radius: width / 2 //编号在列表里的,直接渐变赋值为null,就不会在Qml运行时报警告了 gradient: g.invalidList.indexOf(modelData + 1) < 0 ? modelData + 1 : null anchors.centerIn: parent anchors.verticalCenterOffset: 10 } } } } } 条形进度条

    普通进度条的原理,就是有一个比较长的矩形做背景,在上面放一个颜色不同的矩形,其宽度跟着百分比变化,

    100%时宽度与背景一致。

    可以写一个很简要的进度条。

    Rectangle { id: back width: 300 height: 50 radius: height / 2 color: "white" Rectangle { id: front //宽度是 背景宽度 * 百分比 width: percent / 100 * parent.width height: parent.height radius: parent.radius color: "red" } }

    再添加一点元素,在右侧放一个文本,表示百分比,或者放图片。甚至给进度条加个闪光特效。

    经过一系列的加工,封装成一个综合的组件,最终结果如下:

    //NormalProgressBar.qml import QtQuick 2.12 import QtQuick.Controls 2.12 Item { id: r property int percent: 0 implicitWidth: 200 implicitHeight: 16 //枚举, 表示右侧Bar的类型 enum BarType { Text, //右侧放文本 SucceedOrFailed, //右侧放图片表示成功和失败,没有100%就是失败 NoBar //右侧不放东西 } //只读属性,内置一些颜色 readonly property color __backColor: "#f5f5f5" readonly property color __blueColor: "#1890ff" readonly property color __succeedColor: "#52c41a" readonly property color __failedColor: "#f5222d" //背景色,默认值 property color backgroundColor: __backColor //前景色 property color frontColor: { switch (barType) { case TNormalProgress.BarType.SucceedOrFailed: return percent === 100 ? __succeedColor : __failedColor default: return __blueColor } } //文字 property string text: String("%1%").arg(percent) //渐变 0-180 除掉不能用的,165种渐变任你选 property int gradientIndex: -1 //闪烁特效 property bool flicker: false //右侧Bar类型 property var barType: TNormalProgress.BarType.Text Text { id: t enabled: barType === TNormalProgress.BarType.Text visible: enabled text: r.text anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right } Image { id: image source: percent === 100 ? "qrc:/Core/Image/ProgressBar/ok_circle.png" : "qrc:/Core/Image/ProgressBar/fail_circle.png" height: parent.height width: height enabled: barType === TNormalProgress.BarType.SucceedOrFailed visible: enabled anchors.right: parent.right } property var __right: { switch (barType) { case TNormalProgress.BarType.Text: return t.left case TNormalProgress.BarType.SucceedOrFailed: return image.left default: return r.right } } Rectangle { //背景 id: back anchors.left: parent.left anchors.right: __right anchors.rightMargin: 4 height: parent.height radius: height / 2 color: backgroundColor Rectangle { //前景 id: front width: percent / 100 * parent.width height: parent.height radius: parent.radius color: frontColor gradient: gradientIndex === -1 ? null : gradientIndex Rectangle { //前景上的闪光特效 id: flick height: parent.height width: 0 radius: parent.radius color: Qt.lighter(parent.color, 1.2) enabled: flicker visible: enabled NumberAnimation on width { running: visible from: 0 to: front.width duration: 1000 loops: Animation.Infinite; } } } } } 圆形进度条

    将一个Rectangle做成圆形: 宽高相等,半径为宽度一半。

    再把 颜色设置为透明,边框不透明,边框加粗一点,就是一个圆环了。

    Rectangle { id: back width: 120 height: width radius: width / 2 color: "transparent" border.width: 10 border.color: "white" }

    接下来给圆环贴上一个圆形渐变色,渐变按照百分比来做。

    import QtGraphicalEffects 1.12 Rectangle { id: back width: 120 height: width radius: width / 2 color: "transparent" border.width: 10 border.color: "white" ConicalGradient { anchors.fill: back source: back gradient: Gradient { GradientStop { position: 0.0; color: "white" } GradientStop { position: percent / 100 ; color: "red" } GradientStop { position: percent / 100 + 0.001; color: "white" } GradientStop { position: 1.0; color: "white" } } } }

    渐变从0 到 percent处都是有渐变颜色的, 再从percent + 0.001 到1.0处,都是背景色,这样就是一个简易的圆形进度条了。

    不过这里percent为100的情况,圆形渐变处理不了,我们可以特殊处理,直接让背景圆环变成前景色就行了。(既然都100%了,背景肯定是全部被遮住了,那就让背景做前景,藏掉真正的前景)

    ```qml import QtGraphicalEffects 1.12 Rectangle { id: back width: 120 height: width radius: width / 2 color: "transparent" border.width: 10 border.color: percent === 100 ? "red" : "white" //百分比为100时显示为前景,否则显示为背景 ConicalGradient { anchors.fill: back source: back enabled: percent != 100 //百分比不为100时有效 visible: enabled //百分比不为100时有效 gradient: Gradient { GradientStop { position: 0.0; color: "white" } GradientStop { position: percent / 100 ; color: "red" } GradientStop { position: percent / 100 + 0.001; color: "white" } GradientStop { position: 1.0; color: "white" } } } }

    再加点料,封装成组件

    //CircleProgressBar.qml import QtQuick 2.12 import QtQuick.Controls 2.12 import QtGraphicalEffects 1.12 Item { id: r property int percent: 0 enum BarType { Text, SucceedOrFailed, NoBar } readonly property color __backColor: "#f5f5f5" readonly property color __blueColor: "#1890ff" readonly property color __succeedColor: "#52c41a" readonly property color __failedColor: "#f5222d" property color backgroundColor: __backColor property color frontColor: { switch (barType) { case TNormalProgress.BarType.SucceedOrFailed: return percent === 100 ? __succeedColor : __failedColor default: return __blueColor } } property string text: String("%1%").arg(percent) property var barType: TNormalProgress.BarType.Text Rectangle { id: back color: "transparent" anchors.fill: parent border.color: percent === 100 ? frontColor : backgroundColor border.width: 10 radius: width / 2 } Text { id: t enabled: barType === TNormalProgress.BarType.Text visible: enabled text: r.text anchors.centerIn: parent verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } Image { id: image source: percent === 100 ? "qrc:/Core/Image/ProgressBar/ok.png" : "qrc:/Core/Image/ProgressBar/fail.png" enabled: barType === TNormalProgress.BarType.SucceedOrFailed visible: enabled scale: 2 anchors.centerIn: parent } ConicalGradient { anchors.fill: back source: back enabled: percent != 100 visible: enabled smooth: true antialiasing: true gradient: Gradient { GradientStop { position: 0.0; color: frontColor } GradientStop { position: percent / 100 ; color: frontColor } GradientStop { position: percent / 100 + 0.001; color: backgroundColor } GradientStop { position: 1.0; color: backgroundColor } } } }

    最后,来个合影

    Item { id: r anchors.fill: parent Grid { id: g anchors.fill: parent anchors.margins: 10 columns: 2 spacing: 10 Column { width: g.width / 2 - 10 height: g.height /2 - 10 spacing: 10 TNormalProgress { width: parent.width backgroundColor: gConfig.reserverColor NumberAnimation on percent { from: 0; to: 100; duration: 5000; running: true; loops: Animation.Infinite} } TNormalProgress { width: parent.width backgroundColor: gConfig.reserverColor flicker: true percent: 50 } TNormalProgress { width: parent.width backgroundColor: gConfig.reserverColor barType: TNormalProgress.BarType.SucceedOrFailed percent: 70 } TNormalProgress { width: parent.width backgroundColor: gConfig.reserverColor barType: TNormalProgress.BarType.SucceedOrFailed percent: 100 } TNormalProgress { width: parent.width backgroundColor: gConfig.reserverColor barType: TNormalProgress.BarType.NoBar percent: 50 gradientIndex: 12 } } Row { width: g.width / 2 - 10 height: g.height /2 - 10 spacing: 10 TCircleProgress { width: 120 height: 120 backgroundColor: gConfig.reserverColor NumberAnimation on percent { from: 0; to: 100; duration: 5000; running: true; loops: Animation.Infinite} } TCircleProgress { width: 120 height: 120 backgroundColor: gConfig.reserverColor barType: TNormalProgress.BarType.SucceedOrFailed percent: 75 } TCircleProgress { width: 120 height: 120 backgroundColor: gConfig.reserverColor barType: TNormalProgress.BarType.SucceedOrFailed percent: 100 } } Row { width: g.width / 2 - 10 height: g.height /2 - 10 spacing: 10 TCircleProgress { width: 120 height: 120 backgroundColor: gConfig.reserverColor text: String("%1天").arg(percent) NumberAnimation on percent { from: 0; to: 100; duration: 5000; running: true; loops: Animation.Infinite} } TCircleProgress { id: ppppp width: 120 height: 120 backgroundColor: gConfig.reserverColor barType: TNormalProgress.BarType.SucceedOrFailed SequentialAnimation { running: true loops: Animation.Infinite NumberAnimation { target: ppppp property: "percent" from: 0 to: 100 duration: 3000 } PauseAnimation { duration: 500 } } } TCircleProgress { width: 120 height: 120 backgroundColor: gConfig.reserverColor percent: 100 } } Column { width: g.width / 2 - 10 height: g.height /2 - 10 spacing: 10 } Column { width: g.width / 2 - 10 height: g.height /2 - 10 spacing: 10 } } }

    效果如下:

    预览

    read more

关注我们

微博
QQ群











召唤伊斯特瓦尔