4. 基础控件

Qt可分为QCheckBox、QPushButton、和QListView、QCalendarWidget等基础控件, QStatckedWidget、QTabWidget等具有相同属性的组合控件,以及QDialog,QFrame等抽象控件。

下图是Qt控件的继承关系图(图片来源于互联网)

class001

Qt的基础控件统一由QWidget派生出来,其中:

  • QAbstractButton、QAbstractSlider、QAbstractSpinBox为三个抽象类,分别抽象出按键、滑块、旋钮控件的基本特性,进而由其子类实现成具体的控件。

  • QDialog为Qt中的对话框,具体表现有文件对话框,字体对话框,颜色对话框等一系列组件.

  • QFrame是存放架构控件的基类,进一步派生出了QLabel,QTextEdit等等控件

  • 除此以外还有很多具备特定功能的高级控件,比如涉及到模型/视图的View控件等等。

这一章节我们主要讲解Qt中的基础控件,介绍这些控件长什么样,具备什么样的功能,怎么样使用。

在此之前我们先了解这些控件(类)的使用方法,在我们 Qt Creator 中,有一个帮助按钮,点击帮助,切换到查找, 在下面的搜索栏中输入我们要查到的类或关键词。

controlui000

我们这里搜索QAbstractButton 会出现如下结果,结果中就包含该类的介绍,使用方法。

4.1. QAbstractButton

在Qt中QAbstractButton这个类实现一个抽象按钮。此类的子类处理用户操作,并指定如何绘制按钮。

QAbstractButton同时支持push和toggle。 toggle在其子类QRadioButton和QCheckBox类中实现;push在QPushButton和QToolButton类中实现。

任何按钮都可以显示包含文本和图标。 我们可以通过setText()来设置文本;setIcon()来设置图标。 除此以外,按钮在按下和抬起,选中和未选中,使能和失能都可以设置成不同的显示效果

QAbstractButton提供了用于按钮的大多数状态:

  • isDown() 指示是否按下按钮。

  • isChecked() 指示按钮是否已选中。只能选中和取消选中可检查的按钮(请参阅下文)。

  • isEnabled() 指示用户是否可以按下按钮。

  • setAutoRepeat() 设置如果用户按下按钮,按钮是否将自动重复。autoRepeatDelay和autoRepeatInterval定义如何进行自动重复。

  • setCheckable() 设置按钮是否为切换按钮。

isDown()和isChecked()之间的区别如下。当用户单击切换按钮进行检查时,首先按下该按钮,然后将其释放到选中状态。 当用户再次单击它(以取消选中它)时,该按钮首先移至按下状态,然后移至未选中状态(isChecked()和isDown()均为false)。

QAbstractButton提供了四个信号:

  • pressed() 当鼠标光标位于按钮内部时,如果按下鼠标左键,则将发出此信号

  • released() 释放鼠标左键时,产生released信号。

  • clicked() 当按钮第一次被按下随即被释放时,或者有快捷键被触发,或click()或animateClick()被调用时会产生此信号。

  • toggled() 当切换按钮的状态更改时会触发此信号。

我们直接在QtDesigner中使用的控件,QPushButton,QToolButton,QRadioButton,QCheckBox等都是通过继承QAbstractButton,获得以上属性, 并通过重新实现paintEvent(),用来绘制按钮的轮廓及其文本或像素图。

4.1.1. QPushButton

按钮或命令按钮可能是任何图形用户界面中最常用的窗口小部件。 按下(单击)按钮以命令计算机执行某些操作或回答问题。典型的按钮是“确定”,“应用”,“取消”,“关闭”,“是”,“否”和“帮助”。

我们在例程中使用了四个按钮,Qt原生QPushButton如下:

control001

我们将QPushButton的clicked()信号绑定到pushbutton_clicked()槽函数,当按钮被按下时就执行槽函数中的内容。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//绑定槽函数
QList<QPushButton*> btnlist = ui->stackedWidget->findChildren<QPushButton*>();
foreach(auto btn, btnlist)
{
    connect(btn,SIGNAL(clicked()),this,SLOT(pushbutton_clicked()));
}

