Qt基础知识及代码

文件介绍快捷键

// 宏,允许类中使用信号和槽机制
Q_OBJECT

快捷键

// 运行
Ctrl + r
// 编译
Ctrl + b
// 查找
Ctrl + f
// 整行移动
Ctrl + Shift + ↑ 或 ↓
// 帮助文档
F1
// 自动对齐
Ctrl + r
// 同名之间的.h文件和.cpp文件之间切换
F4

设置窗口属性

  • 修改窗口的标题

    • this->setWindowTitle("MyProject");
      
  • 设置窗口的大小,设置完成可以拉伸

    • this->resize(600, 400);
      
  • 设置固定大小,设置完成不可拉伸

    • this->setFixedSize(600, 400);
      

控件

创建按钮

包含头文件

#include <QPushButton>

调用类的构造函数创建按钮

QPushButton* a = new QPushButton();

显示按钮

// 另外开一个窗口显示按钮
a->show();
// 设置按钮的父对象为窗口,这样按钮就在窗口上显示
a->setParent(this);

设置按钮的属性

// 设置按钮的内容
a->setText("按钮");
// 设置按钮的位置
a->move(100, 100);
// 设置按钮的大小
a->setFixedSize(20, 10);

对象树

  • 当创建的对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作,将对象会放入到对象树中。
  • 一定程度上简化了内存回收机制

坐标系

  • 左上角为 (0, 0)
  • x以右为正方向
  • y以下为正方向

信号和槽

  • 连接团数:connect

    • 参数

      • 参数1 信号的发送者
      • 参数2 发送的信号(函数的地址)
      • 参数3 信号的接受者
      • 参数4处理的槽经数(函数的地址)。
    • 松散耦合

    • 实现 点击按钮 关闭窗口的案例

    • connect(a, &QPushButton::clicked, this, &Widget::close);
      

自定义的信号和槽

  • 自定义信号

    • 写到 signals
    • 返回 void
    • 需要声明,不需要实现
    • 可以有参数,可以重载
  • 自定义槽函数

    • 返回 void
    • 需要声明,也需要实现
    • 可以有参数,可以重载
    • 写到 public slot 下或者 public 或者全局函数
  • 触发自定义的信号

    • emit 自定义信号
  • 案例-下课后,老师触发饿了信号,学生响应信号,请客吃饭

    • 创建Teacher类 和 Student

      // teacher.h文件
      #ifndef TEACHER_H
      #define TEACHER_H
      
      #include <QObject>
      
      class Teacher : public QObject
      {
          Q_OBJECT
      public:
          explicit Teacher(QObject *parent = nullptr);
      
      signals:
          void hungry();
          void hungry(QString foodName);
      };
      
      #endif // TEACHER_H
      
      
      // teacher.cpp文件
      #include "teacher.h"
      
      Teacher::Teacher(QObject *parent)
          : QObject{parent}
      {}
      
      // student.h文件
      #ifndef STUDENT_H
      #define STUDENT_H
      
      #include <QObject>
      
      class Student : public QObject
      {
          Q_OBJECT
      public:
          explicit Student(QObject *parent = nullptr);
          void treat();
          void treat(QString foodName);
      
      signals:
      };
      
      #endif // STUDENT_H
      
      
      // student.cpp文件
      #include "student.h"
      #include <QDebug>
      
      Student::Student(QObject *parent)
          : QObject{parent}
      {}
      
      void Student::treat() {
          qDebug() << "请老师吃饭";
      }
      
      void Student::treat(QString foodName) {
          qDebug() << "请老师吃饭,老师要吃:" << foodName.toUtf8().data();
      }
      
      
      
      // widget.h文件 
      #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include "teacher.h"
      #include "student.h"
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          Widget(QWidget *parent = nullptr);
          ~Widget();
      private:
          Teacher *tt;
          Student *st;
          void classIsOver();
      };
      #endif // WIDGET_H
      
      // widget.cpp文件
      #include "widget.h"
      #include <QPushButton>
      
      Widget::Widget(QWidget *parent)
          : QWidget(parent)
      {
          // 创建一个老师对象
          this->tt = new Teacher(this);
          // 创建一个学生对象
          this->st = new Student(this);
      
          // 老师饿了, 学生请客的连接
          void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
          void(Student:: *studentSolt)(QString) = &Student::treat;
      
          connect(tt, teacherSignal, st, studentSolt);
      
          // 调用下课的函数
          // classIsOver();
      
          // 点击一个 下课按钮,再触发下课
          QPushButton* a = new QPushButton("下课", this);
          this->setFixedSize(600, 400);
          a->move(100, 100);
          // 点击按钮 触发下课
          // connect(a, &QPushButton::clicked, this, &Widget::classIsOver);
      
          // 无参信号和槽连接
          void(Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
          void(Student:: *studentSolt2)(void) = &Student::treat;
          connect(tt, teacherSignal2, st, studentSolt2);
      
          // 信号连接信号
          connect(a, &QPushButton::clicked, tt, teacherSignal2);
      
          // 断开信号
          disconnect(tt, teacherSignal2, st, studentSolt2);
      
      }
      
      Widget::~Widget() {}
      
      void Widget::classIsOver() {
          // 下课函数,调用后触发老师饿了的信号
          emit tt->hungry("宫保鸡丁"); // 触发hungry()信号
      }
      
      //Qt4版本以前的信号和槽连接方式
      //利用Qt4信号槽连接无参版本
      //Qt4版本底层SIGNAL(hungry())
      connect(tt, SIGNAL(hungry()), st, SLOT(treat()));
      //Qt4版本优点:参数直观,缺点:类型不做检测
      //Qt5以上支持Qt4的版本写法,反之不支持
      
      int ret = []()->int{return 1000;}();
          qDebug() << ret;
      
      QPushButton *btn = new QPushButton("btn2", this);
          btn->move(100, 0);
          connect(btn, &QPushButton::clicked, this, [=](){
              this->close();
              emit tt->hungry("宫保鸡丁");
          });
      
      

当自定义信号和槽发生重载的解决

重载自定义信号和槽的代码如上

  • 需要利用函数指针 明确指向 函数的地址
  • void(Teacher *tSingal) (Qstring)=&Teacher::hungry
  • QString 转成char*
    • .ToUtf8()转为QByteArray
    • .Data()转为Char*
  • 信号可以连接信号
  • 断开信号 disconnect

拓展

  • 信号是可以连接信号
  • 一个信号 可以连接 多个槽函数
  • 多个信号 可以连接 同一个槽函数
  • 信号和槽函数的参数 必须类型一一对应
  • 信号和槽的参数个数 是不是要一致?信号的参数个数 可以多余槽函数的参数个数

Lambda表达式11.10

  • [] 标识符名函数
    • = 值传递
    • & 引用传递
  • () 参数
  • {} 实现体
  • mutable 修饰 值传递变量,可以修改拷贝出的数据,改变不了本体。
  • 返回值 int ret = []()->int{return 1000;}();

QMainWindow

  • 菜单栏最多有一个
    • QMenuBar *bar=MenuBar();
    • setMenuBar(bar);
    • QMenu *fileMenu = bar->addMenu(文件") 创建菜单
    • QAction *newAction = fileMenu->addAction(“新建"); 创建菜单项
    • 添加分割线 fileMenu->addSeparator);
  • 工具栏 可以有多个
    • QToolBar *toolbar = newQToolBar(this)
    • aadToolBar(默认停靠区域,toolbar); Qt:LefToolBarArea
    • 设置 后期停靠区域,设置浮动,设置移动
    • 添加菜单项 或者添加 小控件
  • 状态栏 最多一个
    • QStatusBar *stBar=statusBar();
    • 设置到窗口中 setStatusBar(stBar);
    • stBar->addwidget(label); 放左侧信息
    • stBar->addPermanentWidket(label2); 放右侧信息
  • 铆接部件 (浮动窗口) 可以多个
    • QDockWidget
    • addDockWidget 默认停靠区域,浮动窗口指针
    • 设置后期停靠区域
  • 设置核心部件 只能一个
    • setCentralWidget(edit);
// 在mainwindow.cpp

#include "mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>
#include <QTextEdit>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 重置窗口大小
    this->resize(600, 400);

    // 菜单栏 只能最多有一个
    // 菜单蓝创建
    QMenuBar *bar = this->menuBar();
    // 将菜单栏放入到窗口中
    this->setMenuBar(bar);

    // 创建菜单
    QMenu *fileMenu = bar->addMenu("文件");
    QMenu *editMenu = bar->addMenu("编辑");

    // 创建菜单项
    QAction *newAction = fileMenu->addAction("新建");
    // 添加分割线
    fileMenu->addSeparator();
    QAction *openAction = fileMenu->addAction("打开");

    // 工具栏 可以有多个
    QToolBar *toolBar = new QToolBar(this);
    this->addToolBar(Qt::LeftToolBarArea, toolBar);

    // 后期设置 只允许 左右停靠
    toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);

    // 设置浮动
    toolBar->setFloatable(false);

    // 设置移动 (总开关)
    toolBar->setMovable(false);

    // 工具栏中可以设置内容
    toolBar->addAction(newAction);
    // 添加分割线
    toolBar->addSeparator();
    toolBar->addAction(openAction);

    // 工具栏中添加控件
    QPushButton *btn = new QPushButton("aa", this);
    toolBar->addWidget(btn);

    // 状态栏 最多有一个 (函数)
    QStatusBar *stBar = statusBar();
    // 设置到窗口中
    this->setStatusBar(stBar);
    // 放标签控件到状态栏上
    QLabel *label = new QLabel("提示信息", this);
    stBar->addWidget(label);

    QLabel *label2 = new QLabel("右侧提示信息", this);
    stBar->addPermanentWidget(label2);

    // 铆接部件 (浮动窗口) 可以有多个
    QDockWidget *dockWidget = new QDockWidget("浮动", this);
    addDockWidget(Qt::TopDockWidgetArea, dockWidget);
    // 设置后期停靠区域,只允许上下
    dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);

    // 设置中心部件 只能一下
    QTextEdit *edit = new QTextEdit(this);
    this->setCentralWidget(edit);
}

MainWindow::~MainWindow() {}

资源文件

  • 将图片文件 拷贝到项目位置下
  • 右键项目 -> 添加新文件 -> Qt->Qtrecourse File -> 给资源文件起名
  • res生成res.qrc
  • open in editor 编辑资源
  • 添加前缀 添加文件
  • 使用 ": + 前缀名 + 文件名"
ui->actionnew->setIcon(QIcon(":/icon/8666681_edit_icon.png"));

对话框

分类

  • 模态对话框 不可以对其他窗口进行操作阻塞
    • QDialogdlg(this);
    • dlg.exec();
  • 非模态对话框 可以对其他窗口进行操作
    • 防止一闪而过 创建到堆区
    • QDialog *dlg2 = new QDialog(this);
    • dlg2->show();
    • dlg2->setAttribute(Qt::WA_DeleteOnClose); //55号属性

标准对话框-消息对话框

  • QMessageBox 静态成员函数创建对话框
  • 错误、信息、提问、警告
  • 参数1 父亲 参数2 标题 参数3 显示内容 参数4 按键类型 参数5 默认关联回车按键
  • 返回值 也是 StandardButton 类型,利用返回值判断用户的输入

其他标准对话框

  • 颜色对话框 QColorDialog::getColor
  • 文件对话框 QFileDialog::BetOpenFileName (父亲,标题,默认路径,过滤文件)
  • 字体对话框 QFontDialog::getFont
// 在mainwindows.cpp文件中

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QAction>
#include <QDialog>
#include <QDebug>
#include <QMessageBox>
#include <QColorDialog>
#include <QString>
#include <QFileDialog>
#include <QFontDialog>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 点击新建按钮 弹出一个对话框
    connect(ui->actionNew, &QAction::triggered, this, [=](){
        // QDialog dlg(this);
        // dlg.resize(200, 100);
        // dlg.exec();  // 阻塞状态
        // qDebug() << "模态对话框弹出来";

        // QDialog *dlg2 = new QDialog(this);
        // dlg2->resize(200, 100);
        // dlg2->show();
        // dlg2->setAttribute(Qt::WA_DeleteOnClose); // 55号 属性
        // qDebug() << "非模态对话框弹出来";

        // 消息对话框
        // 错误对话框  (静态成员函数 通过类名调用)
        // QMessageBox::critical(this, "critical", "错误");

        // 信息对话框
        // QMessageBox::information(this, "info", "信息");

        // 提问对话框
        // 参数1 父亲 参数2 标题 参数3 提示内容 参数4 按键类型 参数5 默认关联回车按键
        // if (QMessageBox::Save == QMessageBox::question(this, "ques", "提问", QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Cancel))
        // {
        //     qDebug() << "保存";
        // }else {
        //     qDebug() << "取消";
        // }

        // 警告对话框
        // QMessageBox::warning(this, "warning", "警告");

        // 其他对话框
        // 颜色对话框
        //QColor color = QColorDialog::getColor(QColor(255, 0, 0));
        //qDebug() << "r = " << color.red() << "g = " << color.green() << "b = " << color.blue();

        // 文件对话框 参数1 父亲 参数2 标题 参数3 默认打开路径 参数4 过滤文件格式
        // 返回值是 选取的路径
        //QString str = QFileDialog::getOpenFileName(this, "打开文件", "C:\\Users\\admin\\Desktop", "(*.txt");
        //qDebug() << str;

        // 字体对话框
        bool flag;
        QFont font = QFontDialog::getFont(&flag, QFont("华文彩云", 36));
        qDebug() << "字体: " << font.family().toUtf8().data() << "字号" << font.pointSize() << "是否加粗" << font.italic();
    });

}

MainWindow::~MainWindow()
{
    delete ui;
}

界面布局

  • 实现登陆窗口
  • 利用布局方式给窗口进行美化
  • 选取widget进行布局,水平布局、垂直布局、栅格布局
  • 给用户名、密码、登陆、退出按钮进行布局
  • 默认窗口和控件之间有 6 间隙,可以调整layoutLeftMargin
  • 利用弹簧进行布局

控件

按钮组

  • QPushButton 常用按钮
  • QToolButton 工具按钮 用于显示图片,如图想显示文字,修改风格:toolButtonStyle,凸起风格autoRaise
  • radioButton 单选按钮,设置默认 ui->rBtnMan->setChecked(true)
  • checkbox 多选按钮,监听状态,2选中 1半选 0未选中
// 设置单选按钮  男默认选中
    ui->radioButton->setChecked(true);
    
    // 选中女后 打印信息
    connect(ui->radioButton, &QRadioButton::clicked, this, [=]() {
        qDebug() << "选中了女";
    });
    
    // 多选按钮 2是选中 0是未选择中 1是半选
    connect(ui->checkBox, &QCheckBox::stateChanged, [=](int state){
            qDebug() << state;
    });

QListWidget列表容器

  • QListWidgetitem *item 一行内容
  • ui->listWidget->addltem(item)
  • 设置居中方式item->setTextAlignment(Qt:AlignHCenter);
  • 可以利用addItems一次性添加整个诗内容
// // 利用listWidget 写诗
    // QListWidgetItem *item = new QListWidgetItem("锄禾日当午");
    // // 将一行诗放入到listWidget控件中
    // ui->listWidget->addItem(item);
    // item->setTextAlignment(Qt::AlignHCenter);

    //QStringList QList<QString>
    QStringList list;
    list << "aaa"  << "aaaaaaa" << "aaaaaaaaaa" << "aaaaaaaaaa";
    ui->listWidget->addItems(list);

QTreeWidget树控件

  • 设置头
    • ui->treeWidget->setHeaderlabels(QstringList() << "英雄" << "英雄介绍" )
  • 创建根节点
    • QTreeWidgetitem *liltem=newQTreeWidgetitem(QStringList() << "力量")
  • 添加根节点到树控件上
    • ui->treeWidget->addTopLevelltem(lltem);
  • 添加子节点
    • liltem->addchild(l1);
