Qt输入窗口部件编程(一) QComboBox和QFontComboBox


前言

从本文开始,我们系列文章开始介绍Qt输入窗口部件编程。本文介绍QComboBox组合框和 QFontComboBox字体组合框编程。通过这个例子,继续巩固QT的信号与槽知识,了解qt4与qt5信号与槽函数的连接方式的不同。

本例程设计是在chatgpt的帮助下完成的,编译代码经过测试通过。

感谢朋友提供的chatgpt软件,特别是其中的gpt-box桌面工具,更是我离不开的工具。感兴趣的同仁可前往一观( www.apsuai.com)。

我们的调试环境仍然是双架构Kits,编译调试在当前的ubuntu(qt5)中进行,重新编译后下载到目标arm设备(qt4)中运行。
我们的编程环境为:Ubuntu64位系统(22.04),目标架构:
(1) qt5 x86_64 架构;
(2)qt4 32位arm架构。
环境配置请参见《Qt常用的按钮控件编程(一)》第1节。


1、 Qt常用的输入窗口控件

在这里插入图片描述

  1. Comb Box:组合框
  2. Font Comb Box:字体组合框
  3. Line Edit:单行编辑框
  4. Text Edit:文本编辑框
  5. Plain Text Edit:纯文本编辑框
  6. Spin Box:数字旋转框
  7. Double Spin Box:双精度数字旋转框
  8. Time Edit:时间编辑框
  9. Date Edit:日期编辑框
  10. Date/Time Edit:日期时间编辑框
  11. Dial:数字拨盘框
  12. Horizontal Scroll Bar:水平滚动条
  13. Vertical Scroll Bar:垂直滚动条
  14. Horizontal Slider:水平滑动条
  15. Vertical Slider:垂直滑动条
  16. Key sequence Edit:按键序列编辑框
    在以后编程示例中我们会详细介绍这些控件。

2、QFontComboBox 和 QComboBox控件编程

2.1 控件简介

2.1.1 QComboBox组合框

QComboBox是Qt中的一个控件类,用户可以从下拉列表中选择一个值。当用户点击下拉箭头,一个列表就会展开,以显示可用选项。用户可以从列表中选择一个选项,所选选项将作为组合框的当前值。
QComboBox是一个强大的组合框控件,可以用于在GUI中选择从一组值中选择的值。例如,在绘图应用中,可以使用QComboBox来选择画笔颜色、字体、线型等。QComboBox也可以用于选择文件格式、数据源等。

以下是QComboBox的一些常用函数和信号:

  • addItem(text: str, userData: Any = None): 向下拉列表框中添加一个选项。
  • removeItem(index: int): 从下拉列表框中移除指定的选项。
  • clear(): 清除下拉列表框中的所有选项。
  • currentTextChanged(text: str): 当用户选择新选项时,发出此信号。

2.1.2 QFontComboBox字体组合框

QFontComboBox是QComboBox类的一个子类,继承了QComboBox的所有功能。QFontComboBox是Qt为了方便开发者使用而提供的一个特殊控件,可以将其视为Qt的语法糖。它大大简化开发过程,并使代码更易于理解和维护,但其实它内部实现并不简单,需要扫描操作系统中所有已安装的字体,并格式化这些字体进行显示,同时提供信号来捕获所选字体的更改。

2.2 例程功能设计

向chatgpt提出的要求如下:
“使用Qt Creator 创建一个c++例程,项目名称"_qcombobox" ,基类不选默认MainWindow类,而选择Widget作为基类,不要勾选“Generate form”,不使用拖取控件,控件全部采用编程。主窗口大小800*480。在主窗口上,放置一个 QComboBox控件控件用来选择颜色,放置一个 QFontComboBox 控件用来选择字体,选择后,用槽函数将综合选择的结果体现在一个QTextEdit控件中。“
chatgpt根据要求给出了完整的例程,经过少量调整就能满足我们的需求。

2.3 例程执行效果

在主窗口上,左上放置一个 QComboBox控件,点击后显示的下拉框可以改变下部文本框(QTextEdit控件)选中文本的颜色,右上放置一个QFontComboBox控件,点击后出现许多中文字体可供选择,选中其中之一,文本框中的全部内容会按照选择的字体发生改变,如下图:

在这里插入图片描述

2.4 生成项目

使用Qt Creator 创建一个c++例程,项目名称"_qcombobox" ,不选默认MainWindow类,选择Widget作为基类,不要勾选“Generate form”,不使用拖取控件,控件全部采用编程。将两个配置好的Kits同时选上,项目新建完成如下图。(详细的项目新建过程参见:《Qt常用的按钮控件编程(一)》)。
在这里插入图片描述
点击左侧的Debug选项,可以看到两个编译套件Kit,可以选择编译运行在不同平台上的可执行文件,arm-v7为arm架构的设备,使用Qt4库,而桌面则是当前ubuntu系统,使用Qt5。

2.5 代码编辑

2.5.1 修改项目文件_qcombobox.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

# 根据使用的 Qt 版本设置编译条件
greaterThan(QT_MAJOR_VERSION, 4) {
    # 如果使用的是 Qt 5 或者更新版本
    message("使用的是 Qt 5版本")

} else {
    # 如果使用的是 Qt 4 或者更早的版本
    message("使用的是 Qt 4版本")
    DEFINES += QT_ARM_PLATFORM
    QMAKE_CXXFLAGS += -std=c++11
    QMAKE_CXXFLAGS += -Wno-psabi -Wno-deprecated-declarations

    LIBS += -lts

}

2.5.2 修改 main.cpp

#include "widget.h"

#include <QApplication>
#ifdef QT_ARM_PLATFORM
#include <QTextCodec>
#endif
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

#ifdef QT_ARM_PLATFORM
    //解决Qt4中文乱码
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("system"));    //若英文系统,则用GBK
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
    Widget w;
    w.show();
    return a.exec();
}

2.5.3 修改 widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QFontComboBox>
#include <QTextEdit>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void setColor(int index);
    void setFont(const QFont &font);

private:
    QComboBox *colorComboBox;
    QFontComboBox *fontComboBox;
    QTextEdit *textEdit;
    QHBoxLayout *comboLayout;
    QVBoxLayout *layout;

};
#endif // WIDGET_H

2.5.4 修改 widget.cpp

#include "widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle("ComboBox Example");
    resize(800, 480);




    colorComboBox = new QComboBox;
#ifdef QT_ARM_PLATFORM
/*对于 Qt4,其中的 C++11 功能实现是不完整的,因此很多 C++11 的新特性是无法使用的,比如必须使用分离引用声明方式初始化 QString 对象 QStringList。*/

    QStringList colors;
    colors << "Red" << "Green" << "Blue";
#else
/*在 Qt5 的连接语法中,我们可以使用分离引用声明方式({}语法)来初始化 QObject 的对象或其子类。*/
    QStringList colors = {"Red", "Green", "Blue"};
#endif

    colorComboBox->addItems(colors);


    fontComboBox = new QFontComboBox;

    fontComboBox->setWritingSystem(QFontDatabase::SimplifiedChinese);

    textEdit = new QTextEdit("你好 Qt 例程!!!!");
    textEdit->setFont(QFont("宋体", 28));
    comboLayout = new QHBoxLayout();
    comboLayout->addWidget(colorComboBox);
    comboLayout->addWidget(fontComboBox);

    layout = new QVBoxLayout();
    layout->addLayout(comboLayout);
    layout->addWidget(textEdit);


    this->setLayout(layout);


#ifdef QT_ARM_PLATFORM
    connect(colorComboBox, SIGNAL(activated(int)), this, SLOT(setColor(int)));
    connect(fontComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(setFont(QFont)));
#else

    connect(colorComboBox, QOverload<int>::of(&QComboBox::activated), this, &Widget::setColor);
    connect(fontComboBox, &QFontComboBox::currentFontChanged, this, &Widget::setFont);

#endif

}

Widget::~Widget()
{
}

void Widget::setColor(int index)
{

    switch (index) {
    case 0:
        textEdit->setTextColor(Qt::red);
        break;
    case 1:
        textEdit->setTextColor(Qt::green);
        break;
    case 2:
        textEdit->setTextColor(Qt::blue);
        break;
    }
}

void Widget::setFont(const QFont &font)
{
    QFont font1=font;

    font1.setPointSize(28);
    textEdit->setFont(font1);
}

2.6 切换Kit,获得运行在不同系统中的运行的执行文件

点击窗口左边的Debug,可以选择编译运行在不同平台上的可执行文件,arm-v7为arm架构的设备,使用Qt4库,而桌面则是当前ubuntu系统,使用Qt5。(参见2.4节)
Qt5编译完成的可执行程序_qcombobox,存放在项目目录的build-_qcombobox-unknown-Debug/文件夹下,Qt4编译完成的同名可执行程序_qcombobox,存放在项目目录的build-_qcombobox-arm_v7-Debug/文件夹下。

将程序下载到多台设备arm设备上测试,大多数设备上Font Comb Box能够正常工作,而某些设备则出现触摸完全无效的情况,这是由于很多输入窗口控件在Qt4、tslib环境下工作不正常所致,如果希望彻底解决问题,最好将系统升级到Qt5。

2.7 程序中的qt机制分析

2.7.1 qt4与qt5信号与槽函数的连接方式比较

在前面的代码中,qt4的连接方式:

   connect(colorComboBox, SIGNAL(activated(int)), this, SLOT(setColor(int)));
   connect(fontComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(setFont(QFont)));

而在qt5中,代码如下:

connect(colorComboBox, QOverload<int>::of(&QComboBox::activated), this, &Widget::setColor);
connect(fontComboBox, &QFontComboBox::currentFontChanged, this, &Widget::setFont);

在 Qt4 中,我们使用 SIGNAL 和 SLOT 宏来连接信号和槽函数,需要在编译时进行字符串匹配,这种方式存在以下几个限制:

  • 一些字符串的名字不容易重构或改写,对翻译的支持也不够良好;
  • 对于多重重载函数,必须手动将参数写成字符串,并且和函数实际的参数类型及个数完全匹配;
  • 必须写出 Qt 提供的信号和槽函数的名称,反射机制不够灵活。

而在 Qt5 中,我们可以使用更安全、类型安全的函数指针连接两个对象的信号和槽函数,避免了字符串相关的限制和风险,提供了更加完善和方便的信号槽组合。使用 QOverload 来连接重载的信号和槽函数,它具有以下优势:

  • 可以在 compile time(编译时间) 保证参数类型和数目正确,避免了类型安全问题;
  • 可以通过函数指针灵活地选择任何重载,不必指定参数类型字符串;
  • 更稳健、更高效、更具有可读性。

“compile time”(编译时间),是指程序的编译期间,也就是源代码被编译器编译成可执行文件之前的时间段。这个阶段的操作包括词法分析、语法分析、语义分析、代码生成、优化等,可以将源代码转换为机器代码或字节码等。
“runtime”(运行时)是指程序的执行期间,也就是可执行文件开始执行到结束的时间段。这个时间段的操作包括栈和堆的分配、变量赋值、函数调用、I/O 操作等与计算机硬件和操作系统相关的的操作。

总结

本文介绍QComboBox组合框和 QFontComboBox字体组合框编程。例程的设计是在chatgpt的帮助下完成的。
AI 技术的快速发展将深刻地改变我们生活的各个方面。chatgpt 的自动代码生成功能给予了程序员一个全新的编程体验,只需要清晰地描述需求,chatgpt 就可以为我们提供相应的代码建议,极大地提高了开发效率和准确性。只需要少量的修改和调整,便可以轻松地将它们应用于实际项目中。
当前的chatgpt由于对篇幅的限制,目前还不能做比较大的项目,但已经能够为我们提供很多的代码模块,大大减轻了开发强度和难度。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要想使用Qt实现一个好看的QComboBox,可以通过设置样式表、使用QIcon、设置QFont和设置数据模型等来实现。下面是一个示例代码,可以用于设置一个好看的QComboBox: ```cpp #include <QApplication> #include <QComboBox> #include <QStandardItemModel> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建QComboBox QComboBox combo; // 设置样式表 combo.setStyleSheet("QComboBox {" "border: 2px solid gray;" "border-radius: 8px;" "padding: 2px 16px 2px 8px;" "color: white;" "background-color: #292929;" "}" "QComboBox::drop-down {" "subcontrol-origin: padding;" "subcontrol-position: top right;" "width: 24px;" "border-left-width: 1px;" "border-left-color: gray;" "border-left-style: solid;" "border-top-right-radius: 8px;" "border-bottom-right-radius: 8px;" "background-color: #292929;" "}" "QComboBox::down-arrow {" "image: url(arrow.png);" "width: 16px;" "height: 16px;" "}"); // 设置图标 QIcon icon("arrow.png"); combo.setIcon(icon); // 设置字体和大小 QFont font("Arial", 12); combo.setFont(font); // 设置数据模型 QStandardItemModel model; model.appendRow(new QStandardItem("Item 1")); model.appendRow(new QStandardItem("Item 2")); model.appendRow(new QStandardItem("Item 3")); combo.setModel(&model); // 显示QComboBox combo.show(); return a.exec(); } ``` 这段代码会创建一个带有自定义样式、图标、字体和数据模型的QComboBox,并将其显示出来。你可以根据自己的需求修改样式表、图标、字体和数据模型,以达到自己想要的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值