QT基础学习

2创建项目

2.1使用向导创建

打开Qt Creator 界面选择 New Project或者选择菜单栏 【文件】-【新建文件或项目】菜单项

弹出New Project对话框,选择Qt Widgets Application,

选择【Choose】按钮,弹出如下对话框

设置项目名称和路径,按照向导进行下一步,(不能有中文和空格

选择编译套件

向导会默认添加一个继承自CMainWindow的类,可以在此修改类的名字和基类。默认的基类有QMainWindow、QWidget以及QDialog三个,我们可以选择QWidget(类似于空窗口),这里我们可以先创建一个不带UI的界面,继续下一步

系统会默认给我们添加main.cpp、mywidget.cpp、 mywidget.h和一个.pro项目文件,点击完成,即可创建出一个Qt桌面程序。

对main原始代码的一些解释

#include "widget.h"
#include <QApplication>//包含一个应用程序类的头文件//main程序入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{//a应用程序对象,在gt中,应用程序对象 有且仅有一个QApplication a(argc, argv);//窗口对象 mywidget父类 ->QwidgetWidget w;//窗口对象 默认不会显示,必须要调用show方法显示窗口w.show();//让应用程序对象进入消息循环//当代码阻塞到这行return a.exec();//    while (true)
//   {
//      if(点击叉子)
//         {
//           break;
//         }
//    }
}
QT       += core gui   //Qt包含的模块greaterThan(QT_MAJOR_VERSION, 4): QT += widgets  //大于4版本以上 包含 widget模块TARGET = QTtest        //目标   生成的exe程序的名称
TEMPLATE = appDEFINES += QT_DEPRECATED_WARNINGSbefore Qt 6.0.0SOURCES += \                //源文件main.cpp \widget.cppHEADERS += \                //头文件widget.h
总结

快捷键   

帮助文档 第一种方式 F1 第二种 左侧按钮 第三种 D:\QT\5.11.1\mingw53_32\bin

// 命名规范
// 类名 首字母大写,单词和单词之间首字母大写
// 函数名 变量名称 首字母小写,单词和单词之间首字母大写
//快捷键//注释 ctrl+/
//运行 etrl + r//编译 ctrl + b
//字体缩放 ctrl + 鼠标滚轮
//查找 ctrl + f
//整行移动 ctrl + shift+,或者↓
//帮助文档 F1
//自动对齐 ctrl + i;
//同名之间的.h 和.cpp切换 F4

3第一个Qt小程序

3.1 按钮的创建

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>class myWidget : public QWidget     //继承的语法
{Q_OBJECTpublic:myWidget(QWidget *parent = 0);  //有参构造函数~myWidget();
};#endif // MYWIDGET_H

 mypushbutton.h

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H#include <QPushButton>class MyPushButton : public QPushButton
{Q_OBJECT
public:explicit MyPushButton(QWidget *parent = 0);~MyPushButton();signals:public slots:
};#endif // MYPUSHBUTTON_H

 main.cpp

#include "mywidget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);myWidget w; //窗口对象  myWidget的父类  -> QWidgetw.show(); //窗口对象 默认不会显示,必须要调用show方法显示窗口return a.exec();//让应用程序对象进入消息循环//当代码阻塞到这行//    while(true)//    {//         if(点击叉子)//        {//            break;//        }//    }}

 mypushbutton.cpp

#include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent)
{//创建一个按钮QPushButton * btn = new QPushButton;//btn->show(); //show以顶层方式弹出窗口控件//让btn对象依赖在mywidget窗口中btn->setParent (this);//显示文本btn->setText ("第一个按钮");//创建第二个按钮 按照控件的大小创建窗口QPushButton * btn2 = new QPushButton("第二个按钮",this)://移动btn2按钮btn2->move (100,100);//重置窗口大小resize (600, 400);//设置固定窗口大小setFixedSize (600, 400);//设置窗口标题setwindowTitle("第一个窗口");Widget::~Widget()
{}

 mywidget.h

#include "mywidget.h"
#include <QPushButton> //按钮控件的头文件
#include "mypushbutton.h"
#include <QDebug>myWidget::myWidget(QWidget *parent): QWidget(parent)//初始化列表
{//创建一个按钮QPushButton * btn = new QPushButton;//btn->show(); //show以顶层方式弹出窗口控件//让btn对象 依赖在 myWidget窗口中btn->setParent(this);//显示文本btn->setText("第一个按钮");//创建第二个按钮 按照控件的大小创建窗口QPushButton * btn2 = new QPushButton("第二个按钮",this);//移动btn2按钮btn2->move(100,100);//按钮可不可以 重新制定大小 可以!btn2->resize(50,50);//重置窗口大小resize(600,400);//设置固定窗口大小setFixedSize(600,400);//设置窗口标题setWindowTitle("第一个窗口");//创建一个自己的按钮对象MyPushButton * myBtn = new MyPushButton;myBtn->setText("我自己的按钮");myBtn->move(200,0);myBtn->setParent(this); //设置到对象树中//需求 点击我的按钮 关闭窗口//参数1 信号的发送者 参数2发送的信号(函数的地址)参数3 信号的接受者 参数4 处理的槽函数connect( myBtn, &MyPushButton::clicked, this, &myWidget::close );connect( myBtn, &QPushButton::clicked, this, &QWidget::close );
}myWidget::~myWidget()
{}

来自ChatGPT的代码解析解答

总结

3.2对象模型(对象树)

在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的。

 

  • QObject是以对象树的形式组织起来的。
  1. 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。
  2. 这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
  3. 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!
  4. 这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。
  • QWidget是能够在屏幕上显示的一切组件的父类。
  1. QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
  2. 当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

Qt 引入对象树的概念,在一定程度上解决了内存问题。

  •  当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对 象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
  • 任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。
  • 如果QObject在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下下面的代码片段:

  • {QWidget window;QPushButton quit("Quit", &window);
    }
    

    作为父组件的 window 和作为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。

    但是,如果我们使用下面的代码:

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

    情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。

    由此我们看到,Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。

3.3 Qt窗口坐标体系 

坐标体系:

以左上角为原点(0,0),X向右增加,Y向下增加。

 对于嵌套窗口,其坐标是相对于父窗口来说的。

4 信号和槽机制

信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

信号:各种事件

槽: 响应信号的动作

当某个事件发生后,如某个按钮被点击了一下,它就会发出一个被点击的信(signal)。

某个对象接收到这个信号之后,就会做一些相关的处理动作(称为槽slot)。

但是Qt对象不会无故收到某个信号,要想让一个对象收到另一个对象发出的信号,这时候需要建立连接(connect)

4.1 系统自带的信号和槽

        下面我们完成一个小功能,上面我们已经学习了按钮的创建,但是还没有体现出按钮的功能,按钮最大的功能也就是点击后触发一些事情,比如我们点击按钮,就把当前的窗口给关闭掉,那么在Qt中,这样的功能如何实现呢?

如下图:

connect( 信号的发送者,发送的具体信号,信号的接受者,信号的处理(槽) )

信号槽的优点,松散耦合,信号发送端和接受端本身是没有关联的,通过connect连接,将两端耦合在一起

           其实两行代码就可以搞定了,我们看下面的代码

QPushButton * quitBtn = new QPushButton("关闭窗口",this);connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);

    第一行是创建一个关闭按钮,这个之前已经学过,第二行就是核心了,也就是信号槽的使用方式

    connect函数是建立信号发送者、信号、信号接收者、槽四者关系的函数:

connect(sender, signal, receiver, slot);

参数解释:

        1)sender:信号发送者

        2)signal:信号

        3)receiver:信号接收者

        4)slot:接收对象在接收到信号之后所需要调用的函数(槽函数)

         这里要注意的是connect的四个参数都是指针,信号和槽是函数指针。

        系统自带的信号和槽如何查找呢,这个就需要利用帮助文档了,在帮助文档中比如我们上面的按钮的点击信号,在帮助文档中输入QPushButton,首先我们可以在Contents中寻找关键字 signals,信号的意思,但是我们发现并没有找到,这时候我们应该想到也许这个信号的被父类继承下来的,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个。

        这里的clicked就是我们要找到,槽函数的寻找方式和信号一样,只不过他的关键字是slot。 

4.2 自定义信号和槽

使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。

4.2.1自定义信号使用条件
  1. 声明在类的signals域下
  2. 没有返回值,void类型的函数
  3. 只有函数声明,没有定义
  4. 可以有参数,可以重载
  5. 通过emit关键字来触发信号,形式:emit object->sig(参数);
 4.2.3 使用自定义信号和槽

        定义场景:下课了,老师跟同学说肚子饿了(信号),学生请老师吃饭(槽)

        首先定义一个学生类和老师类:

        老师类中声明信号 饿了 hungry

signals:void hungry();

      学生类中声明槽 请客treat

public slots:void treat();

    在窗口中声明一个公共方法下课,这个方法的调用会触发老师饿了这个信号,而响应槽函数学生请客

	void MyWidget::ClassIsOver()
{//发送信号emit teacher->hungry();
}

        学生响应了槽函数,并且打印信息

        //自定义槽函数 实现

void Student::treat()
{qDebug() << "Student treat teacher";
}

       在窗口中连接信号槽

 teacher = new Teacher(this);student = new Student(this);connect(teacher,&Teacher::hungury,student,&Student::treat);

        并且调用下课函数,测试打印出相应log 

4.3 信号和槽的扩展

        1.一个信号可以和多个槽相连

        如果是这种情况,这些槽会一个接一个的被调用,但是槽函数调用顺序是不确定的。像上面的例子,可以将一个按钮点击信号连接到关闭窗口的槽函数,同时也连接到学生请吃饭的槽函数,点击按钮的时候可以看到关闭窗口的同时也学生请吃饭的log也打印出来。

        2. 多个信号可以连接到一个槽

        只要任意一个信号发出,这个槽就会被调用。如:一个窗口多个按钮都可以关闭这个窗口。

        3.一个信号可以连接到另外的一个信号

        当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。注意这里还是使用connect函数,只是信号的接收者和槽函数换成另一个信号的发送者和信号函数。如上面老师饿了的例子,可以新建一个按钮btn。

connect(btn,&QPushButton::clicked,teacher,&Teacher::hungry);

        4.信号和槽可以断开连接

        可以使用disconnect函数,当初建立连接时connect参数怎么填的,disconnect里边4个参数也就怎么填。这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。

        5.信号和槽函数参数类型和个数必须同时满足两个条件

                1)信号函数的参数个数必须大于等于槽函数的参数个数

                2)信号函数的参数类型和槽函数的参数类型必须一一对应

 自定义信号槽需要注意的事项

  1. 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
  2. 信号和槽函数返回值是 void
  3. 信号只需要声明,不需要实现
  4. 槽函数需要声明也需要实现
  5. 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
  6. 使用 emit 在恰当的位置发送信号;
  7. 使用connect()函数连接信号和槽。
  8. 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
  9. 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
  10. 如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。

4.4 Qt4版本的信号槽写法 

connect(teacher,SIGNAL(hungry(QString)),student,SLOT(treat(QString))
);

        这里使用了SIGNAL和SLOT这两个宏,宏的参数是信号函数和槽函数的函数原型。

        因为直接填入了函数原型,所有这里边编译不会出现因为重载导致的函数指针二义性的问题。但问题是如果函数原型填错了,或者不符合信号槽传参个数类型约定,编译期间也不会报错,只有运行期间才会看到错误log输出。

        原因就是这两个宏将后边参数(函数原型)转化成了字符串。目前编译器还没有那么智能去判断字符串里边的内容符不符合运行条件。

 4.5 Lambda 表达式

        C++11中的Lambda表达式用于定义匿名的函数对象,以简化编程工作。首先看一下Lambda表达式的基本构成:

        分为四个部分:[局部变量捕获列表]、(函数参数)、函数额外属性设置opt、函数返回值->retype、{函数主体}

[capture](parameters) opt ->retType
{……;
}
4.5.1 局部变量引入方式 

        [ ],标识一个Lambda的开始。由于lambda表达式可以定义在某一个函数体A里边,所以lambda表达式有可能会去访问A函数中的局部变量。中括号里边内容是描述了在lambda表达式里边可以使用的外部局部变量的列表:

        []

            表示lambda表达式不能访问外部函数体的任何局部变量

        [a]

            在函数体内部使用值传递的方式访问a变量

        [&b]

            在函数体内部使用引用传递的方式访问b变量

        [=]

            函数外的所有局部变量都通过值传递的方式使用, 函数体内使用的是副本

        [&]

            引用的方式使用lambda表达式外部的所有变量

        [=, &foo]

            foo使用引用方式, 其余是值传递的方式

        [&,foo]

            foo使用值传递方式, 其余是引用传递的方式

         [this]

           在函数内部可以使用类的成员函数和成员变量,=和&形式也都会默认引入

        由于引用方式捕获对象会有局部变量释放了而lambda函数还没有被调用的情况。如果执行lambda函数那么引用传递方式捕获进来的局部变量的值不可预知。

        所以在无特殊情况下建议使用[=](){}的形式

 4.5.2 函数参数

        (params)表示lambda函数对象接收的参数,类似于函数定义中的小括号表示函数接收的参数类型和个数。参数可以通过按值(如:(int a,int b))和按引用(如:(int &a,int &b))两种方式进行传递。函数参数部分可以省略,省略后相当于无参的函数。

4.5.3 选项 Opt

        Opt 部分是可选项,最常用的是mutable声明,这部分可以省略。外部函数局部变量通过值传递引进来时,其默认是const,所以不能修改这个局部变量的拷贝,加上mutable就可以

int a = 10 ;
[=]()
{a=20;//编译报错,a引进来是const
}[=]()mutable
{a=20;//编译成功
};
4.5.5 是函数主体{}

        {},标识函数的实现,这部分不能省略,但函数体可以为空。

 4.5.6 槽函数使用 Lambda 表达式

以QPushButton点击事件为例:

connect(btn,&QPushButton::clicked,[=](){qDebug()<<"Clicked";
});

        这里可以看出使用Lambda表达式作为槽的时候不需要填入信号的接收者。当点击按钮的时候,clicked信号被触发,lambda表达式也会直接运行。当然lambda表达式还可以指定函数参数,这样也就能够接收到信号函数传递过来的参数了。

        由于lambda表达式比我们自己自定义槽函数要方便而且灵活得多,所以在实现槽函数的时候优先考虑使用Lambda表达式。一般我们的使用习惯也是lambda表达式外部函数的局部变量全部通过值传递捕获进来,也就是:

[=](){  }的形式

 老师学生吃饭例子:

student.h

teacher.h
widget.h

main.cpp
student.cpp

teacher.cpp

widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
//Teacher 类  老师类
//Student 类  学生类
//下课后 ,老师会触发一个信号,饿了 ,学生响应信号,请客吃饭void func()
{qDebug() <<"aaa";}Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//创建一个老师对象this->zt = new Teacher(this);//创建一个学生对象this->st = new Student(this);//    //老师饿了 学生请客的连接
//    connect(zt,&Teacher::hungry,st,&Student::treat);//    //调用下课函数
//    classIsOver();//连接带参数的 信号和槽//指针 -> 地址// 函数指针 -> 函数地址void(Teacher:: *teacherSignal)(QString  ) = &Teacher::hungry;void(Student:: *studentSlot)(QString  )  = &Student::treat;connect(zt,teacherSignal,st,studentSlot);// classIsOver();//点击一个 下课的按钮 ,再触发下课QPushButton * btn = new QPushButton("下课",this);//重置窗口大小this->resize(600,400);//点击按钮 触发下课//connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);//无参信号和槽连接void(Teacher:: *teacherSignal2)(void) = &Teacher::hungry;void(Student:: *studentSlot2)(void)  = &Student::treat;//connect(zt,teacherSignal2,st,studentSlot2);//信号连接信号connect(btn,&QPushButton::clicked, zt, teacherSignal2);//断开信号//disconnect(zt,teacherSignal2,st,studentSlot2);//拓展//1、信号是可以连接信号//2、一个信号可以连接多个槽函数//3、多个信号 可以连接 同一个槽函数//4、信号和槽函数的参数 必须类型一一对应//5、信号和槽的参数个数  是不是要一致?信号的参数个数 可以多余槽函数的参数个数//Qt4版本以前的信号和槽连接方式//利用Qt4信号槽 连接无参版本//Qt4版本 底层SIGNAL("hungry")  SLOT( "treat")connect(zt,SIGNAL(hungry()) , st , SLOT(treat()));//Qt4版本优点:参数直观,缺点 :类型不做检测//Qt5以上  支持 Qt4的版本写法,反之不支持//    QPushButton * btn2 = new QPushButton;//    [btn](){
//        btn->setText("aaaa");
//        btn2->setText("bbb"); //btn2看不到
//    }();// mutable关键字 用于修饰值传递的变量,修改的是拷贝,而不是本体//    QPushButton * myBtn = new QPushButton (this);
//    QPushButton * myBtn2 = new QPushButton (this);
//    myBtn2->move(100,100);
//    int m = 10;//    connect(myBtn,&QPushButton::clicked,this,[m] ()mutable { m = 100 + 10; qDebug() << m; });//    connect(myBtn2,&QPushButton::clicked,this,[=] ()  { qDebug() << m; });//    qDebug() << m;//    int ret = []()->int{return 1000;}();
//    qDebug() << "ret = " << ret ;//利用lambda表达式 实现点击按钮 关闭窗口QPushButton * btn2 = new QPushButton ;btn2->setText("关闭");btn2->move(100,0);btn2->setParent(this);connect(btn2,&QPushButton::clicked, [=](){
//        this->close();
//        emit zt->hungry("宫保鸡丁");btn2->setText("aaaa");});//lambda表达式 最常用  [=](){}
}void Widget::classIsOver()
{//下课函数,调用后 触发老师饿了的信号//emit zt->hungry();emit zt->hungry("宫保鸡丁");
}Widget::~Widget()
{delete ui;
}

 

5QMainWindow

        QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等。

5.1 菜单栏

        一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。

       1.通过QMainWindow类的menubar()函数获取主窗口菜单栏指针,如果当前窗口没有菜单栏,该函数会自动创建一个。

   QMenuBar *  menuBar() const;

        2.创建菜单,调用QMenu的成员函数addMenu来添加菜单

    QAction* addMenu(QMenu * menu);QMenu* addMenu(const QString & title);QMenu* addMenu(const QIcon & icon, const QString & title);

        3.创建菜单项,调用QMenu的成员函数addAction来添加菜单项

    QAction* activeAction() const;QAction* addAction(const QString & text);QAction* addAction(const QIcon & icon, const QString & text);QAction* addAction(const QString & text, const QObject * receiver,const char * member, const QKeySequence & shortcut = 0);QAction* addAction(const QIcon & icon, const QString & text, const QObject * receiver, const char * member, const QKeySequence & shortcut = 0);

         Qt 并没有专门的菜单项类,只是使用一个QAction类,抽象出公共的动作。当我们把QAction对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。用户可以通过点击菜单项、点击工具栏按钮、点击快捷键来激活这个动作。

 5.2 工具栏

        主窗口的工具栏上可以有多个工具条,通常采用一个菜单对应一个工具条的的方式,也可根据需要进行工具条的划分。

        1.调用QMainWindowd对象的成员函数addToolBar(),该函数每次调用都会创建一个新的工具栏,并且返回该工具栏的指针。

        2.插入属于工具条的项,这时工具条上添加项也是用QAction。通过QToolBar类的addAction函数添加。

        1)Qt::LeftToolBarArea           停靠在左侧

        2)Qt::RightToolBarArea         停靠在右侧

        3)Qt::TopToolBarArea           停靠在顶部

        4)Qt::BottomToolBarArea   停靠在底部       

        5)Qt::AllToolBarAreas           以上四个位置都可停靠

使用setAllowedAreas()函数指定停靠区域:

setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea)

使用setFloatable(trueOrFalse)函数来设定工具栏可否浮动

使用setMoveable(trueOrFalse)函数设定工具栏的可移动性:

setMoveable(false)//工具条不可移动, 只能停靠在初始化的位置上

 5.3 状态栏

        一个QMainWindow的程序最多只有一个状态栏。QMainWindow中可以有多个的部件都使用add…名字的函数,而只有一个的部件,就直接使用获取部件的函数,如menuBar。同理状态栏也提供了一个获取状态栏的函数statusBar(),没有就自动创建一个并返回状态栏的指针。
 

 QMenuBar *	menuBar() const;

1.添加小部件(从状态栏左侧添加)

void addWidget(QWidget * widget, int stretch = 0);
//插入小部件
int	insertWidget(int index, QWidget * widget, int stretch = 0);
//删除小部件
void removeWidget(QWidget * widget);

2.添加小部件(从状态栏右侧添加)

void addPermenentWidget (QWidget *widget, int stretch = 0);

5.4 停靠部件(也成为铆接部件、浮动窗口)

        停靠部件 QDockWidget,也称浮动窗口,可以有多个。

QDockWidget * dock = new QDockWidget("标题",this);
//添加停靠部件到mainWindow中,并且设定默认停靠在左边
addDockWidget(Qt::LeftDockWidgetArea,dock);
//设定停靠部件允许停靠的范围
dock->setAllowedAreas(Qt::LeftDockWidgetArea |
Qt::RightDockWidgetArea | Qt::TopDockWidgetArea); 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/152818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

N 字形变换

将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1a; P A H N A P L S I I G Y I R 之后&#xff0c;你的输出需要从左往右逐行读取&#xff0…

网络参考模型与标准协议(一)

OSI参考模型 OSI 模型(Open Systems Interconnection Model)&#xff0c;由国际化标准组织ISO (TheInternational Organization for Standardization )收录在ISO 7489标准中并于1984年发布。 OSI参考模型又被称为七层模型&#xff0c;由下至上依次为: 物理层: 在设备之间传输比…

Linux编辑器-gcc/g++使用

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练使用gcc/g编译器 > 毒鸡汤&#xff1a;真正…

75基于matlab的模拟退火算法优化TSP(SA-TSP),最优路径动态寻优,输出最优路径值、路径曲线、迭代曲线。

基于matlab的模拟退火算法优化TSP(SA-TSP)&#xff0c;最优路径动态寻优&#xff0c;输出最优路径值、路径曲线、迭代曲线。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 75matlab模拟退火算法TSP问题 (xiaohongshu.com)

如何通过cpolar内网穿透工具实现远程访问本地postgreSQL

文章目录 前言1. 安装postgreSQL2. 本地连接postgreSQL3. Windows 安装 cpolar4. 配置postgreSQL公网地址5. 公网postgreSQL访问6. 固定连接公网地址7. postgreSQL固定地址连接测试 前言 PostgreSQL是一个功能非常强大的关系型数据库管理系统&#xff08;RDBMS&#xff09;,下…

uniapp开发小程序,包过大解决方案

1、首先和大家说一下 微信小程序 主包限制不能超过2M 分包一共不能超过8M 然后具体解决优化步骤如下&#xff0c; 将主包进行分包 在pages.json 下subPackages里面进行配置分包 分包配置完 配置过的文件都需要进行修改对应的路径 2 、 在运行的时候 一定要勾选 压缩代码 有…

Android Termux安装MySQL,内网穿透实现公网远程访问

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【电路笔记】-欧姆定律

欧姆定律 文章目录 欧姆定律1、概述2、AC电路的等效性2.1 输入电阻2.2 输入电感2.3 输入电容 3、欧姆定律的局部形式3.1 介绍和定义3.2 德鲁德模型(Drude Model)3.3 局部形式表达式 4、电阻和宏观欧姆定律5、总结 电流、电压和电阻之间的基本关系被称为欧姆定律&#xff0c;可能…

cpu飙高问题,案例分析(一)

一、复习知识点&#xff1a; CPU性能指标&#xff1a; load average&#xff1a;负载&#xff0c;linux查看的时候&#xff0c;通常显示如下&#xff1a; load average后面有三段数字&#xff1a;代表了系统1分钟&#xff0c;5分钟&#xff0c;15分钟平均负载。 形象的类别可…

使用npm发布自己的组件库

在日常开发中&#xff0c;我们习惯性的会封装一些个性化的组件以适配各种业务场景&#xff0c;突发奇想能不能建一个自己的组件库&#xff0c;今后在各种业务里可以自由下载安装自己的组件。 一. 项目搭建 首先直接使用vue-cli创建一个vue2版本的项目&#xff0c;并下载好ele…

Ps:陷印

在准备图像进行专业印刷之前&#xff0c;陷印 Trap是一个重要的步骤。 在彩色印刷中&#xff0c;多种颜色的墨水通常分别印刷。陷印是一种叠印技术&#xff0c;它可避免打印时印版的微小偏差或移动而使打印图像出现微小的缝隙。 进行陷印处理以纠正未对齐现象 A. 未对齐现象&am…

代码逻辑修复与其他爬虫ip库的应用

在一个项目中&#xff0c;由于需要设置 http_proxy 来爬虫IP访问网络&#xff0c;但在使用 requests 库下载文件时遇到了问题。具体表现为在执行 Python 脚本时&#xff0c;程序会阻塞并最终超时&#xff0c;无法正常完成文件下载。 解决方案 针对这个问题&#xff0c;我们可以…

VB.net读写S50/F08IC卡,修改卡片密码控制位源码

本示例使用设备&#xff1a;Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/智能海报/-淘宝网 (taobao.com) 函数声明 Module Module1读卡函数声明Public Declare Function piccreadex Lib "OUR_MIFARE.dll" (ByVal ctrlword As Byte, ByRef serial As Byte, …

基于单片机K型热电偶温度采集报警系统

**单片机设计介绍&#xff0c; 基于单片机K型热电偶温度采集报警系统 文章目录 一 概要简介系统特点系统组成工作原理应用领域 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 # 基于单片机K型热电偶温度采集报警系统介绍 简介 该系统是基于单片…

【论文阅读笔记】Deep learning for time series classification: a review

【论文阅读笔记】Deep learning for time series classification: a review 摘要 在这篇文章中&#xff0c;作者通过对TSC的最新DNN架构进行实证研究&#xff0c;探讨了深度学习算法在TSC中的当前最新性能。文章提供了对DNNs在TSC的统一分类体系下在各种时间序列领域中的最成功…

8 Redis与Lua

LUA脚本语言是C开发的&#xff0c;类似存储过程,是为了实现完整的原子性操作&#xff0c;可以用来补充redis弱事务的缺点. 1、LUA脚本的好处 2、Lua脚本限流实战 支持分布式 import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis…

Excel 文件比较工具 xlCompare 11.01 Crack

比较两个 Excel 文件之间的差异 xlCompare. xlCompare.com 是性能最佳的 Excel diff 工具&#xff0c;用于比较两个 Excel 文件或工作表并在线突出显示差异。xlCompare 包括免费的在线 Excel 和 CSV 文件比较服务以及用于比较和合并 Excel 文件的强大桌面工具。如果您想在线了…

软件测试: 测试用例

一. 软件测试四要素 测试环境,操作步骤,测试数据,预期结果 二. 基于需求进行测试用例的设计 基于需求设计测试用例是测试设计和开发测试用例的基础,第一步就要分析测试需求,验证需求是否正确,完整,无二义性,并且逻辑自洽.在需求正确的基础上细化测试需求,从测试需求提炼出一…

React整理总结(五、Redux)

1.Redux核心概念 纯函数 确定的输入&#xff0c;一定会产生确定的输出&#xff1b;函数在执行过程中&#xff0c;不能产生副作用 store 存储数据 action 更改数据 reducer 连接store和action的纯函数 将传入的state和action结合&#xff0c;生成一个新的state dispatc…

猫12分类:使用yolov5训练检测模型

前言&#xff1a; 在使用yolov5之前&#xff0c;尝试过到百度飞桨平台&#xff08;小白不建议&#xff09;、AutoDL平台&#xff08;这个比较友好&#xff0c;经济实惠&#xff09;训练模型。但还是没有本地训练模型来的舒服。因此远程了一台学校电脑来搭建自己的检测模型。配置…