通常,各个图形界面框架都会使用操作系统本地代码来生成一个窗口。所以生成的窗口风格都与操作系统有关。而像qq那些,都是自己绘制,即DirectUI,即无句柄绘制。
默认情况下我们的程序主窗口都继承自QMainWindow,以便获得QMainWindow提供的各种便利的函数。Qt使用QAction类作为动作。QAction类可能显示在菜单,作为一个菜单项,对用户的点击做出反应;也可以出现在工具栏,作为一个工具栏按钮,用户点击这个按钮就可以执行相应的操作。但是,无论出现在菜单栏还是出现在工具栏,用户选择后,所执行的动作都是一样的----都是连接一个槽函数。所以,QT没有专门的菜单项类,只是是用一个QAction类,抽象出公共的动作。QAction类包含了图片,菜单文字,快捷键,状态文字,浮动文字等信息。
Qt::对象模型
GUI界面需要同时具有运行时的效率以及更高级别的灵活性。为了解决这一问题,Qt先使用了一个叫做moc(Meta Object Compiler,元对象编译器)的工具,先对Qt源代码进行一次预处理(Qt的moc预处理发生在标准c++预处理工作之前,并且Qt的moc预处理不是递归的)
生成标准c++源代码,然后再使用标准c++编译器进行编译。(信号函数就是由moc加上的函数体)
QObject是以对象树的形式组织起来的。当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数是parent,也就是父对象指针。在Qt中每个QObject内部都有一个list,用来保存所有的children,还有一个指针,保存自己的parent。当它自己析构时,它会将自己从parent列表中删除,并且析构掉所有的children。
QWiget是能够在屏幕上显示的一切组件的父类。QWiget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此它会显示在父组件的坐标系统中被父组件的边界裁剪。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么我们希望属于这个对话框的按钮,图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
当一个QObject对象在堆上创建的时候,Qt会同时为其创建一个对象树,不过,对象树中对象的顺序是没有定义的。这意味着销毁这些对象的顺序也是未定义的。Qt保证的是,任何对象树中的QObject对象delete的时候,如果这个对象有parent,则自动将其从parent的children列表中删除;如果有孩子,则自动delete每一个孩子。Qt保证没有QObject会被delete两次,这是由析构函数决定的。
eg:connect(spinBox, &QSpinBox::valueChanged, slider, &QSlider::setValue);的时候,会报错。
因为QSpinBox有两个信号:1,void valueChanged(int) 2, void valueChanged(const QString&)当我们使用&QString::valueChanged取函数指针时,编译器不知道取哪一个函数(经过moc预处理后,signal也是一个普通的函数)的地址,因此报错。故我们应该显示地指定一个函数,即创建一个函数指针。这个函数指针参数指定为int
void (QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged;