#《Qt学习之路》学习之路(3)#对象模型->布局管理器->简单界面实现

2018.5.1

理工科的学习一般是摸着石头过河,有很多新东西可能还没有完全搞明白,但是却必须要先用起来了。实验室这个项目DDL太近,作为QT从没用过的小白,要想纯粹从头学起肯定没法按时完成任务。所以基本上是一边按需学习模仿,一边恶补基础知识。

目前实现的界面效果如下(数据内容涉密就不放出来了):


这个简单的界面实现,用到了三种布局QHBoxLayout、QHBoxLayout、QGridLayout,用到了QLabel、QButton、QTextEdit等多个控件,用到了绘图工具等,用的地图是我们学校的地图,欢迎各位来我们南大玩耍,相互交流学习。项目整体大概推了1/5吧,解决了几个小问题,希望越往后学解决问题可以越轻松一点。

当然,工程还是要推,基础知识还是得捡起来学。



网上大概翻了一些教程,对比一下发现Qt学习之路2的学习推进方式更适合我一些,为了防止自己遗忘,在这里分享一些学习的要点,我记的知识要点可能偏个人一些,大概率思维会比较跳跃,建议参考博主原文和查看官方API理解。


对象模型:

QObject是以对象树的形式组织起来的。当创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。当父对象析构的时候,这个列表中的所有对象也会被析构。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。又例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,属于这个对话框的按钮、图标等也一起被删除。

当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。Qt 保证的是,任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。如果QObject在栈上创建,Qt 保持同样的行为。

以下代码会产生二次析构:

根据栈后进先出原则,作为父对象的 window 会首先被析构,在析构过程中,它析构子对象。代码继续执行, quit 也是一个局部变量,在超出作用域的时候也需要析构,这时就造成了二次析构。

{
    QPushButton quit("Quit");
    QWidget window;
 
    quit.setParent(&window);
}

我们最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。


布局管理器:

QT最常用 的布局管理器有以下几种:

QHBoxLayout:按照水平方向从左到右布局;
QVBoxLayout:按照竖直方向从上到下布局;
QGridLayout:在一个网格中进行布局,类似于 HTML 的 table;
QFormLayout:按照表格布局,每一行前面是一段文本,文本后面跟随一个组件(通常是输入框),类似 HTML 的 form;

QStackedLayout:层叠的布局,允许我们将几个组件按照 Z 轴方向堆叠,可以形成向导那种一页一页的效果。

使用QHBoxLayout进行的简单布局展示(使用QSpinBox和QSlider两个控件):

#include "mainwindow.h"
#include <QApplication>
#include <QSpinBox>
#include <QSlider>
#include <QHBoxLayout>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //MainWindow w;
    //w.show();

    QWidget window;
    window.setWindowTitle("Enter your age");

    //QSpinBox就是只能输入数字的输入框,并且带有上下箭头的步进按钮。QSlider则是带有滑块的滑竿。
    QSpinBox *spinBox = new QSpinBox(&window);
    QSlider *slider = new QSlider(Qt::Horizontal, &window);
    spinBox->setRange(0, 130);
    slider->setRange(0,130);

    //将QSlider与QSpinBox值相连接
    QObject::connect(slider, &QSlider::valueChanged, spinBox, &QSpinBox::setValue);
    //将QSpinBox与QSlider值相连接,双向绑定,直接连接会报错,因为编译器认为QSpinBox::valueChanged是一个 overloaded 的函数。
    //void valueChanged(int)与void valueChanged(const QString &),需要利用函数指针先显示指定一个函数
    void(QSpinBox::*spinBoxSignal)(int) = &QSpinBox::valueChanged;
    QObject::connect(spinBox, spinBoxSignal, slider, &QSlider::setValue);
    spinBox->setValue(23);

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(spinBox);
    layout->addWidget(slider);
    window.setLayout(layout);

    window.show();

    return a.exec();
}
基本效果如下。

左边的QSpinBox和右边的QSlider相互绑定,输入数值会影响滑块位置,反之滑块移动也会改变数值。

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/80166238