//槽函数
void MainWindow::pushbutton_clicked()
{
    QPushButton* btn= qobject_cast<QPushButton*>(sender());
    if(btn->objectName()=="btn_2")
    {
        if(btn->isChecked())
            ui->statusBar->showMessage(QString("%1按下").arg(btn->objectName()));
        else
            ui->statusBar->showMessage(QString("%1弹起").arg(btn->objectName()));

        return;
    }

    ui->statusBar->showMessage(QString("%1被点击").arg(btn->objectName()));
}

在槽函数中,我们在statusBar中显示,具体哪一个按键被按下。 当然在实际应用中,我们回赋予每一个按钮实际的功能。 我们也可以采用上一章节中on_xxxx_clicked()的写法,让每一个按键对应一个槽函数。

4.1.2. QToolButton

工具按钮是一种特殊按钮,可用于快速访问特定命令或选项。 与普通命令按钮相反,工具按钮通常不显示文本标签,而是显示图标。

工具按钮的图标设置为QIcon。这使得可以为禁用状态和活动状态指定不同的像素图。 当按钮的功能不可用时,将使用禁用的像素图。当自动升高按钮时,由于鼠标指针悬停在其上,因此将显示活动的像素图。

例程中也使用了四个工具按钮,使用方法和QPushButton差不多:

control002

将工具按钮的clicked()信号绑定到toolbutton_clicked(),点击工具按钮以实现特定的功能。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 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
//将按钮设置为可保存状态的形式
ui->tbtn_2->setCheckable(true);

//绑定信号和槽
QList<QToolButton*> tbtnlist = ui->stackedWidget->findChildren<QToolButton*>();
foreach(auto tbtn, tbtnlist)
{
    connect(tbtn,SIGNAL(clicked()),this,SLOT(toolbutton_clicked()));
}

//槽函数
void MainWindow::toolbutton_clicked()
{
    QToolButton* tbtn= qobject_cast<QToolButton*>(sender());

    if(tbtn->objectName()=="tbtn_2")
    {
        if(tbtn->isChecked())
            ui->statusBar->showMessage(QString("%1按下").arg(tbtn->objectName()));
        else
            ui->statusBar->showMessage(QString("%1弹起").arg(tbtn->objectName()));

        return;

    }

    ui->statusBar->showMessage(QString("%1被点击").arg(tbtn->objectName()));
}

这里呢,将 tbtn_2 通过其 setCheckable() 将按钮设置为可保存状态的形式,并通过 isChecked() 来判断工具按钮按下弹起状态。

4.1.3. QRadioButton

QRadioButton是一个选项按钮,可以打开(选中)或关闭(取消选中)。

通常情况下QRadioButton为单选,当存在多个选项的时候,我们可以设置一组QRadioButton(将多个按钮放入QButtonGroup), 使能autoExclusive属性,这时同一组的QRadioButton只能选中一个选项。

每当按钮打开或关闭时,它都会发出change() 信号。如果您想在每次按钮更改状态时触发一个动作,请连接到此信号。 使用isChecked() 查看是否选择了特定按钮。

就像QPushButton一样,单选按钮可以显示文本,还可以显示一个小图标。该图标使用setIcon() 设置。 可以在构造函数中或使用setText() 设置文本。可以通过在文本中的首选字符前面加上“&”符号来指定快捷键。

control003
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
QList<QRadioButton*> rbtnlist = ui->stackedWidget->findChildren<QRadioButton*>();
foreach(auto rbtn, rbtnlist)
{
    connect(rbtn,SIGNAL(clicked()),this,SLOT(radiobutton_clicked()));
}

void MainWindow::radiobutton_clicked()
{
    QRadioButton* rbtn= qobject_cast<QRadioButton*>(sender());

    ui->statusBar->showMessage(QString("%1被选中").arg(rbtn->objectName()));
}

我们依然只是将QRadioButton的clicked()信号和槽连接起来,用于判断那个按钮被选中了。

4.1.4. QCheckBox

QCheckBox是一个选项按钮,可以打开(选中)或关闭(取消选中)。

QCheckBox则通常多为复选框,复选框通常用于表示应用程序中可以启用或禁用而不会影响其他功能的功能。

control004
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
QList<QCheckBox*> cboxlist = ui->stackedWidget->findChildren<QCheckBox*>();
foreach(auto cbox, cboxlist)
{
    connect(cbox,SIGNAL(stateChanged(const int)),this,SLOT(checkbox_stateChange(const int)));
}

void MainWindow::checkbox_stateChange(const int state)
{
    QCheckBox* cbox= qobject_cast<QCheckBox*>(sender());

    if(state)
        ui->statusBar->showMessage(QString("%1被选中").arg(cbox->objectName()));
    else
        ui->statusBar->showMessage(QString("%1未选中").arg(cbox->objectName()));

}

4.1.5. QComboBox

QComboBox提供了一种以占用最少屏幕空间的方式向用户显示选项列表的方法。

组合框是显示当前项目的选择小部件,并且可以弹出可选项目的列表。组合框可能是可编辑的,从而允许用户修改列表中的每个项目。

组合框可以包含像素图和字符串。适当地重载了insertItem()和setItemText()函数。 对于可编辑的组合框,提供了函数clearEditText(),以清除显示的字符串,而不更改组合框的内容。

如果组合框的当前项目发生更改,则会发currentIndexChanged(),currentTextChanged()和Activated()三个信号。 无论更改是通过编程方式还是通过用户交互完成,始终都会发出currentIndexChanged()和currentTextChanged(),而仅是由用户交互引起时才发出activate()。

control005
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
//设置comboBox选项
QStringList sizelist;
sizelist<< "12"<<"14"<<"16"<<"18"<<"20";
ui->comboBox->addItems(sizelist);

//选项改变时,设置app字体大小
void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
    QFont font = qApp->font();
    font.setPointSize(arg1.toInt());
    qApp->setFont(font);
    this->update();
    ui->statusBar->showMessage(QString("当前字号:%1").arg(arg1));
}

在例程中,我们通过 addItems() 方法将我们预设的字号插入到组合框中,当我们改变组合框中的选项时, 信号和槽会传递切换之后的组合框被选中的选项中的文字,即我们设置的字号,再通过qApp->setFont(),来设置app的字号。

4.1.6. QFontComboBox

QFontComboBox继承自QComboBox,组合框中填充了按字母顺序排列的字体系列名称列表,例如Arial,Helvetica和Times New Roman。

在使用之前我们可调用setWritingSystem()告诉QFontComboBox仅显示支持给定书写系统的字体,也可以调用setFontFilters()过滤掉某些类型的字体,例如不可缩放的字体或等宽字体。

当选择新字体时,除了currentIndexChanged()之外,还会发出currentFontChanged()信号,传递当前选项中的字体。

control006
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
3
4
5
void MainWindow::on_fontComboBox_currentFontChanged(const QFont &f)
{
    qApp->setFont(f);
    ui->statusBar->showMessage(QString("当前字体设置为:%1").arg(f.family()));
}

例程中QFontComboBox复选框选项发生改变时,我们通过setFont()设置app的字体。

4.2. QAbstractSlider

QAbstractSlider 该类被设计为QScrollBar,QSlider和QDial之类的小部件的公共类。

这是该类的主要属性:

  • value:QAbstractSlider当前的值。

  • minimum:可能的最小值。

  • maximum:可能的最大值。

  • singleStep:抽象滑块提供的两个自然步骤中的较小者,通常对应于用户按下箭头键。

  • pageStep:抽象滑块提供的两个自然步骤中的较大者,通常对应于用户按下PageUp或PageDown的情况。

  • tracking: 是否启用了滑块跟踪。

  • slidePosition:滑块的当前位置。如果启用了跟踪(默认设置),则此值与value相同。

QAbstractSlider有如下信号:

  • valueChanged() value值已更改。

  • slidePressed() 用户开始拖动滑块。

  • slideMoved() 用户拖动滑块。

  • slideReleased() 用户释放滑块。

  • actionTriggered() 触发了滑块操作。

  • rangeChanged() minimum-maximum范围已更改。

4.2.1. QSlider

滑块是用于控制有界值的经典小部件。它使用户可以沿水平或垂直凹槽移动滑动手柄,并将手柄的位置转换为合法范围内的整数值。

Qt中QSlider原生控件如下:

control008

在例程中,我们直接将QSlider的 valueChanged(int) 信号和QProgressBar的 setValue(int) 进行绑定

controlui001

最终效果就是当我们拖动滑块的手柄,进度条也跟着变化。

4.2.2. QScrollBar

滚动条,使用户能够访问文档中大于用于显示文档的窗口小部件的部分。它提供了用户在文档中当前位置以及可见文档数量的视觉指示。 滚动条通常配有其他控件,可以实现更准确的导航。

control009

在例程中我们使用了一个定时器,每隔1s调整滚动条的值。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
QTimer *timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(handletimeout()));
timer->start(1000);

void MainWindow::handletimeout()
{
    static int curr=0;
    ui->horizontalScrollBar->setValue(curr);
    ui->verticalScrollBar->setValue(curr);
    if(curr++>ui->horizontalScrollBar->maximum())
        curr=0;
}

4.2.3. QDial QLcdNumber

当用户需要将值控制在程序可定义的范围内,并且该范围可以环绕(例如,角度范围从0到359度)或对话框布局需要方形小部件时,可以使用QDial。

由于QDial继承自QAbstractSlider,因此刻度盘的行为与滑块类似。当wrap()为false(默认设置)时,滑块和拨盘之间没有真正的区别。 它们都共享相同的信号,插槽和成员功能。您使用哪一种取决于用户的期望和应用程序的类型。

QLcdNumber可以显示几乎任何大小的数字。它可以显示十进制,十六进制,八进制或二进制数字。 使用display()插槽可以很容易地连接到数据源,该槽函数可以重载五种参数类型中的任何一种。

在例程中,我们直接将QDial的 sliderMoved(int) 信号和display(int)进行绑定,当滑动QDial时,QLcdNumber上面的值就会随之改变。

control010
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
//设置QDial值得范围
ui->dial->setRange(0,255);

4.2.4. QProgressBar

进度条用于向用户指示操作的进度,并向他们显示应用程序仍在运行。

进度条使用通常先指定最小和最大可能的步长值,然后设置当前得值,它最终将显示已完成的百分比。 百分比是通过 (value-minimum)/(maximum-minimum) 计算得出的。

control011

4.3. QAbstractSpinBox

QAbstractSpinBox 是QSpinBox,QDoubleSpinBox和QDateTimeEdit的抽象类。

这是该类的主要属性:

  • text:在控件中显示的文本。

  • alignment:文本的对齐方式。

  • wrapping: 否从最小值包装到最大值。

QAbstractSpinBox提供了一个虚拟的stepBy()函数,只要用户触发了一个步骤,就会调用该函数。此函数采用整数值表示已执行了多少步骤

4.3.1. QSpinBox、QDoubleSpinBox

QSpinBox旨在处理整数和离散值集(例如,月份名称);使用QDoubleSpinBox作为浮点值。

QSpinBox允许用户通过单击上/下按钮或按键盘上的上/下按钮来选择/选择一个值,以增加/减少当前显示的值。用户也可以手动输入该值。 旋转框支持整数值,但可以扩展为使用带有validate(),textFromValue()和valueFromText()的不同字符串。

每次值更改时,QSpinBox(QDoubleSpinBox)都会发出valueChanged()和textChanged()信号,前者提供一个int(double)值,而后者提供一个QString。 当前值可以使用value() 获取当,也可以使用setValue() 对当前值进行设置。

control007

在例程中,我们使用了两个spinBox和一个doubleSpinBox,分别用来表示颜色的RGB值, 对每个控件值的范围进行限定,限定值为0-255。

采用 on_xxxx_valueChanged() 的形式,绑定信号和槽。当控件的值发生改变时,就会执行槽函数中的内容。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ui->spinBox_R->setRange(0,255);
ui->spinBox_G->setRange(0,255);
ui->doubleSpinBox_B->setRange(0,255);

ui->spinBox_R->setValue(0);
ui->spinBox_G->setValue(0);
ui->doubleSpinBox_B->setValue(0);

void MainWindow::on_spinBox_R_valueChanged(int )
{
    ui->gBox_Box->setStyleSheet(QString("color:rgb(%1, %2, %3)").arg(ui->spinBox_R->value()).arg(ui->spinBox_G->value()).arg(ui->doubleSpinBox_B->value()));
    ui->statusBar->showMessage(QString("字体颜色:rgb(%1, %2, %3)").arg(ui->spinBox_R->value()).arg(ui->spinBox_G->value()).arg(ui->doubleSpinBox_B->value()));
}
void MainWindow::on_spinBox_G_valueChanged(int )
{
    ui->gBox_Box->setStyleSheet(QString("color:rgb(%1, %2, %3)").arg(ui->spinBox_R->value()).arg(ui->spinBox_G->value()).arg(ui->doubleSpinBox_B->value()));
    ui->statusBar->showMessage(QString("字体颜色:rgb(%1, %2, %3)").arg(ui->spinBox_R->value()).arg(ui->spinBox_G->value()).arg(ui->doubleSpinBox_B->value()));
}

void MainWindow::on_doubleSpinBox_B_valueChanged(double )
{
    ui->gBox_Box->setStyleSheet(QString("color:rgb(%1, %2, %3)").arg(ui->spinBox_R->value()).arg(ui->spinBox_G->value()).arg(ui->doubleSpinBox_B->value()));
    ui->statusBar->showMessage(QString("字体颜色:rgb(%1, %2, %3)").arg(ui->spinBox_R->value()).arg(ui->spinBox_G->value()).arg(ui->doubleSpinBox_B->value()));
}

在槽函数中,我们通过QSS来设置样使表,修改字体显示的颜色。

4.3.2. QDateTimeEdit

QDateTimeEdit允许用户通过使用键盘或箭头键来增加和减少日期和时间值来编辑日期。 箭头键可用于在QDateTimeEdit框中的一个区域移动。

日期和时间可设置的显示格式,比如 yyyy年MM月dd日 hh:mm:ss 最终显示为 2021年3月20日 14:08:56;yyyy-MM-dd hh:mm:ss 最终显示为2021-3-20 14:08:56 格式可通过setDisplayFormat()来设置。

control012
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
3
4
5
6
7
ui->dateEdit->setDisplayFormat("yyyy年MM月dd日");
ui->dateEdit->setDate(QDate::currentDate());

void MainWindow::on_dateTimeEdit_dateTimeChanged(const QDateTime &dateTime)
{
    ui->statusBar->showMessage(QString("当前时间日期:%1").arg(dateTime.toString("yyyy-MM-dd hh:mm:ss")));
}

Qt中用QDateTime这个类来记录时间日期,我们可以使用QDateTime::currentDateTime()获取当前的时间日期, 也可以用toString()方法来转成字符串。

4.3.3. QTimeEdit、QDateEdit

QTimeEdit、QDateEdit是QDateTimeEdit的子类,一个用于时间,一个用于日期。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
3
4
5
6
7
ui->timeEdit->setDisplayFormat("hh:mm:ss");
ui->timeEdit->setTime(QTime::currentTime());

void MainWindow::on_timeEdit_userTimeChanged(const QTime &time)
{
    ui->statusBar->showMessage(QString("当前时间:%1").arg(time.toString("hh:mm:ss")));
}
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
3
4
5
6
7
8
ui->dateTimeEdit->setDisplayFormat("yyyy年MM月dd日 hh:mm:ss");
ui->dateTimeEdit->setDateTime(QDateTime::currentDateTime());

void MainWindow::on_dateEdit_userDateChanged(const QDate &date)
{
    ui->calendarWidget->setSelectedDate(date);
    ui->statusBar->showMessage(QString("当前日期:%1").arg(date.toString("yyyy-MM-dd")));
}

在示例中,我们将QDateEdit和QCalendarWidget关联起来,当两个控件中的任意一个控件的日期改变时, 另一个控件对应的日期也会发生相应的改变。

4.3.4. QCalendarWidget

Qt提供一个日历的小窗口

control013
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
3
4
5
void MainWindow::on_calendarWidget_clicked(const QDate &date)
{
    ui->dateEdit->setDate(date);
    ui->statusBar->showMessage(QString("当前日期:%1").arg(date.toString("yyyy-MM-dd")));
}

4.4. 其他基础控件

4.4.1. QLabel

QLabel用于显示文本或图像。没有提供用户交互功能。

control014
embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
1
2
3
4
5
6
7
8
9
ui->lab_1->setText("123");
QPixmap pix(":/images/camera/take_pressed.png");
ui->lab_2->setPixmap(pix);
QMovie *movie = new QMovie(":/images/etc/2021-3-20.gif");
movie->setScaledSize(ui->lab_2->size());
movie->start();
ui->lab_3->setMovie(movie);
ui->lab_3->setScaledContents(true);
ui->lab_4->setText("<p style=\"color:red;font-size:16px;\"> hello <b style=\"color:black;font-size:22px;\">QLabel</b></p>");
controlui002

在例程中,我们通过 setText() 来设置文字,setPixmap() 来设置图片; setMovie() 来设置GIF动画,我们还可以通过html来显示更多样式的文字。

4.4.2. QLineEdit

行编辑允许用户使用有用的编辑功能集合输入和编辑一行纯文本,包括撤消和重做,剪切和粘贴以及拖放

我们可以通过设置相关的属性来实现某些功能,比如 setEchoMode(QLineEdit::Password) ,将设置QLineEdit的回显为passwd模式; setPlaceholderText() 可设置提示文本;除此以外还可以使用正则表达式来限制输入。

control015

在例程中,我们将LineEdit的 textEdited(const QString)returnPressed() 信号分别绑定到槽函数 lineedit_textEdited(const QString)lineedit_returnPressed() ; 当我们编辑LineEdit的文字的时候,编辑的文字会被显示到plainTextEdit中, 当我们在LineEdit中点击回车时,控件中的文字会被追加到textBrowser中。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 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
ui->lineEdit_1->setText("123");
ui->lineEdit_2->setPlaceholderText("默认显示");
QRegExp regx("[0-9]+12");
ui->lineEdit_3->setValidator(new QRegExpValidator(regx, this));
ui->lineEdit_4->setEchoMode(QLineEdit::Password);

QList<QLineEdit*> linelist = ui->stackedWidget->findChildren<QLineEdit*>();
foreach(auto line, linelist)
{
    connect(line,SIGNAL(textEdited(const QString)),this,SLOT(lineedit_textEdited(const QString)));
    connect(line,SIGNAL(returnPressed()),this,SLOT(lineedit_returnPressed()));
}

void MainWindow::lineedit_returnPressed()
{
    QLineEdit* line= qobject_cast<QLineEdit*>(sender());
    QString str= line->text();
    if(str.isEmpty())
        return;

    line->clear();
    ui->plainTextEdit->appendPlainText(">>> "+ str);
}

void MainWindow::lineedit_textEdited(const QString str)
{
    //QLineEdit* line= qobject_cast<QLineEdit*>(sender());
    ui->textBrowser->clear();
    ui->textBrowser->append(str);
}

4.4.3. QTextEdit

QTextEdit是一种高级WYSIWYG查看器/编辑器,支持使用HTML样式的标记或Markdown格式的富文本格式。 它经过优化,可处理大型文档并快速响应用户输入。

QTextEdit适用于段落和字符。段落是经过格式化的字符串,将其自动换行以适合窗口小部件的宽度。 默认情况下,阅读纯文本时,一个换行符表示一个段落。一个文档包含零个或多个段落。 段落中的单词根据段落的对齐方式对齐。段落之间用强行换行符分隔。段落中的每个字符都有其自己的属性,例如字体和颜色。

QTextEdit可以显示图像,列表和表格。如果文本太大而无法在文本编辑的视口中查看,则会出现滚动条。 文本编辑可以加载纯文本文件和富文本文件。富文本可以使用HTML 4标记的子集来描述;

Qt中的富文本格式支持旨在提供一种快速,便携式和高效的方法,为应用程序添加合理的在线帮助功能,并为富文本编辑器提供基础支持。

control016

4.4.4. QTextBrowser

QTextBrowser扩展了QTextEdit(以只读模式),并添加了一些导航功能,以便用户可以跟踪超文本文档中的链接。

4.4.5. QPlainTextEdit

QPlainTextEdit是支持纯文本的高级查看器/编辑器。它经过优化,可处理大型文档并快速响应用户输入。 QPlainText使用与QTextEdit几乎相同的技术和概念,但针对纯文本处理进行了优化。

4.5. 例程说明

野火提供的Qt Demo已经开源,仓库地址在:

文档所涉及的示例代码也提供下载,仓库地址在:

本章例程在 embed_qt_develop_tutorial_code/Control_1

例程展示了大多数Qt基础控件,并提供了一些简单的示例应用。

4.5.1. 编程思路

  • 首先创建一个空工程;

  • 在UI放置stackedWidget作为主窗口;

  • 将我们要演示的控件分别添加到stackedWidget中;

  • 通过菜单栏对stackedWidget显示页面进行切换,显示不同控件。

  • 代码中将控件的信号绑定到自定义的槽。

  • 在自定义的槽函数中实现该控件的常用示例;

4.5.2. 代码讲解

在介绍控件的时候,已经对控件使用的代码进行了讲解。 这里讲解一下,信号与槽的绑定,页面的切换等。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void MainWindow::inttControl()
{
    connect(ui->action_bar,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));
    connect(ui->action_btn,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));
    connect(ui->action_datetime,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));
    connect(ui->action_etc,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));
    connect(ui->action_text,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));
    connect(ui->action_about,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));
    connect(ui->action_exit,SIGNAL(triggered()),this,SLOT(on_setCurrentIndex()));

    QList<QPushButton*> btnlist = ui->stackedWidget->findChildren<QPushButton*>();
    foreach(auto btn, btnlist)
    {
        connect(btn,SIGNAL(clicked()),this,SLOT(pushbutton_clicked()));
    }
    ...
}

在初始化控件的时候,我们对控件的信号进行绑定。 UI上面创建了7个菜单,用代码将七个菜单的触发信号绑定到on_setCurrentIndex()槽函数上, 当菜单被点击的时候,就会调用on_setCurrentIndex()。

embed_qt_develop_tutorial_code/Control_1/mainwindows.cpp
 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
void MainWindow::on_setCurrentIndex()
{
    QAction* action= qobject_cast<QAction*>(sender());
    //QString actionName = QObject::sender()->objectName();
    //qDebug()<<actionName;

    if(action->objectName()=="action_datetime")
        ui->stackedWidget->setCurrentIndex(0);
    else if(action->objectName()=="action_etc")
        ui->stackedWidget->setCurrentIndex(1);
    else if(action->objectName()=="action_btn")
        ui->stackedWidget->setCurrentIndex(2);
    else if(action->objectName()=="action_text")
        ui->stackedWidget->setCurrentIndex(3);
    else if(action->objectName()=="action_bar")
        ui->stackedWidget->setCurrentIndex(4);
    else if(action->objectName()=="action_about")
    {
        QString dlgTitle="about Qt";
        QMessageBox::aboutQt(this, dlgTitle);
    }
    else if(action->objectName()=="action_exit")
        exit(0);

    ui->statusBar->showMessage(QString("切换到:%1页").arg(action->text()));
}

在on_setCurrentIndex()中,我们通过qobject_cast获取信号的来源,并通过信号的objectName属性来判断,具体哪一个菜单被点击。 并分别实现不同操作,比如点击退出,执行exit(0),结束程序运行;点击关于Qt,就弹出About Qt弹窗;其他菜单项被点击则会切换到相应的页面展示控件。

4.5.3. 编译构建

build001
  • Ubuntu 选择 Desktop Qt 5.11.3 GCC 64bit 套件,编译运行

  • LubanCat 选择 ebf_lubancat,只编译

提示

当两种构建套件进行切换时,请重新构建项目或清除之前项目。针对我们的工程还需要手动重新构建QtUI和Skin。

build002

4.5.4. 运行结果

4.5.4.1. PC实验

直接点击编译并运行程序,结果如下:

controlui003

4.5.4.2. LubanCat实验

编译程序之后,需要将程序拷贝到LubanCat开发板中,可通过NFS或SCP命令

NFS环境搭建 参考这里

SCP命令如下:

# scp传输文件
# scp 文件名 服务器上的某个用户@服务器ip:/文件保存路径
scp filename server_user_name@192.168.0.205:server_file_path
# 从服务器拉取文件
# scp 服务器上的某个用户@服务器ip:/服务器文件存放路径 拉取文件保存路径
scp server_user_name@192.168.0.229:server_file_path local_path

编译好的程序在 embed_qt_develop_tutorial_code/app_bin 目录中,通过scp命令将编译好的程序拉到LubanCat。

scp root@192.168.0.174:/home/embed_qt_develop_tutorial_code/app_bin/Control_1 /usr/local/qt-app/

在LubanCat运行程序,使用run_myapp.sh配置好环境,并执行 Control_1 。

sudo /usr/local/qt-app/run_myapp.sh /usr/local/qt-app/Control_1
controlui004