qt基础笔记

  1. .pro文件:

    1、本质Makefile文件
    2、CONFIG配置选项:设置项目的配置信息和编译选项
    3、-debug 构建debug版本可执行程序
    4、-release 构建release版本可执行程序
    5、debug and release 构建debug和release版本可执行程序
    6、warn on 尽可能多的打印警告信息
    7、warn off 不输出警告信息
    
  2. 软件开发流程

    1. 需求分析->功能分解->功能实现->功能测试(重构)->系统测试->发布
    2. 尽量将界面代码与功能代码分离开
    3. 尽量复用平台提供的组件
  3. sender()函数,可以获取信号的发送者的指针

  4. QT vs STL,有stl为什么qt要再实现一遍

    1. STL的标准只是接口标准,实现根据不同厂商而定
    2. 相同的全局函数
    3. 相同的算法类和数据结构类
    4. 相同的类成员函数
    5. qt字符串类优点
      1. 采用Unicode编码
      2. 使用隐式共享技术来节省内存和不必要的内存拷贝
      3. 跨平台使用时,不必考虑字符串的平台兼容性
  5. 对话框

    1. QDialog
      1. QDialog是qt中所有对话框的基类
      2. QDialog继承于qwidget是一种容器类型的组件
      3. QDialog不能作为子部件嵌入到其他容器中
      4. QDialog是定制了窗口样式的qwidget
      5. QDialog必须为顶层组件
        1. 通过QDialog::setModel函数可以设置混合特性的对话框,非模态对话框做模态对话框使用
          1. dialog->setAttribute(Qt::WA_DeleteOnClose);
          2. dialog->setModel(this);
    2. 模态对话框
      1. 阻塞式,无法与父窗口交互,QDialog::exec()
      2. 一般在栈上创建
      3. 返回值为交互结果
        1. void QDialog::done(int i)将i作为交互结果
        2. QDialog::Accepted成功
        3. QDialog::Rejected失败
      4. 当作为主窗口是不要再次调用a.exec()了
    3. 非模态对话框
      1. 非阻塞式,QDialog::show()
      2. 一般在堆上创建
      3. 需要指定dialog->setAttribute(Qt::WA_DeleteOnClose)属性
        1. 原因:在函数内的堆上创建后,关闭对话框不会释放资源
      4. 指定父类才可以保证显示在顶层
    4. 登录对话框(复用)
    5. 标准对话框
      1. QMessageBox
      2. QFileDialog
      3. QPrintDialog
      4. QColorDialog
      5. QFontDialog
      6. QInputDialog
      7. QProgressDialog
  6. 布局管理器

    1. QLayout是界面组件的定位策略
      1. QBoxLayout
      2. QgridLayout
      3. QFormLayout表单布局
      4. QStackLayout
        1. 组件大小一致,充满父组件的显示区
        2. 不能嵌套其他布局管理器(可以嵌套个qwidget里面再次布局)
        3. 能够自由切换需要显示的组件
    2. 设置比例系数:void setStretch(int index, int stretch)
  7. 文本编辑器

    1. construct
      1. initMenuBar
        1. initFileMenu
        2. initEditMenu
        3. initFormatMenu
        4. initViewMenu
        5. initHelpMeny
      2. initToolBar
        1. initFIleToolItem
        2. initEditToolItem
        3. initFormatToolItem
        4. initViewToolItem
      3. initStatusBar
      4. initMainEditor
      5. 使用QMap对保存时的后缀进行判断
      6. QplainText有对应的内部信号和槽函数设置拷贝剪切撤销等操作
  8. 软件开发流程

    1. 即兴模型
    2. 瀑布模型
    3. 增量模型
    4. 螺旋模型
    5. 敏捷模型
  9. 文件操作

    1. QFile

      1. 支持文本文件和数据文件的读写
      2. QTextStream
      3. QDatastream
        1. 当数据流文件在不同版本的QT程序之间传递数据时,需要考虑版本问题
        2. void setVersion(QDataStream::Qt_4_7)
        3. int version()const
    2. QFileInfo

    3. QTemporaryFile

      1. 安全的创建一个全局唯一的临时文件

      2. 当对象销毁时对应的临时文件将被删除

      3. 临时文件的打开方式:QIODevice::ReadWrite

      4. 临时文件常用于大数据传递或者进程间通信

        QTemporaryFile tempFile;
        if(tempFile.open())
        {
        	tempFile.write("zhang");
        	tempFile.close();
        }
        
    4. 缓冲区

      1. 在线程间进行不同类型的传递
      2. 缓存外部设备中的数据返回
      3. 数据读取速度小于数据写入速度
      QByteArray array;
      QBuffer buffer(&array);
      
      if(buffer.open(QIODevice::WriteOnly))
      {
      	QDataStream out(&buffer);
      	out << "zhang";
      	buffer.close();
      }
      
    5. QDir

      const char* PATH = "./dir";
      
      QDir dir;
      if(!dir.exists(PATH))
      {
      	dir.mkdir(PATH);
      }
      if(dir.exists(PATH))
      {
      	dir.cd(PATH);
      	QStringList list = dir.entryList();
      	for(int i=0; i< list.count(); i++)
      	{
      		
      	}
      }
      
      //计算文件大小
      unsigned int calculate_size(QString path)
      {
      	QFileInfo info(path);
      	unsigned int ret = 0;
      	if(info.isFile())
      	{
      		ret = info.size();
      	}
      	else if(info.isDir())
      	{
      		QDir dir(path);
      		QFileInfoList list = dir.enteryInfoList();
      		for(int i = 0 i< list.count(); i++)
      		{
      			if( (list[i].fileName() != ".")
      			&& (list[i].fileName() != "..")
      			{
      				ret += calculate_size(list[i].absolateFilePath);
      			}
      		}
      	}
      	return ret;
      }
      
    6. QFileSystemWather

      1. 能够监控特定目录和文件的状态
      2. 能够同时对多个目录和文件进行监控
      3. 当目录或者文件发生改变时触发信号
      4. 通过信号槽机制捕获信号
  10. QMap & QHash

  11. QMap

    1. QMap以升序顺序存储键值对
    2. 原型为class QMap<K, T>模板
    3. 根据key值进行了排序
    4. key类型必须重载了operator<
  12. QHash

    1. QHash原型为class QHash<K, T>模板
    2. QHash中的键值对在内部无序排列
    3. QHash中的key类型必须重载operator==
    4. QHash中的key对象必须重载全局哈希函数qHash(),得到不同的id
  13. 比较

    1. 接口相同,可直接替换使用
    2. QHash查找速度明显低于QMap
    3. QHash占用的存储空间明显多于QMap
    4. QHash以任意方式存储数据
    5. QMap以key顺序存储元素
    6. QHash的key必须提供operator==()和qHash(key)函数
    7. QMap的key类型必须提供operator<()函数
  14. Qt中的事件处理

    1. 处理顺序:事件过滤器->焦点部件的event()->焦点部件的具体事件处理函数->焦点部件忽略该事件后会传递到父组件的事件处理函数

    2. QEvent

      1. QInputEvent
      2. QDropEvent
      3. QPaintEvent
      4. QCloseEvent
      5. QTimerEvent
    3. QEvent* e

      1. e->accept();//表示事件已经被处理
      2. e->ignore();//表示忽略该事件,事件可能传递给父组件
      3. e->isAccepted();//判断当前是哪是否被处理
    4. 事件被组件对象处理后的消息有可能传递到其他父组件

    5. eventFilter

    6. 拖拽事件

      1. 对应部件类中重写函数

        void dragEnterEvent(QDragEnterEvent* e)
        {
        	if(e->minmeData->hasUrls())
        		e->acceptProposeAction();
        	else
        		e->ignore();
        }
        void dropEvent(QDropEvent* e)
        {
        	if(e->minmeData->hasUrls())
        	{
        		QList<QUrl> list = e->mimeData()->urls();
        		qDebug() << list[0].toLocalFile();
        	}
        	else
        		e->ignore();
        }
        
  15. 文本打印与光标定位

    1. MVC架构:界面与界面内的数据分离技术

    2. QPlainTextEdit本身只负责界面形态显示,内部通过QTextDocument对象存储文本数据

    3. 光标位置计算QTextCursor

      QTextCusor c = mainEditor.textCursor();//获取当前光标
      c.setPosition(1);//定位到下标为1的位置
      c.setPosition(4, QTextCursor::KeepAnchor);//文本选择范围[1,4]
      mainEditor.setTextCursor(c);//设置光标信息到文本框
      
    4. 光标定位行列号算法没看懂!!!

  16. 自定义信号事件

    1. QApplication类

      1. 阻塞型发送函数:

        1. bool sendEvent(QObject* receiver, QEvent* event);
        2. 函数内部调用的是QObject中的event()事件
        3. 同时支持栈事件对象和堆事件对象的发送
      2. 非阻塞型发送函数:

        1. void postEvent(QObject* receiver, QEvent* event);
        2. 发送成功后,将消息放入到消息队列中,并立即返回,将消息分发下去
        3. 只能发送堆事件,结束后有QT平台销毁
      3. 模拟键盘delete按下事件

        void onEditDelete()
        {
        	QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
        	QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Delete, Qt::NoModifier);
        	
        	//发送阻塞事件
        	QApplication::sendEvent(&mainEditor, &keyPress);
        	QApplication::sendEvent(&mainEditot, &keyRelease);
        }
        
    2. 自定义事件类

      1. 必须继承自QEvent
      2. 必须拥有全局唯一的Type(自定义)值
        1. QEvent::User + value
      3. 程序中必须提供处理自定义事件对象的方法
        1. 将事件过滤器安装到目标对象,在eventFilter()函数中编写处理逻辑
        2. 重写event()函数,编写处理逻辑
      4. 使用情况
        1. 需要扩展一个已有组件类的功能
        2. 需要开发一个全新功能的组件类
        3. 需要向一个第三方的组件类发送消息
  17. 查找对话框设计,功能复用

  18. 替换对话框

  19. Qt调色板

    1. QPalette

      1. 激活颜色组(Active) 组件获得焦点使用的颜色方案
      2. 非激活颜色组(Inactive) 组件失去焦点使用的颜色方案
      3. 失效颜色组(Disabled) 组件处于不可用状态的颜色方案
      4. 使用
      QPalette p =widget.palette();
      
      p.setColor(QPalette::Active,QPalette::WindowText, Qt::blue);
      p.setColor(QPalette::Inactive, QPalette::WindowText, Qt::blue);
      widget.setPalette(p);
      
  20. QDesktopServices::openUrl(QUrl(“path”));

  21. 命令行参数的应用

    1. 操作系统关联方式:文件双击运行,将文件路径作为命令行参数启动应用程序

      mainWindow* w = MainWindow::NewInstance();
      if(w != NULL)
      {
      	if(argc > 1)
      	{
      		QFIleInfo info(argv[1]);
      		if(info.exists())
      		{
      			//打开文件
      		}
      	}
      }
      
  22. 模型视图设计模式

    1. 思想:

      1. 将数据与现实分离
      2. 模型对外提供标准接口存取数据
      3. 视图自定义数据显示格式
      4. 模型中的数据都是以层次结构表示的
      5. 索引在需要是由模型创建
      6. 使用空索(虚拟父节点)引作为父节点表示顶层数据元素
    2. 必须为每一个数据提供独一无二的索引,视图通过索引访问模型中的具体数据

      QFileSystemModel fsModel;					//文件系统模型
      QTreeView treeView;							//属性显示视图
      QString path = QDir::currentPath();			//要显示的目录
      
      fsModel.seetRootPath(path);					//从当前目录获取数据
      treeView.setModel(&fsModel);				//连接模型视图
      
      treeView.setRootIndex(fsModel.index(path));	//设置属性视图的数据索引
      
    3. 类型

      1. 线性模型使用行列作为数据索引
        1. QModelIndex index = model->index(row, col);
      2. 非线性模型(树)
        1. 虚拟一个root节点,通过(index,parent)方式确定
      3. 三元组
        1. (row, col, parent)
    4. 标准模型定义

      QStandardItemModel model;
      
      QStandardItem* root = model.invisibleRootItem();//获取虚拟节点
      QStandardItem* item1 = new QStandardItem();
      QStandardItem* item2 = new QStandardItem();
      
      item1->setData("aa", Qt::DisplayRole);
      item1->setData("bb", Qt::ToolTipRole);
      
      //角色定义
      Qt::DisplayRole 	//作为直接可见的提示信息
      Qt::DecorationRole 	//以图表方式显示
      Qt::EditRole		//可编辑的数据信息
      Qt::ToolTipRole		//悬浮框中的补充型提示信息
      Qt::StatusTipRole	//在状态中显示的提示性信息
      Qt::WhatsThisRole	//悬浮框中的详细帮助信息
      Qt::SizeHintRole	//数据大小信息
        
      item2->setData("cc");//问题:必须设置角色属性否则无法显示,因为数据级别相同,无法区分
      item2->setData("dd");
      
      root->setChild(0, 0, item1);
      root->setChild(0, 1, item1);
      
      //不同视图显示的数据模型样式可能不同
      tableView.setModel(&m_model);
      listView.setModel(&m_model);
      treeView.setModel(&m_model);
      
    5. 数据角色

      1. 模型中的数据在视图中的用途(显示方式)可能不同
      2. 模型必须为数据设置特定的属性
      3. 数据角色用于提示视图数据的作用
      4. 数据角色是不同视图以统一风格显示数据的标准
    6. 自定义模型类

      1. QStandardItemModel
        1. 能够以任意方式组织数据(线性,非线性)
        2. 数据组织的基本单位(QStandardItem)
        3. 每个数据项能够存储多个数据(数据角色)
        4. 每个数据项能够对数据状态进行控制
      2. 变体类型QVariant
        1. 用于封装的类型
        2. 能够表示大多数常见的值类型
        3. 每次只能保存单一类型的值
        4. 意义:能够设计 返回类型可变的函数
      3. 系统架构
        1. 数据显示层->数据组织层->数据表示层->数据层
    7. 视图 - 委托

      1. QStyleItemDeletgate
        1. 重写
          1. createEditor
          2. updateEditorGeometry
          3. setEditorData
          4. setModelData
          5. paint(可选)
      2. 是视图中处理用户输入的部件
      3. 视图可以设置委托对象用于处理用户输入
      4. 委托能够提供编辑是需要的上下文环境
      5. 不同委托提供的编辑器类型不同(文本框,单选框)
      6. 编辑器从模型获取数据,并将编辑结果返回模型
      7. 委托也会负责部分数据的显示,如框体线
      8. paint负责数据绘制
      9. 自定义组件绘制
        1. 重写委托paint,处理数据显示方式
        2. 重写editorEvent,处理交互事件
  23. 信号槽

    1. 信号只是一个特殊的成员函数声明
      1. 函数只能声明不能定义
      2. 函数返回值必须是void
    2. 信号必须使用signals关键字声明
      1. 函数的访问属性自动设置为protected
      2. 只能通过emit关键字触发信号
    3. 要求
      1. qt只能在头文件中声明
      2. 信号与槽的类型应完全相同
      3. 信号的参数个数可以多余槽的参数个数,多余的会被忽略
      4. 信号和槽的返回值必须是void
      5. 槽函数可以像普通函数一样调用
      6. 信号槽的访问属性对应connect和disconnect无效
    4. 意义
      1. 最大限度的弱化了类之间的耦合
      2. 在设计阶段可以减少不必要的接口类(抽象类)
      3. 在开发阶段,对象之间的交互使用信号槽动态绑定
  24. 图形绘制

    1. QPainter

      1. painter.setViewport();//设置视口,物理窗口的大小,即要显示窗口占总窗口的大小
      2. painter.setWindow();//设置窗口,逻辑坐标系大小,可以设置在指定视口范围内的坐标表示范围,即自定义坐标系
    2. 画图软件

    3. 图像

      1. QImage

        1. 独立于具体硬件的图像类
        2. 针对IO访问设计
        3. 能够像素级访问
      2. QPixmap

        1. 依赖具体硬件的图像类
        2. 针对屏幕设计,不可移植
      3. 灰度化

        image = img.scaled(QSize(200, 200), Qt::KeepAspectRatio);
        for(int i=0; i<image.width(); i++)
        {
            for(int j = 0; j< image.height(); j++)
            {
                QRgb rgb = image.pixel(i, j);
                int r = QRed(rgb);
                int g = QGreen(rgb);
                int b = Qblue(rgb);
                int gray = (r + g + b) / 3;
                
                image.setPixel(i, j, QRgb(gray, gray, gray));
            }
        }
        
      4. 屏幕截图

        WId id = QApplication::desktop()->winId();
        QPixmap pixmap = QPixmap::grabWindow(win);
        QImage image = pixmap.toImage();
        image.save("image.png");
        
        //grabWindow()用于对屏幕像素进行抓取
        //grabWidget()用于对当前程序中的组件外观图像进行抓取
        
      5. 绘制文本

        1. QFontMettics获取字符串在指定字体下的宽高
        2. 通过改变字体大小产生字体由远到近的效果(动画效果)
        3. 在QPainter中可以自定义文字颜色、位置、字体、旋转
        4. QPainter可以将文字绘制与图片(水印效果)
  25. 进程&线程

    1. 程序&进程

      1. 源代码程序:文本文件,描述程序行为和功能
      2. 可执行程序:二进制文件,可以直接加载运行
    2. 进程

      1. 广义:程序关于某一个数据集合的一次运行活动
      2. 狭义:程序被加载早内存中执行后得到进程
    3. 程序和进程的区别

      1. 程序是硬盘中静态的文件,二进制文件
      2. 进程是内存中动态运行的实体,数据段,代码段,pc指针,等
      3. 一个程序可能对应多个进程,一个程序多次运行每个都是一个进程
      4. 一个进程可能包含多个程序,如:加载的其他动态库
    4. 当代操作系统中资源分配的单位的进程,CPU调度的基本单位是线程

    5. QT多线程

      1. 不要使用terminate终止,会导致资源无法释放
      2. 方法:添加公有函数stop(),添加成员变量volatile bool m_toStop;使得run函数可以正常返回,且必须使用volatile关键字,每次从内存中取数据,不允许编译器做优化!!!
      3. 使用模式
        1. 无事件循环模式
          1. 耗时操作:文件复制,网络数据读取
        2. 开启事件循环模式
          1. 执行事务性操作:文件写入,数据库写入等
    6. 多线程同步

      1. QThread t; t.wait();
    7. 多线程互斥

      1. 生产者&消费者

        1. QMutex

          1. lock();会判断当前锁是否空闲,必须调用unlock()解锁
          2. 锁在调用unlock()时是空闲状态,程序行为是未定义的
          3. 死锁
            1. 多个锁时,处理顺序不同,互相等待对方释放锁,可能会产生互锁
            2. 多个临界资源且临界资源不可抢占
            3. 线程需要多个临界资源才能执行
          4. 解决
            1. 对临界资源分配唯一ID,且对线程锁分配同样的ID,并且每个线程严格按照递增顺序请求资源
        2. 信号量QSemaphore

          1. 信号量是特殊的线程锁

          2. 信号量允许多个线程同时访问临界资源

          3. QSemaphore内部维护一个整型值,每次使用acquire()减一,使用release()加一

            QSemaphore sem(1);
            sem.acquire();
            //do someting
            sem.release();
            
            等价于
            
            QMutex mutex;
            mutex.lock();
            //do something
            mutex.unlock();
            
    8. 银行家算法

      1. 将资金优先借给资金需求少的客户
      2. 应用场景
        1. 操作系统内核中的进程管理
        2. 数据库内核中的频繁事物管理
    9. 多线程信号槽

      1. 操作系统通过整型标识管理进程和线程
        1. 进程拥有全局唯一的ID值(PID)
        2. 线程拥有进程内的唯一ID值(TID)
      2. QThread
        1. QThread::currentThread();
        2. Qt::HANDLE currentThreadId();
      3. 线程拥有独立的栈空间用于函数调用
      4. 没有临界资源的函数可以无副作用的被多个线程调用
      5. QObject::moveToThread用于改变对象的线程依附性
      6. 线程中的事件循环
        1. 信号槽的机制需要事件循环的支持
        2. QThread类中提供了exec()函数(在run函数内部调用exec();)开始线程到的事件循环
        3. 调用了exec()开启了事件循环,run函数就不会返回,线程就没办法结束
        4. 解决:在线程启动后等待一定时间,thread.wait(1000)后,调用thread.quit()或者thread.exit(0)结束线程,(quit() == exit(0))
        5. 只有开启了事件循环,槽函数(线程内的)才能在信号发送后被调用(在依附的线程中被调用)
        6. 意义:
          1. 当信号和槽函数在不同线程时,可能产生临界资源的竞争问题
      7. 信号槽连接方式
        1. 立即调用:Qt::DirectConnection
        2. 异步调用:Qt::QueuedConnection
        3. 同步调用:Qt::BlockingQueuedConnection
        4. 默认连接:Qt::AutoConnection
        5. 单一连接:Qt::UniqueConnection
    10. 线程生命周期

    11. 准则

      1. 线程对象的生命周期 > 对应线程的生命周期
    12. 同步性线程设计

      1. 概念:
        1. 线程对象主动等待线程生命周期结束后才销毁
      2. 特点:
        1. 同时支持在栈和堆上创建线程对象
        2. 对象销毁时确保线程生命周期结束
      3. 使用方法:
        1. 在线程类的析构函数中调用wait()函数,等待线程结束再销毁线程
    13. 异步型线程设计

      1. 概念:
        1. 线程生命周期结束时通知销毁线程对象
      2. 特点:
        1. 只能在堆上创建线程对象
        2. 线程对象不能被外界主动销毁
      3. 使用场景:
        1. 线程生命周期不可控,需要长时间运行于后台
      4. 使用方法:
        1. 在run()函数中最后调用deleteLater()函数,会在线程结束后申请销毁调用run的对象
        2. 使用二阶构造,以保证在堆上创建对象,且不会主动调用析构函数销毁对象,以向qt平台发送的deleteLater()来申请销毁对象
    14. 线程创建方式

      1. 在类中定义一个槽函数void tmain();作为线程入口函数
      2. 在类中定义一个QThread成员对象m_thread;
      3. 改变当前对象的线程依附到m_thread
      4. 连接m_thread的start()到tmain();
    15. 多线程与界面组件通信

      1. 方式一:
        1. GUI只能在主线程操作,界面组件必须依赖于主线程
        2. 使用信号槽通信,连接必须采用异步连接方式
      2. 方式二:
        1. 自定义事件类用于描述界面更新细节
        2. 在主窗口类中冲写事件处理函数event()
        3. 使用postEvent函数(异步方式)发送自定义事件
    16. Qt问题:

      1. GUI系统的核心模型和机制是什么?
      2. 界面组件间的父子关系有什么意义?
      3. 信号槽的使用方式?
      4. 多线程和界面组件的关系是什么?
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值