// treeWidget树控件使用

    // 设置水平头 QStringList使用匿名对象
    ui->treeWidget->setHeaderLabels(QStringList() << "英雄" << "英雄介绍");

    QTreeWidgetItem *liItem = new QTreeWidgetItem(QStringList() << "力量");
    QTreeWidgetItem *minItem = new QTreeWidgetItem(QStringList() << "敏捷");
    QTreeWidgetItem *zhiItem = new QTreeWidgetItem(QStringList() << "智力");
    // 加载顶层的节点
    ui->treeWidget->addTopLevelItem(liItem);
    ui->treeWidget->addTopLevelItem(minItem);
    ui->treeWidget->addTopLevelItem(zhiItem);

    // 追加子节点
    QStringList heroL1;
    heroL1 << "刚被猪" << "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    QTreeWidgetItem *l1 = new QTreeWidgetItem(heroL1);
    liItem->addChild(l1);

QTableWidget表格控件

  • 设置列数
    • ui->tableWidget->setColumnCount(3);
  • 设置水平表头
    • ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄");
  • 设置行数
    • ui->tableWidget->setRowCount(5);
  • 设置正文
    • ui->tableWidget->setItem(0, 0, new QTableWidgetItem("雅思"));
 // TableWidget 控件
    // 设置列数
    ui->tableWidget->setColumnCount(3);

    // 设置水平表头
    ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄");

    // 设置行数
    ui->tableWidget->setRowCount(5);

    // 设置正文
    // ui->tableWidget->setItem(0, 0, new QTableWidgetItem("雅思"));
    QStringList nameList;
    nameList << "雅思" << "赵云" << "张飞" << "关羽" << "花木兰";

    QStringList sexList;
    sexList << "男" << "男" << "男" << "男" << "女";

    for (int row = 0; row < 5; row++)
    {
        int col = 0;
        ui->tableWidget->setItem(row, col++, new QTableWidgetItem(nameList[row]));
        ui->tableWidget->setItem(row, col++, new QTableWidgetItem(sexList.at(row)));
        // int 转 QString
        ui->tableWidget->setItem(row, col++, new QTableWidgetItem(QString::number(row + 18)));
    }

其他控件介绍

  • stackedWidget 栈控件
    • ui->stackedWidget->setCurrentIndex(2);
  • 下拉框
    • ui->comboBox->addItem("aaa");
  • Qlabel 显示图片
    • ui->label->setPixmap(QPixmap(":/Image/a.png"));
  • QLabel 显示动图 gif图片
    • ui->label_2->setMovie(movie);
    • movie->start();
#include "widget.h"
#include "./ui_widget.h"
#include <QMovie>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 栈控件使用
    // 设置默认 定位scrollArea
    ui->stackedWidget->setCurrentIndex(2);

    // scrollArea按钮
    connect(ui->btn_scrollArea, &QPushButton::clicked, [=] () {
        ui->stackedWidget->setCurrentIndex(2);
    });

    // tooBox按钮
    connect(ui->btn_toolBox, &QPushButton::clicked, [=] () {
        ui->stackedWidget->setCurrentIndex(1);
    });

    // TabWidget按钮
    connect(ui->btn_TabWidget, &QPushButton::clicked, [=] () {
        ui->stackedWidget->setCurrentIndex(0);
    });

    // 下拉框
    ui->comboBox->addItem("aaa");
    ui->comboBox->addItem("bbb");
    ui->comboBox->addItem("ccc");

    // 点击按钮 选中拖拉机
    connect(ui->btn_select, &QPushButton::clicked, [=] () {
        //ui->comboBox->setCurrentIndex(2);
        ui->comboBox->setCurrentText("ccc");
    });

    // 利用QLabel显示图片
    ui->label->setPixmap(QPixmap(":/Image/a.png"));
    // 利用QLabel显示 gif动态图片
    QMovie *movie = new QMovie(":/Imgea/a.gif");
    ui->label_2->setMovie(movie);
    // 播放动图
    movie->start();
}

Widget::~Widget()
{
    delete ui;
}

自定义控件封装

  • 添加新文件 Qt 设计师界面类(.h .cpp .ui)
  • .ui中设计QSpinBoxQslider两个控件
  • Widget中使用自定义控件,拖拽一个Widget,点击提升为,点击添加,点击提升
  • 实现功能,改变数字,滑动条跟着移动,信号槽监听。
  • 提供getNumsetNum对外接口
  • 测试接口

关于Qt控件提升后找不到头文件的解决方法

  • CMake文件中添加头文件目录,在CMake中添加下面这段就可以解决了

  • INCLUDE_DIRECTORIES(
        ${PROJECT_SOURCE_DIR}
    )
    
// 在smallwidget.cpp中

#include "smallwidget.h"
#include "ui_smallwidget.h"

SmallWidget::SmallWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::SmallWidget)
{
    ui->setupUi(this);

    // QSpinBox移动   QSlider跟着移动
    void(QSpinBox:: * spSignal) (int) = &QSpinBox::valueChanged;
    connect(ui->spinBox, spSignal, ui->horizontalSlider, &QSlider::setValue);

    // QSlider滑动    QSpinBox数字跟着改变
    connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);
}

SmallWidget::~SmallWidget()
{
    delete ui;
}

void SmallWidget::setNum(int num)
{
    ui->spinBox->setValue(num);
}

int SmallWidget::getNum()
{
    return ui->spinBox->value();
}

// smallwidget.h
#ifndef SMALLWIDGET_H
#define SMALLWIDGET_H

#include <QWidget>

namespace Ui {
class SmallWidget;
}

class SmallWidget : public QWidget
{
    Q_OBJECT

public:
    explicit SmallWidget(QWidget *parent = nullptr);
    ~SmallWidget();

    // 设置数字
    void setNum(int);
    // 获取数字
    int getNum();

private:
    Ui::SmallWidget *ui;
};

#endif // SMALLWIDGET_H


// smallwidget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>SmallWidget</class>
 <widget class="QWidget" name="SmallWidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>151</width>
    <height>33</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QHBoxLayout" name="horizontalLayout">
   <item>
    <widget class="QSpinBox" name="spinBox"/>
   </item>
   <item>
    <widget class="QSlider" name="horizontalSlider">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
        
// widget.cpp
        #include "widget.h"
#include "./ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 点击获取 获取当控件当前的值
    connect(ui->btn_get, &QPushButton::clicked, [=](){
        qDebug() << ui->widget->getNum();
    });

    // 设置一半
    connect(ui->btn_set, &QPushButton::clicked, [=](){
        ui->widget->setNum(50);
    });
}

Widget::~Widget()
{
    delete ui;
}

Qt中的事件

  • 鼠标事件
  • 鼠标进入事件 enterEvent
  • 鼠标离开事件 leaveEvent
  • 鼠标按下 mousePressEvent(QMouseEvent *ev)
  • 鼠标释放 mouseReleaseEvent
  • 鼠标移动 mouseMoveEvent
  • ev->x() x坐标 ev->y() y坐标
  • ev->button()可以判断所有按键 Qt::LeftButton Ot::RightButton
  • ev->buttons()判断组合按键 判断move时候的左右键 结合 & 操作符
  • 格式化字符串QString(“%1 %2”).arg().arg()
// mylabel.h中
#ifndef MYLABEL_H
#define MYLABEL_H

#include <QLabel>

class myLabel : public QLabel
{
    Q_OBJECT
public:
    explicit myLabel(QWidget *parent = nullptr);

    // 鼠标进入事件
    //void enterEvent(QEnterEvent *event);

    // 鼠标离开事件
    //void leaveEvent(QEvent *event);

    // 鼠标按下
    virtual void mousePressEvent(QMouseEvent *ev);
    // 鼠标释放
    virtual void mouseReleaseEvent(QMouseEvent *ev);
    // 鼠标移动
    virtual void mouseMoveEvent(QMouseEvent *ev);

signals:
};

#endif // MYLABEL_H


// 在mylabel.cpp中

#include "mylabel.h"
#include <QDebug>
#include <QString>
#include <QMouseEvent>

myLabel::myLabel(QWidget *parent)
    : QLabel{parent}
{
    // 设置鼠标追踪状态
    setMouseTracking(true);
}


// 鼠标进入事件
// void myLabel::enterEvent(QEnterEvent *event) {
//     qDebug() << "鼠标进入了";
// }

// 鼠标离开事件
// void myLabel::leaveEvent(QEvent *event) {
//     qDebug() << "鼠标离开了";
// }

// 鼠标按下
void myLabel::mousePressEvent(QMouseEvent *ev) {

    if (ev->button() == Qt::LeftButton) {
        QString str = QString("鼠标按下 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}
// 鼠标释放
void myLabel::mouseReleaseEvent(QMouseEvent *ev) {
    if (ev->button() == Qt::LeftButton) {
        QString str = QString("鼠标释放 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}
// 鼠标移动
void myLabel::mouseMoveEvent(QMouseEvent *ev) {
    if (ev->buttons() & Qt::LeftButton) {
        QString str = QString("鼠标移动 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}

定时器 1

  • 利用事件 voidtimerEvent(QTimerEvent *ev)
  • 启动定时器 startTimer(1000) 毫秒单位
  • timerEvent 的返回值是定时器的唯一标示 可以和 ev->timerid 做比较

定时器 2

  • 利用定时器类QTimer
  • 创建定时器对象QTimer *timer = new QTimer(this)
  • 启动定时器 timer->start(毫秒)
  • 每隔一定毫秒,发送信号timeout,进行监听
  • 暂停timer->stop
// 在widget.h中
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    // 重写定时器的事件
    void timerEvent(QTimerEvent *e);

    int id1; // 定时器1的唯一标识
    int id2; // 定时器2的唯一标识

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H


// 在widget.cpp中
#include "widget.h"
#include "./ui_widget.h"
#include <QTimer>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 启动定时器
    // 返回唯一ID
    id1 = startTimer(1000); // 参数1 间隔 单位 毫秒

    id2 = startTimer(2000);

    // 定时器第二种方式
    QTimer * timer = new QTimer(this);
    // 启动定时器
    timer->start(500);

    connect(timer, &QTimer::timeout, [=](){
        static int num = 1;

        // label_4 每隔0.5秒 +1
        ui->label_4->setText(QString::number(num++));
    });

    // 点击暂停按钮 实现停止定时器
    connect(ui->pushButton, &QPushButton::clicked, [=](){
        timer->stop();
    });
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timerEvent(QTimerEvent *e) {
    if (e->timerId() == id1) {
        static int num1 = 1;
        ui->label_2->setText(QString::number(num1++));
    }

    if (e->timerId() == id2) {
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }
}


event事件

  • 用途:用于事件的分发
  • 也可以做拦截操作,不建议
  • bool event (QEvent *e);
  • 返回值如果是true代表用户处理这个事件,不向下分发了
  • e->type() == 鼠标按下

在这里插入图片描述

事件过滤器

  • 在程序将时间分发到事件分发器前,可以利用过滤器做拦截
  • 步骤
    • 给控件安装事件过滤器
    • 重写eventFilter函数 (obj, ev)

在这里插入图片描述

// 在widget.h中
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    // 重写定时器的事件
    void timerEvent(QTimerEvent *e);

    int id1;
    int id2;

    // 步骤2 重写 eventfilter事件
    bool eventFilter(QObject *, QEvent *);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H


// 在widget中
#include "widget.h"
#include "./ui_widget.h"
#include <QTimer>
#include <QPushButton>
#include <QMouseEvent>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 启动定时器
    // 返回唯一ID
    id1 = startTimer(1000); // 参数1 间隔 单位 毫秒

    id2 = startTimer(2000);

    // 定时器第二种方式
    QTimer * timer = new QTimer(this);
    // 启动定时器
    timer->start(500);

    connect(timer, &QTimer::timeout, [=](){
        static int num = 1;

        // label_4 每隔0.5秒 +1
        ui->label_4->setText(QString::number(num++));
    });

    // 点击暂停按钮 实现停止定时器
    connect(ui->pushButton, &QPushButton::clicked, [=](){
        timer->stop();
    });
    
    // 给label 安装事件过滤器
    // 步骤1 安装事件过滤器
    ui->label->installEventFilter(this);
    // 步骤2 重写 eventfilter事件
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timerEvent(QTimerEvent *e) {
    if (e->timerId() == id1) {
        static int num1 = 1;
        ui->label_2->setText(QString::number(num1++));
    }

    if (e->timerId() == id2) {
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }
}

// 步骤2 重写 eventfilter事件
bool Widget::eventFilter(QObject *obj, QEvent *e) {
    if (obj == ui->label) {
        if (e->type() == QEvent::MouseButtonPress) {
            QMouseEvent *ev = static_cast<QMouseEvent *>(e);
            QString str = QString("事件过滤器中 鼠标按下 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
            qDebug() << str;

            return true; // true代表用户自己处理这个事件,不向下分发
        }
    }
    // 其他默认处理
    return QWidget::eventFilter(obj, e);
}


// 在mylabel.h中
#ifndef MYLABEL_H
#define MYLABEL_H

#include <QLabel>

class myLabel : public QLabel
{
    Q_OBJECT
public:
    explicit myLabel(QWidget *parent = nullptr);

    // 鼠标进入事件
    //void enterEvent(QEnterEvent *event);

    // 鼠标离开事件
    //void leaveEvent(QEvent *event);

    // 鼠标按下
    virtual void mousePressEvent(QMouseEvent *ev);
    // 鼠标释放
    virtual void mouseReleaseEvent(QMouseEvent *ev);
    // 鼠标移动
    virtual void mouseMoveEvent(QMouseEvent *ev);

    // 通过event事件分发器 拦截器 鼠标按下事件
    bool event(QEvent *e);

signals:
};

#endif // MYLABEL_H


// 在mylabel.cpp中
#include "mylabel.h"
#include <QDebug>
#include <QString>
#include <QMouseEvent>
#include <QLabel>

myLabel::myLabel(QWidget *parent)
    : QLabel{parent}
{
    // 设置鼠标追踪状态
    setMouseTracking(true);
}


// 鼠标进入事件
// void myLabel::enterEvent(QEnterEvent *event) {
//     qDebug() << "鼠标进入了";
// }

// 鼠标离开事件
// void myLabel::leaveEvent(QEvent *event) {
//     qDebug() << "鼠标离开了";
// }

// 鼠标按下
void myLabel::mousePressEvent(QMouseEvent *ev) {

    if (ev->button() == Qt::LeftButton) {
        QString str = QString("鼠标按下 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}
// 鼠标释放
void myLabel::mouseReleaseEvent(QMouseEvent *ev) {
    if (ev->button() == Qt::LeftButton) {
        QString str = QString("鼠标释放 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}
// 鼠标移动
void myLabel::mouseMoveEvent(QMouseEvent *ev) {
    if (ev->buttons() & Qt::LeftButton) {
        QString str = QString("鼠标移动 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}

bool myLabel::event(QEvent *e) {

    // 如果是鼠标按下,在event事件分发中拦截操作
    if (e->type() == QEvent::MouseButtonPress) {
        QMouseEvent *ev = static_cast<QMouseEvent *>(e);
        QString str = QString("Event函数中 鼠标按下 x = %1 y = %2 global_x = %3 global_y = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;

        return true; // true代表用户自己处理这个事件,不向下分发
    }

    // 其他事件 交给父类处理 默认处理
    return QLabel::event(e);
}

QPainter 绘图

  • 绘图事件void paintEvent()

  • 声明一个画家对象QPainter painter(this) this指定绘图设备

  • 画线、画圆、画矩形、画文字

  • 设置画笔QPen设置画笔宽度、风格

  • 设置画刷QBrush设置画刷风格

QPainter高级设置

  • 抗锯齿 效率低
    • painter.setRenderHint(QPainter::Antialiasing)
  • 对画家进行移动
    • painter.translate(100,0);
    • 保存状态save
    • 还原状态restore
  • 如果想手动调用绘图事件 利用update
  • 利用画家画图片 painter.drawPixmap(x, y, QPixmap(路径))
// 在widget.h中
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    // 绘图事件
    void paintEvent(QPaintEvent *);

    int posX = 0;

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H


// 在widget.cpp中
#include "widget.h"
#include "./ui_widget.h"
#include <QPainter> // 画家类
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 点击移动按钮 移动图片
    connect(ui->pushButton, &QPushButton::clicked, [=](){
        posX += 20;
        // 如果要手动调用绘图事件 用update函数
        update();
    });
}

void Widget::paintEvent(QPaintEvent *) {
    // // 实例化画家对象 this指定的是绘图设备
    // QPainter painter(this);
    // // 设置画笔
    // QPen pen(QColor(255, 0, 0));
    // // 设置画笔的宽度
    // pen.setWidth(3);
    // // 设置画笔风格
    // pen.setStyle(Qt::DotLine);
    // // 让画家 使用这个画笔
    // painter.setPen(pen);

    // // 设置画刷
    // QBrush brush(Qt::cyan);
    // // 设置画刷的风格
    // brush.setStyle(Qt::Dense7Pattern);
    // // 让画家使用这个画刷
    // painter.setBrush(brush);


    // // 画线
    // painter.drawLine(QPoint(0, 0), QPoint(100, 100));
    // // 画圆 椭圆
    // painter.drawEllipse(QPoint(100, 100), 50, 50);
    // // 画矩形
    // painter.drawRect(QRect(0, 0, 100, 100));
    // // 画文字
    // painter.drawText(QRect(100, 100, 100, 50), "aaaaaaaaaaaaaaaaaaaaaa");

    /* 高级设置 */
    // QPainter painter(this);
    // painter.drawEllipse(QPoint(100, 50), 50, 50);
    // // 设置 抗锯齿能力  效率较低
    // painter.setRenderHint(QPainter::Antialiasing);
    // painter.drawEllipse(QPoint(200, 50), 50, 50);

    // // 画矩形
    // painter.drawRect(QRect(20, 20, 50, 50));

    // // 移动画家
    // painter.translate(100, 0);

    // // 保存画家状态
    // painter.save();

    // painter.drawRect(QRect(20, 20, 50, 50));
    // painter.translate(100, 0);
    // // 还原画家保存状态
    // painter.restore();

    // painter.drawRect(QRect(20, 20, 50, 50));


    /* 利用画家 画资源图片 */
    QPainter painter(this);
    // posX += 20;
    // 如果超出屏幕 从0开始
    if (posX > this->width()) {
        posX = 0;
    }

    painter.drawPixmap(posX, 0, QPixmap(":/img/1.jpg"));

}


Widget::~Widget()
{
    delete ui;
}

QPaintDevice绘图设备

  • QPixmap Qlmage QBitmap(黑白色) QPicture QWidget
  • QPixmap 对不同平台做了显示的优化
    • QPixmap pix(300,300)
    • pix.fill (填充颜色)
    • 利用画家 往 pix 上画画 QPainter painter(&pix)
    • 保存 pix.save("路径")
  • QImage 可以对像素进行访问
    • 使用和QPixmap差不多 Qlmage img(300, 300, Qlmage::Format_RGB32)
    • 其他流程和QPixmap一样
    • 可以对像素进行修改 img.setPixel(ijvalue);
  • QPicture 记录和重现 绘图指令
    • QPicture pic
    • painter.begin(&pic);
    • 保存 pic.save(任意后缀名)
    • 重现 利用画家可以重现 painter.drawPicture(0,0,pic);

在这里插入图片描述

// 在Widget.h中
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    // 绘图事件
    void paintEvent(QPaintEvent *);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

// 在Widget.cpp中
#include "widget.h"
#include "./ui_widget.h"
#include <QPixmap>
#include <QPainter>
#include <QPicture>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // // Pixmap绘图设备 专门为平台做了显示优化
    // QPixmap pix(300, 300);
    // // 填充颜色
    // pix.fill(Qt::white);

    // // 声明画家
    // QPainter painter(&pix);
    // painter.setPen(QPen(Qt::green));
    // painter.drawEllipse(QPoint(150, 150), 100, 100);

    // // 保存
    // pix.save("C:\\Files\\Photos\\pix.png");

    // QImage 绘图设备 可以对像素进行访问
    // QImage img(300, 300, QImage::Format_RGB32);
    // img.fill(Qt::white);
    // // 声明画家
    // QPainter painter(&img);
    // painter.setPen(QPen(Qt::blue));
    // painter.drawEllipse(QPoint(150, 150), 100, 100);

    // // 保存
    // img.save("C:\\Files\\Photos\\img.png");

    // QPicture 绘图设备 可以记录和重现 绘图指令
    QPicture pic;
    QPainter painter;
    painter.begin(&pic); // 开始往上pic上画
    painter.setPen(QPen(Qt::cyan));
    painter.drawEllipse(QPoint(150, 150), 100, 100);
    painter.end(); // 结束画画

    // 保存到磁盘
    pic.save("C:\\Files\\Photos\\pic.cs");

}

// 绘图事件
void Widget::paintEvent(QPaintEvent *) {

    // QPainter painter(this);
    // // 利用Qimage 对像素进行修改
    // QImage img;
    // img.load(":/img/1.jpg");
    // // 修改像素点
    // for (int i = 50;  i < 100; i++) {
    //     for (int j = 50; j < 100; j++) {
    //         QRgb value = qRgb(255, 0, 0);
    //         img.setPixel(i, j, value);
    //     }
    // }

    // painter.drawImage(0, 0, img);

    QPainter painter(this);
    // 重现QPicture的绘图指令
    QPicture pic;
    pic.load("C:\\Files\\Photos\\pic.cs");
    painter.drawPicture(0, 0, pic);

}


Widget::~Widget()
{
    delete ui;
}

QFile对文件进行读写操作10.1

  • QFile 进行读写操作
  • QFile file(path文件路径)
    • file.open(打开方式) QIODeviceBase::ReadOnly
    • 全部读取 file.readAll() 按行读file.readLine() atend() 判断是否读到文件尾
    • 默认支持编码格式 utf-8
    • 利用编码格式类指定格式 QTextCodeC
    • QTextCodec *codec = QTextCodecH::codecForName(gbk");
    • ui->textEdit->setText(codec->toUnicode(array));
    • 文件对象关闭 close
    • file.open(QlODevice::writeOnly/Append)
    • file.write(内容)
    • fle.close 关闭

QFilelnfo读取文件信息

  • QFilelnfoinfo(路径)
    • qDebug() << "大小:" << info.size() << "后缀名:" << info.suffix() << "文件名称:" << info.fileName() << "文件路径:" << info.filePath(); qDebug() << "创建日期:" << info.birthTime().toString("yyyy/MM/dd hh:mm:ss"); qDebug() << "最后修改日期:" << info.lastModified().toString("yyyy-MM-dd hh:mm:ss");
// 在Widget.cpp中
#include "widget.h"
#include "./ui_widget.h"
#include <QFileDialog>
#include <QString>
#include <QFile>
#include <QStringConverter>
#include <QFileInfo>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 点击选取文件按钮,弹出文件对话框
    connect(ui->pushButton, &QPushButton::clicked, [=](){
        QString path = QFileDialog::getOpenFileName(this, "打开文件", "C:\\Files\\Photos");
        // 将路径放入到LineEdit中
        ui->lineEdit->setText(path);

        // 编码格式类
        auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);

        // 读取内容 放入到 textEdit
        // QFile默认支持的格式是 UTF-8
        QFile file(path);   // 参数就是读取文件的路径
        // 设置打开方式
        file.open(QIODeviceBase::ReadOnly);
        // QByteArray array = file.readAll();

        QByteArray array;
        while (!file.atEnd()) {
            array += file.readLine(); // 按行读
        }
        // 将读取到的数据 放入textEdit中
        ui->textEdit->setText(array);

        // 对文件对象进行关闭
        file.close();
        // 进行写文件
        // file.open(QIODeviceBase::Append);   // 用追加方式进行写
        // file.write("啊啊啊啊啊啊啊啊啊");
        // file.close();

        // QFileInfo 文件信息类
        QFileInfo info(path);
        qDebug() << "大小:" << info.size()
                 << "后缀名:" << info.suffix()
                 << "文件名称:" << info.fileName()
                 << "文件路径:" << info.filePath();
        qDebug() << "创建日期:" << info.birthTime().toString("yyyy/MM/dd hh:mm:ss");
        qDebug() << "最后修改日期:" << info.lastModified().toString("yyyy-MM-dd hh:mm:ss");

    });
}

Widget::~Widget()
{
    delete ui;
}

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解了你的要求,我会根据你的要求为您提供帮助。首先,您需要一个基于Qt的图形界面应用程序,以便您可以在其中添加功能。在您的程序中,您需要使用Qt提供的QPainter类来画矩形框。可以使用QPainter的drawRect函数来绘制矩形框,并且可以使用鼠标事件来获取绘制矩形框的坐标。下面是一个简单的示例代码: ```c++ #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> #include <QMouseEvent> #include <QPainter> #include <QDebug> class MyWidget : public QWidget { public: MyWidget(QWidget *parent = 0) : QWidget(parent) { setFixedSize(300, 300); setWindowTitle("Draw Rectangle"); } protected: virtual void mousePressEvent(QMouseEvent *event) override { if (event->button() == Qt::LeftButton) { m_rectStart = event->pos(); } } virtual void mouseReleaseEvent(QMouseEvent *event) override { if (event->button() == Qt::LeftButton) { m_rectEnd = event->pos(); update(); } } virtual void paintEvent(QPaintEvent *event) override { QWidget::paintEvent(event); QPainter painter(this); painter.fillRect(rect(), Qt::white); QRectF rect = QRectF(m_rectStart, m_rectEnd); painter.drawRect(rect); qDebug() << "Rect: " << rect.x() << ", " << rect.y() << ", " << rect.width() << ", " << rect.height(); } private: QPoint m_rectStart; QPoint m_rectEnd; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MyWidget widget; widget.show(); return app.exec(); } ``` 在上面的代码中,我们创建了一个QWidget来实现我们的应用程序,并重载了QMouseEvent事件,以便我们可以在用户单击左键时获取矩形的起点位置。当用户释放鼠标按钮时,我们将获取到的坐标存储在矩形的末点位置。然后,我们重载了paintEvent事件,并使用QPainter类来在窗口中绘制矩形框并打印出它的坐标。 您可以将上面的代码复制到Qt Creator中并编译它,并运行来查看代码的运行结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值