• Qt的一些开发技巧


    Lambda匿名函数

    • 有时候槽函数代码辑逻辑非常简单,可以直接用下面的Lambda匿名函数处理信号,简捷明了.需c++11支持,不支持自身递归调用.

      1
      2
      3
      4
      5
      6
      7
      QComboBox *cb = new QComboBox(this);
      QObject::connect(cb,&QComboBox::currentTextChanged,[=](QString txt){
      [...]
      baseform->changeJsonValue(btn,uname,
      baseform->mWindow->mItemMap.key(txt));
      [...]
      });
    • 函数内部的匿名函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    void ActionList::onCustomContextMenu(const QPoint &pos)
    {
     
    [...]
    auto sawp_lambda_func = [this](int src,int dst) {
     
    QVariantList oldvals;
    for(int i = 0 ; i < mTable->columnCount();i++)
    {
    QWidget *w = mTable->cellWidget(src,i);
     
     
    if(!QString::compare(w->metaObject()->className(),"QComboBox"))
    {
    oldvals.append(((QComboBox*)w)->currentText());
    }else{
    oldvals.append(((QLineEdit*)w)->text());
    }
    QObject::disconnect(w);
    mTable->removeCellWidget(src,i);
    w->deleteLater();
     
    }
    mTable->removeRow(src);
    [...]
    };
     
     
    QAction up(QIcon(":/icon/icons/act_up.png") ,
    QString("上移一行"),this);
    QObject::connect(&up,
    &QAction::triggered,[=](){
    sawp_lambda_func(line,line-1);
    });
    [...]
    }

    模拟事件

    • 一些GUI的操作,需要一些事件来完成,下面模拟一个鼠标Release的事件
    1
    2
    3
    4
    5
    [...]
    QMouseEvent *event = new QMouseEvent(QMouseEvent::MouseButtonRelease,QCursor::pos(),
    Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);
    QApplication::postEvent(this,event);
    [...]
    • 把事件转换成对其它控件的事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void NewGrid::wheelEvent(QWheelEvent *event)
    {
     
    if(sliderOrientation == Qt::Horizontal)
    {
    if(event->orientation() != Qt::Horizontal)
    {
    QWheelEvent *evt = new QWheelEvent(event->pos(),event->globalPos(),
    event->delta(),
    event->buttons(),
    event->modifiers(),Qt::Horizontal);
    QApplication::postEvent(mainScroll->horizontalScrollBar(),evt);
    }
    }
     
    }

    元对像,动态属性

    Meta-Object System 的基本功能
    Meta Object System 的设计基于以下几个基础设施:

    • QObject 类
      作为每一个需要利用元对象系统的类的基类
    • Q_OBJECT 宏,
      定义在每一个类的私有数据段,用来启用元对象功能,比如,动态属性,信号和槽
      元对象编译器moc (the Meta Object Complier),
      moc 分析C++源文件,如果它发现在一个头文件(header file)中包含Q_OBJECT 宏定义,然后动态的生成另外一个C++源文件,这个新的源文件包含 QOBJECT 的实现代码,这个新的 C++ 源文件也会被编译、链接到这个类的二进制代码中去,因为它也是这个类的完整的一部分。通常,这个新的C++ 源文件会在以前的C++ 源文件名前面加上 moc 作为新文件的文件名。其具体过程如下图所示:
      除了提供在对象间进行通讯的机制外,元对象系统还包含以下几种功能:

    • QObject::metaObject() 方法
      它获得与一个类相关联的 meta-object
      QMetaObject::className() 方法
      在运行期间返回一个对象的类名,它不需要本地C++编译器的RTTI(run-time type information)支持

    • QObject::inherits() 方法
      它用来判断生成一个对象类是不是从一个特定的类继承出来,当然,这必须是在QObject类的直接或者间接派生类当中
    • QObject::tr() and QObject::trUtf8()
      这两个方法为软件的国际化翻译字符串
    • QObject::setProperty() and QObject::property()
      这两个方法根据属性名动态的设置和获取属性值

    • 读写属性

    1
    2
    3
    4
    5
    QWidget *w = new QWidget()
    w->setProperty("ABC1",4);
    w->setProperty("ABC2","dddddd");
     
    qDebug() << w->property("ABC1") << w->property("ABC2");

    布署安装

    • 对于开发QT程序来说,最好布署方法就是编译成静态执行文件,只是文件大一点.如果是动态编译就会有一些动态库链接路径的问题.比较特别的它要信赖platforms这个文件路经 .可以通过 QCoreApplication::addLibraryPath(“C:/WINDOWS/System32”);来指定。

    • 下载安装

    • 参考文档,从样本模版里复制一份出来做相应的修改.

    • 一个安装包的目录结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    D:QtDevQtInstaller etmon-root>tree /F
    卷 新加卷 的文件夹 PATH 列表
    卷序列号码为 0006EE44 E462:E6DB
    D:.
    │ build.bat
    ├─config
    │ config.xml
    └─packages
    └─com.vendor.product
    ├─data
    │ │ cares.dll
    │ │ libcjson.dll
    │ │ libcrypto-1_1.dll
    │ │ libcurl.dll
    │ │ libeay32_.dll
    │ │ libgcc_s_dw2-1.dll
    │ │ libmosquitto.dll
    │ │ libssl-1_1.dll
    │ │ libssp-0.dll
    │ │ libstdc++-6.dll
    │ │ libwinpthread-1.dll
    │ │ libz_.dll
    │ │ netmon-tray.exe
    │ │ netmonui_i686.dll
    │ │ print-mon_i686.dll
    │ │ qt.conf
    │ │ Qt5Core.dll
    │ │ Qt5Gui.dll
    │ │ Qt5Network.dll
    │ │ Qt5Widgets.dll
    │ │ ssleay32_.dll
    │ │
    │ ├─imageformats
    │ │ qdds.dll
    │ │ qgif.dll
    │ │ qicns.dll
    │ │ qico.dll
    │ │ qjpeg.dll
    │ │ qsvg.dll
    │ │ qtga.dll
    │ │ qtiff.dll
    │ │ qwbmp.dll
    │ │ qwebp.dll
    │ │
    │ └─platforms
    │ qminimal.dll
    │ qoffscreen.dll
    │ qwindows.dll
    └─meta
    installscript.qs
    license.txt
    package.xml
    page.ui
    • package.xml

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <?xml version="1.0" encoding="UTF-8"?>
      <Package>
      <DisplayName>显示名字</DisplayName>
      <Description>随便写一些东西</Description>
      <Version>0.1.0-1</Version>
      <ReleaseDate>2017-05-11</ReleaseDate>
      <Default>script</Default>
      <Script>installscript.qs</Script>
      <UserInterfaces>
      <UserInterface>page.ui</UserInterface>
      </UserInterfaces>
      </Package>
    • config.xml

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?xml version="1.0" encoding="UTF-8"?>
      <Installer>
      <Name>程序名字</Name>
      <Version>1.0.0</Version>
      <Title>程序的抬头</Title>
      <Publisher>yjdwbj@gmail.com</Publisher>
      <StartMenuDir>网络打印客户端</StartMenuDir>
      <TargetDir>@ApplicationsDir@/NetMon</TargetDir>
      </Installer>
    • isntallscript.qs

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    function Component()
    {
    // constructor
    component.loaded.connect(this, Component.prototype.loaded);
    // 安装完成后自动连接到自动运行的函数
    installer.installationFinished.connect(this,Component.prototype.InstallationFinishedAndRun);
    installer.finishButtonClicked.connect(this,Component.prototype.installationFinished);
    // if (!installer.addWizardPage(component, "Page", QInstaller.TargetDirectory))
    // console.log("Could not add the dynamic page.");
     
    }
     
    Component.prototype.createOperations = function()
    {
    try {
    // call the base create operations function
    component.createOperations();
    component.addOperation("CreateShortcut","C:/WINDOWS/System32/netmon-tray.exe",
    "@StartMenuDir@/网络打印机客户端/网络打印机客户端.lnk","@workDirectory=@TargetDir@");
    component.addOperation("CreateShortcut","@TargetDir@/maintenancetool.exe",
    "@StartMenuDir@/网络打印机客户端/卸载.lnk","@workDirectory=@TargetDir@");
     
    } catch (e) {
    console.log(e);
    }
    }
     
     
    Component.prototype.createOperationsForArchive = function(archive)
    {
    # packagescom.vendor.productdata 下面文件全部解压到system32里。
    component.addOperation("Extract", archive, "C:/WINDOWS/System32");
    }
     
     
    Version:1.0 StartHTML:0000000107 EndHTML:0000006210 StartFragment:0000000471 EndFragment:0000006172
    Component.prototype.InstallationFinishedAndRun = function()
    {
    try {
    if(installer.isInstaller() && installer.status == QInstaller.Success)
    {
    installer.addWizardPageItem(component,"Page",QInstaller.InstallationFinished);
    }
    } catch (e) {
    console.log(e);
    }
    }
     
    Component.prototype.installationFinished = function()
    {
    try {
    if(installer.isInstaller() && installer.status == QInstaller.Success)
    {
    var isRun = component.userInterface("Page").runCheckbox.checked;
    if(isRun)
    {
    QDesktopServices.openUrl("C:/WINDOWS/System32/netmon-tray.exe");
    }
    }
    } catch (e) {
    console.log(e);
    }
    }
    • Page.ui

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      <?xml version="1.0" encoding="UTF-8"?>
      <ui version="4.0">
      <class>Page</class>
      <widget class="QWidget" name="Page">
      <property name="geometry">
      <rect>
      <x>0</x>
      <y>0</y>
      <width>400</width>
      <height>300</height>
      </rect>
      </property>
      <property name="windowTitle">
      <string>Dynamic page example</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
      <item>
      <widget class="QLabel" name="m_pageLabel">
      <property name="alignment">
      <set>Qt::AlignCenter</set>
      </property>
      </widget>
      </item>
      <item>
      <widget class="QCheckBox" name="runCheckbox">
      <property name="text">
      <string>安装完成后,运行该程序</string>
      </property>
      <property name="checked">
      <bool>true</bool>
      </property>
      <property name="tristate">
      <bool>false</bool>
      </property>
      </widget>
      </item>
      </layout>
      </widget>
      <resources/>
      <connections/>
      </ui>
    • 最后这里用一行脚本来生成一键安装包文件。

    1
    binarycreator --offline-only -c D:QtDevQtInstaller etmon-rootconfigconfig.xml -p D:QtDevQtInstaller etmon-rootpackages "Z:/upload/appname-测试版%DATE%-%TIME::=_%.exe"

     

    https://yjdwbj.github.io/2017/01/08/Qt%E7%9A%84%E4%B8%80%E4%BA%9B%E5%BC%80%E5%8F%91%E6%8A%80%E5%B7%A7/

  • 相关阅读:
    perl 解json数组
    华为云3大体系化防护实践,保障金融业云上数据安全
    弹性文件服务解密 -- 块存储、文件存储、对象存储的区别
    【nodejs原理&源码赏析(6)】深度剖析cluster模块源码与node.js多进程
    云+AI+5G时代,华为云已准备好多元化云服务架构
    高能街访 | 为什么他们都纷纷为深圳打Call?
    Angularjs进阶笔记(2)—自定义指令中的数据绑定
    Angularjs进阶笔记(1)—不同类型的双向数据绑定
    ServiceComb java-chassis和CSE java-chassis的区别
    使用inspector功能查看和管理契约
  • 原文地址:https://www.cnblogs.com/findumars/p/9098331.html
Copyright © 2020-2023  润新知