c++/Qt学习笔记

1.基础知识

1.main.cpp

#include "widget.h"

#include <QApplication>


//argc命令行变量的数量  argv命令行变量的数组
int main(int argc, char *argv[])
{
    //应用程序对象,有且只能有一个
    QApplication a(argc, argv);

    //窗口对象  Qwidget是Qmainwindow和Qdialog的父类
    Widget w;
    w.show();
    //应用程序对象进行死循环,内部是一个消息循环机制
    //代码阻塞到这一行,之后的程序不进行运行。
    return a.exec();
}
//svn代码合并a,b实现合并

2. .pro文件解释

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets//大于版本4以上,包含widget模块

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

3.命名规范和快捷键

1.类名 首字母大写,单词与单词之间首字母大写

2.函数名 变量名称 首字母小写 单词与单词之间首字母大写

3.快捷键

注释 ctrl+/

运行 ctrl+r

编译 ctrl+b

查找 ctrl+f

4.常见错误

1、error: ‘header’ was not declared in this scope

在使用此变量之前没有对其进行定义

2、error - RtlWerpReportException failed with status code :-1073741823

这个错误多半是因为一个变量定义好后还没有被初始化,在内存中还没有分配空间,就被拿来使用了。或者一些多线陈里或者文件.h定义先后顺序的问题,检查变量被使用前是否已经初始化和分配空间

3、QMetaObject::connectSlotsByName: No matching signal for on_xxxxx()

对结果没有影响,程序不会出现错误。
Qt中空间名称关联槽的方式进行关联,对应的函数必须写成"on_控件名_信号名"的格式;或者也可以通过connet函数人为显式地将信号和槽关联起来。但是,如果采用显式connect的方法的同时,又将槽函数的名字起成了“on_控件名_信号名”的格式,那么就会在运行时弹出警告.为了消除“对于……没有匹配信号”的警告,我们需要遵循这个命名约定,或者确保我们的槽名都不是以“on_”开头的。

4、error: multiple definition of `menu::menu(QWidget*)’

在.h文件中声明各种类以后,在使用这些类的.cpp文件的开头对这些.h文件进行了声明。若在delete.h文件的开头声明了另一个menu.h文件,即两个文件有了嵌套关系,这时在delete.cpp文件中就不需要再对menu.h进行声明了,否则会出现上方重复定义的错误。也可以打开QT工程文件*.pro,查看SOURCES += \ 以及 HEADERS += \下方是否有重复的源文件名或头文件名,删掉重复。

5、error: ‘setCodecForTr’ is not a member of ‘QTextCodec’

在QT5中,不支持QTextCodec,直接删除这句话。

6、error: ‘UnicodeUTF8’ is not a member of ‘QApplication’

apply(“emergency_call”, “Form”, 0, UnicodeUTF8) 修改为:
apply(“emergency_call”, “Form”, 0)

7、error: ‘class QHeaderView’ has no member named ‘setResizeMode’

将 setResizeMode 替换为为 setSectionResizeMode

8、error: undefined reference to `zero::on_export_menu()’

出现此问题的原因是,在.h文件中对on_export_menu()槽进行了声明,但是并没有在.cpp文件中对其进行定义。可以尝试删除.h文件中的声明或对其进行定义。

9、error: ld returned 1 exit status

解决方案是将保存路径下的build-xxxxx-Desktop…文件夹删除,切记是build…文件,删除后重新编译运行程序会再次生成build文件。

10.路径不可带有中文,而且程序也是中文敏感。

5.按钮控件

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{//创建一个按钮
    QPushButton * btn =new QPushButton;//使用某个类的时候,需要提前添加头文件才可以使用
    btn->show();//show函数以顶层的方式弹出窗口控件
    btn->setParent(this);
    btn->setText("第一个按钮");
//    btn->

    QPushButton * btn2 =new QPushButton("第二个按钮",this);
    btn2->show();
//    resize(600,400);
    btn2->move(100,100);
//设置标题
    setWindowTitle("1111");
    setFixedSize(1000,618);


    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;

}

1.创建

 QPushButton * btn =new QPushButton

2.设置父类

btn->setParent(this)

3.设置文本

btn->setText("第一个按钮")

4.设置位置

btn2->move(100,100)

5.重新制定窗口大小

resize(600,400)     //测试无用
setFixedSize(1000,618)  //测试有用   固定大小,不可拉伸

6.设置窗口标题

setWindowTitle("1111")  //无法设定

7.比较两种创建方式

 QPushButton * btn =new QPushButton;//使用某个类的时候,需要提前添加头文件才可以使用
 btn->show();//show函数以顶层的方式弹出窗口控件
 btn->setParent(this);
 btn->setText("第一个按钮");
    
    
 QPushButton * btn2 =new QPushButton("第二个按钮",this);
 btn2->resize(100,100);
 btn2->move(100,100);

6.对象树

当创建的对象在堆区的时候,如果指定的父亲是QObect派生或者QObect子类派生下来的类,可以不用管理释放的操作。

2.信号和槽机制

1.信号与槽

1.连接函数 connect()

2.参数

参数1 信号的发送者; 参数2 发送的信号; 参数3 信号的接收者 ;参数4 处理的槽函数

3.松散耦合

4.信号和槽如果在子类中没有找到,可以去帮助文档里面寻找父类的signal 和 slot

以下两种交叉使用也是可以的。

connect(myBtn,&QPushButton ::clicked,this,&QWidget::close);
//&传入的是地址

 connect(myBtn,&MyPushButton ::clicked,this,&Widget::close);

//第二种从左到右分别是  按钮对象 按钮对应函数地址   this(指当前类的对象) 当前类槽函数的地址  

2.自定义的信号和槽

自定义的响应类 student.h

//早期的版本qt 必须要写到public slots下,5.4之后,可以写到public或者全局下
    //返回值 void ,需要声明,也需要实现
    //可以有参数,可以发生重载
public:
    void treat();//如果只是在信号下进行声明,会在moc_student文件内部也有一个空的实现,发生重定义错误。所以要注意声明的位置。

自定义的信号发出类 teacher.h

signals:
    //自定义的信号  写到signals下
    //返回值是void,只需要声明,不需要实现
    //可以有参数,也可以重载
    void hungry();

可以观察到信号一般先在头文件中声明,然后在.cpp源文件中加上作用域进行实现。

widget.h

#include "teacher.h"
#include "student.h"


private:
    Ui::Widget *ui;
    Teacher * zt;//

    Student * st;//
    void classIsOver();

1.因为widget类使用了teacher和student两个类。所以需要先在头文件中加入对应类的头文件

2.创建对象的时候,会在相应的widget的私有属性中创建指针。

3.自己写的信号发出函数,也需要在头文件中声明。只有私有的函数成员才可以调用私有的成员属性,所以才写在private中。

widget.cpp

#include "widget.h"
#include "ui_widget.h"

//Teacher 类 学生类
//Student 类 学生类
//下课之后,老师触发了一个信号,饿了,学生响应信号,请客吃饭

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

    this->zt= new Teacher(this);
    //这里this相当于加到了对象树上

    this->st = new Student(this);
    //老师饿了,连接
    connect(zt,&Teacher::hungry,st,&Student::treat);

    classIsOver();//注意方法的位置,先进行连接后进行方法调用。
}


void Widget::classIsOver()
{

    //下课函数,调用后,触发老师饿了的信号
    emit zt->hungry();
}

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




    //重载之后,会出现不能区分地址的问题
    void(Teacher::*teacherSignal)(QString)=&Teacher::hungry;
    void(Student::*studentSignal)(QString)=&Student::treat;
    connect(zt,teacherSignal,st,studentSignal);

1.掌握信号发出函数的书写,以及连接和函数的顺序。

2.这里this相当于加到了对象树上,继承于最终object,无需自己进行析构。

3.重载之后无法识别,利用函数指针准确的指向相应的地址。

Qdebug的用法

#include <QDebug>


void Student::treat()
{
    qDebug()<<"请老师吃饭";

}
qDebug()<<"请老师吃饭,老师要吃"<< foodname.toUtf8().data();//先转为Qbytearray,然后转为char*
//才能去掉引号

3.信号连接信号

1.()填写返回值

2.disconnect()用于断开连接。

 void(Teacher::*teacherSignal2)(void)=&Teacher::hungry;
    void(Student::*studentSlot)(void)=&Student::treat;


    connect(btn,&QPushButton::clicked,zt,teacherSignal2);
    connect(zt,teacherSignal2,st,studentSlot);
    disconnect(btn,&QPushButton::clicked,zt,teacherSignal2);

3.一个信号可以连接多个槽函数,多个信号可以连接同一个槽函数。

4.信号和槽函数的参数 类型必须一一对应

5.信号和槽函数的参数个数 信号的参数可以多于槽函数,反过来不对

例如:Qstring  ->  void     1->0  符合个数要求

6.qt4版本中 ,缺点是类型错误不报错,难以发现错误。

connect(zt,SIGNAL(hungry()),st,SLOT(treat()))

4.Lambda表达式(匿名函数)

1.标准形式

()参数 ----- {} 实现体------------mutable 修饰值传递变量 ,修改拷贝数据,改变不了本体。

最标准的形式 { }

=值传递

&引用传递

[=](){
        btn->setText("aaa");

    }();//注意格式,最后要加上小括号。要不然只是声明,没有调用。[]中的等号表示以值传递将lambda所在类的this中变量传递

2.带有返回值

 int ret=[]()->int{return 1000;}();
    qDebug()<<ret;

3.连接信号


    QPushButton *btn2 =new QPushButton;
    btn2->setParent(this);
    btn2->setText("关闭");
    btn2->move(100,0);

    connect(btn2,&QPushButton::clicked,this,[=](){
        this->close();//lambda中没使用=的话。不识别this
    });

3.QMainWindow

1.菜单栏设计

菜单栏最多只能有一个

     QMenuBar*bar=menuBar();//系统中有对应的方法,已经放在对象树上了。
    //将菜单栏放入到窗口中,空栏不会显示。
    setMenuBar(bar);
//创建菜单
    QMenu* fileMenu = bar->addMenu("文件");
    QMenu* editMenu = bar->addMenu("编辑");



    //创建菜单项
    fileMenu->addAction("新建");

    //添加分割线
    fileMenu->addSeparator();

    fileMenu->addAction("打开");

2.工具栏

可以存在多个。


    QToolBar * toolbar = new QToolBar(this);
    addToolBar(Qt::LeftToolBarArea,toolbar);

    toolbar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);//设置菜单位置
//   Qt::  枚举值
    
//设置浮动
    toolbar->setFloatable(false);
    //设置移动(总开关)
    toolbar->setMovable(false);
  //工具栏中设置内容
    toolbar->addAction(newAction);//采用了第十三个类型
    toolbar->addSeparator();
    toolbar->addAction(openAction);//这是共用了同一个。
//工具栏中添加控件
    QPushButton *btn = new QPushButton("aaa",this);
    toolbar->addWidget(btn);

3.状态栏

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

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


4.铆接部件,浮动窗口


    //铆接部件(浮动窗口)可以有多个,浮动窗口在核心下面
    QDockWidget* dockWidget= new QDockWidget("浮动",this);
    addDockWidget(Qt::BottomDockWidgetArea,dockWidget);

    //设置智能上下浮动
    dockWidget->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);

5.核心部件

这里的中心部件使用了记事本


    //设置中心部件,只能有一个。
    QTextEdit* edit= new QTextEdit(this);
    setCentralWidget(edit);

4.资源文件

1.添加资源文件

1.将图片文件拷贝到项目位置下

2.右键项目->添加新文件->Qt->Qt resource file->给资源文件起名

3.res 生成res.qrc

4.open in editor 编辑资源

5.添加前缀 添加文件

6.使用 “:+前缀名+文件名” 就可以添加资源图片。

5.对话框

对话框 分类
模态对话框 (不可以对其他窗口操作) 非模态(可以操作)

1.非模态

为了防止一闪而过,将对象创建在堆区

connect(ui->actionnew,&QAction::triggered,[=](){
		QDialog *dla = new QDialog (this);
        dla->resize(150,100);
        dla->show();
        dla->setAttribute(Qt::WA_DeleteOnClose);//55号属性,关闭的时候释放内存,防止内存泄漏
        qDebug()<<"非模态的对象创建了";

    });

2.模态

connect(ui->actionnew,&QAction::triggered,[=](){
        //对话框 分类
        //模态对话框 (不可以对其他窗口操作) 非模态(可以操作)
        //模态创建
        QDialog dlg(this);
        dlg.resize(100,100);
        dlg.exec();//阻塞的方法进行窗口持续显示
        qDebug()<<"模态对话框创建了";
  });

3.消息对话框

1.QMessageBox静态成员函数 创建对话框

2.错误、信息、提问、警告

QMessageBox::question(this,"问题","提问",QMessageBox::Save|QMessageBox::Cancel)

3.参数1 : 父亲 参数2 : 标题 参数3:显示内容 参数4:按键类型

4.返回值

返回值就是QMessageBox::Save|QMessageBox::Cancel中的一个,也是StandardButton类型。可以利用返回值来进行用户行为的捕获。

 connect(ui->actionnew,&QAction::triggered,[=](){
  if(QMessageBox::Save== QMessageBox::question(this,"问题","提问",QMessageBox::Save|QMessageBox::Cancel))
        {

        qDebug()<<"用户选择的是save选项";
        };

    });
}

4.颜色对话框

返回值 color对象

connect(ui->actionnew,&QAction::triggered,[=](){


        QColor color=QColorDialog::getColor(QColor(255,0,0));
        qDebug()<<"r="<<color.red()<<"g="<<color.green()<<"b="<<color.blue();

    });

5.文件对话框

返回值是一个字符串类型。是打开文件的地址。

"*.txt"文件格式的筛选

地址要使用双斜杠,否则会出错。

 connect(ui->actionnew,&QAction::triggered,[=](){


       QString str=  QFileDialog::getOpenFileName(this,"打开文件","D:\\桌面存储文件夹\\","*.txt");
        qDebug()<<str;//



    });

6.字体对话框


        bool flag;
        QFont font= QFontDialog::getFont(&flag,QFont("华文彩云",36));
        qDebug()<<font.family().toUtf8()<<font.pointSize()<<font.bold()<<font.italic();//这里的加粗和倾斜并没有出现

6.界面布局

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.控件

1.QPushButton 常用按钮

QToolButton 工具按钮 用于显示带图片的按钮,修改风格

radioButton 单选按钮 设置默认 ui->rbtnman->setChecked(true);

一般的话布局使用ui设计,但是逻辑的话需要通过代码的方式实现。

命名控件—>然后调用控件来实现信号的连接

QRadioButton控件使用的时候,采用了以下的方式连接

 ui->setupUi(this);
    ui->rbtnman->setChecked(true);
    connect(ui->rbtnwomen,&QRadioButton::clicked,[=](){

        qDebug()<<"选中了女的";
    });//这里的连接使用了匿名对象的方式,虽然没有接受者但是可以事件的方式来进行输出

QCheckBox 多选按钮 监听状态 选中参数为2 未选中参数为0 半选为1 在在属性中为tristate



connect(ui->cbox,&QCheckBox::stateChanged,[=](int state){

    qDebug()<<state;//如果匿名函数有返回值的话,我们应该在()中表明
});

2.QListWidget 列表容器

利用listwidget写诗(第一种) QListWidgetItem *item =new QListWidgetItem(“锄禾日当午”); 一行内容


QListWidgetItem *item =new QListWidgetItem("锄禾日当午");

ui->listWidget->addItem(item);
item->setTextAlignment(Qt::AlignHCenter);//选中居中方式

//第二种 QStringlist QList

可以使用QStringList 来完成多行的输入


QStringList list;
list<<"锄禾日当午"<<"汗滴禾下土"<<"谁之盘中餐"<<"粒粒皆辛苦";
ui->listWidget->addItems(list);

3.树控件的使用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍");
QTreeWidgetItem *liitem =new QTreeWidgetItem(QStringList()<<"力量");
QTreeWidgetItem *liitem1 =new QTreeWidgetItem(QStringList()<<"敏捷");
QTreeWidgetItem *liitem2 =new QTreeWidgetItem(QStringList()<<"智力");
//加载顶层的节点

ui->treeWidget->addTopLevelItem(liitem);
ui->treeWidget->addTopLevelItem(liitem1);

ui->treeWidget->addTopLevelItem(liitem2);//设置为顶部的节点

//追加子节点
QStringList hero1;
hero1<<"老田"<<"擅长狗叫";
QTreeWidgetItem *l1 = new QTreeWidgetItem(hero1);
liitem->addChild(l1);//addchild()添加子节点到父节点中

追加子节点的时候,使用了Qstringlist多行生成的代码。两次输出就会分栏。

4,QTablewidget

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

//tablewidget的使用

    //设置列数
    ui->tableWidget->setColumnCount(3);

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

    //设置正文
    ui->tableWidget->setItem(0,0,new QTableWidgetItem("亚瑟"));
    QStringList namelist;//容器
    namelist<<"亚瑟"<<"赵云"<<"张飞"<<"关羽"<<"花木兰";

    QList<QString> sexlist;//容器,把容器看一下
    sexlist<<"男"<<"男"<<"男"<<"男"<<"女";


    //循环赋值
    for(int i=0;i<5;i++)
    {
        int col=0;
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(namelist[i]));//可以索引。超出直接挂
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexlist.at(i)));//超出抛出异常
        //int 转为 QString,因为这个条目的接受值类型为QString
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));

    }

5其他控件

combobox一样的使用connect()来连接信号

stackWidget 栈控件

connect(ui->btn2,&QPushButton::clicked,[=](){
    ui->stackedWidget->setCurrentIndex(0);
});//控件的属性中有对应的索引属性

下拉框

ui->com->addItem("奔驰");
    ui->com->addItem("宝马");
    ui->com->addItem("大众");
    connect(ui->btn,&QPushButton::clicked,[=](){
//        ui->com->setCurrentIndex(1);//012排序
        ui->com->setCurrentText("大众");//这个可以直接写标签名字,如果没有则不会跳转。
    });

QLabel显示图片

ui->cc->setPixmap(QPixmap(":/image/fa1.jpg"));//这里的不是地址

6.自定义框架

1.添加新文件 qt —设计师类–(.h .cpp .ui)

2…ui中设计了QspinBox 和QSlider 两个控件

3.widget中使用了自定义控件,拖拽一个widget-----提升为-----添加

4.实现功能,改变数字,滑动条跟着移动,信号槽监听

widget.cpp


//点击控件,获取控件当前的值
    connect(ui->btn1,&QPushButton::clicked,[=](){

        qDebug()<<ui->widget->getNum();
    });

  //点击按钮设置值为一半
    connect(ui->btn2,&QPushButton::clicked,[=](){
        ui->widget->setNum(50);//这里的

    });

small.h(添加的自定义控件,析构函数中声明两个函数)

void setNum(int num);
    int getNum();//这里写函数,在头文件根据几个原则来写:1,返回值  2.参数  3.需要实现的功能来命名函数

small.cpp

//QSPinbox移动,qslider也跟着移动

    connect(ui->spinBox,&QSpinBox::valueChanged,ui->horizontalSlider,&QSlider::setValue);
    //6.5版本并没有函数重载等问题,所以无需使用信号重载重新获取地址

    //qslider移动,qspinbox也移动
    connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

}

void small::setNum(int num)
{
    ui->spinBox->setValue(num);//按钮是ui->widget-btn,框架中的按钮
                                //但是这个ui->spinbox->setvalue 某个实例化对象的方法
}
int small::getNum()
{
    return ui->spinBox->value();
}

8.鼠标事件

1.鼠标进入 enterevent

2.鼠标离开 leaveevent

3.鼠标按下 mousepressevent

4.鼠标释放 mouserelease

5.鼠标移动 mousemoveevent

6.ev->x() ev->y() ev->globalx() ev->globaly() 坐标 //globalx是相当于屏幕左上角的坐标位置

7.ev->button() 可以判断所有的按键 Qt::leftbutton 等


if( ev->button()==Qt::LeftButton){

QString str= QString("鼠标释放了了 x=%1  y=%2  globalx=%3  globaly=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());//c++中的格式表达式
qDebug()<<str;

//
}

8.ev->buttons() 可以判断组合按键 判断move时候的左右键 结合&操作符

if( ev->buttons()  & Qt::LeftButton){}

9.格式化字符串 c++中的格式表达式

QString str= QString("鼠标移动了 x=%1  y=%2  globalx=%3  globaly=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;//globalx是相当于屏幕左上角的坐标位置
//参数的话,直接加在后面就行
//移动属于一个状态,使用的位与,buttons

10.鼠标追踪

setMouseTracking(this);//类内设置鼠标追踪

9.定时器

第一种定时器

void timerEvent(QTimerEvent *event);//利用事件  

widget.h中的类

/重写定时器事件,记住定时器事件的名称
    void timerEvent(QTimerEvent *event);
int id1;//定时器1的标识,写成成员属性,可以类内的方法均使用到
int id2;//

启动定时器 返回值

id1= startTimer(1000);//参数1  间隔 单位毫秒
   id2=startTimer(2000);//返回值为一个int类型为定时器id,本身是定时器启动的一个方法

定时器一段时间之后,触发timerevent ,并且传入event参数

void Widget::timerEvent(QTimerEvent *event)
{
    //每隔一秒+1
   if(event->timerId()==id1){
    static int num=1;//静态变量,静态变量:有时希望变量的值在函数调用结束后不消失而保留原值,这时就应该指定变量为“静态变量”,用关键字static进行命名
    ui->label_2->setText(  QString::number(num++));
   }
    //每隔两秒+1
   if(event->timerId()==id2){
    static int num2=1;
    ui->label_3->setText(  QString::number(num2++));
   }
}

第二种定时器

//定时器类
   QTimer *timer= new QTimer(this);
   //启动定时器
   timer->start(500);
   connect(timer,&QTimer::timeout,[=](){
       static int num3=1;
       ui->label_4->setText(  QString::number(num3++));
   });
   

这里将一个按钮连接到定时器中

connect(ui->pushButton,&QPushButton::clicked,[=](){

    timer->stop();
});

事件分发器

用途:用于事件的分发,也可以做拦截操作,不推荐

bool mylabel::event(QEvent *e);记得在头文件中声明,返回值true代表用户自己处理这个事件,不向下分发

bool mylabel::event(QEvent *e){

    if(e->type()==QEvent::MouseButtonPress)//对事件分发过程中进行拦截操作,
    {
    QMouseEvent *ev= static_cast<QMouseEvent*>(e);//静态类型转换
        
        
    QString str= QString("event函数中,鼠标按下了 x=%1  y=%2  globalx=%3  globaly=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());//c++中的格式表达式
    qDebug()<<str;
        
        
    return true;
    }
    //拦截了一个,其他事件交给父类处理 默认处理  mylabel的父类是QLabel
    return QLabel::event(e);

}

事件过滤器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

过滤器>分发器


bool Widget::eventFilter(QObject *watched, QEvent *event)
 {
   if(watched==ui->label)//选中控件
   {
    if(event->type()==QEvent::MouseButtonPress)//选中事件
    {
    QMouseEvent *ev= static_cast<QMouseEvent*>(event);//静态类型转换,确保可以正常的ev输出,转换Qevent为QMouseevent
    QString str= QString("eventfiler函数中,鼠标按下了 x=%1  y=%2  globalx=%3  globaly=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());//c++中的格式表达式
    qDebug()<<str;
    return true;//true代表用户自己处理这个事件,不向下分发
    }
   }

    //其他的默认处理
    return QWidget::eventFilter(watched,event);

};

问题:过滤器写在了widget中,分发器是写在mylabel控件中。

10.Qpainter

记得在头文件中声明,通过重写painterevent来实现



void Widget::paintEvent(QPaintEvent *event)
    {
    //实例化画家对象
    QPainter painter(this);//this指定的是绘图设备,在这里是指Widget

    //设置颜色,画家使用画笔,颜色的设置必须在画家之后
    QPen pen1(QColor(255,0,0));
    pen1.setWidth(3);
    pen1.setStyle(Qt::DotLine);
    painter.setPen(pen1);

    //画刷可以填充封闭图形颜色,自动填充
    QBrush brush(QColor(Qt::cyan));
    brush.setStyle(Qt::CrossPattern);
    //让画家使用画刷
    painter.setBrush(brush);

    painter.drawLine(QPoint(0,0),QPoint(100,100));

    painter.drawEllipse(QPoint(100,100),100,50);//圆和椭圆
    painter.drawRect(QRect(20,20,50,50));

    painter.drawText(QRect(10,200,100,50),"好好学习");

};

1.高级设计


    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));
painter.drawPixmap(posX,100,QPixmap(":/image/fa1.jpg"));

2.绘图设备

1.widget Qpixmap Qimage Qpicture

2.QPixmap

//QPixmap绘图设备 专门为平台做了显示的优化


    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("D:\\桌面存储文件夹\\pix.png");

3.Qimage 可以对像素进行操作

基础用法,直接写在类内,

   Qimage作为绘图设备  可以对像素访问
    QImage img(300,300,QImage::Format_RGB32);
    img.fill(Qt::white);

    QPainter pp(&img);
    pp.setPen(QPen(Qt::red));
    pp.drawEllipse(QPoint(100,100),100,100);
    img.save("D:\\桌面存储文件夹\\pix.png");
    

Qimage的 用法在widget中直接写不好使,得用绘图事件触发,写在构造函数中,原因之后在研究

void paintEvent(QPaintEvent *event);//头文件中的声明


void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QImage img;
    img.load(":/image/fa2.jpg");


    //修改像素点
    for(int i=0;i<100;i++)
    {

        for(int j=0;j<100;j++)
        {
            QRgb value=qRgb(0,255,0);
            img.setPixel(i,j,value);
        }
    }
     painter.drawImage(0,0,img);//画家画应该放在最后一步
};

QPicture 以任意的后缀进行文件存储

QPicture pic;
    QPainter pp;
    pp.begin(&pic);


    pp.setPen(QPen(Qt::red));

    pp.drawEllipse(QPoint(150,150),100,100);

    pp.end();
    pic.save("D:\\桌面存储文件夹\\ppp.ziliang");




通过事件进行调用

void paintEvent(QPaintEvent *event);

void Widget::paintEvent(QPaintEvent *event)
   {
    QPainter pp2(this);
    QPicture pc;
    pc.load("D:\\桌面存储文件夹\\ppp.ziliang");
    pp2.drawPicture(0,0,pc);


};

11.Qfile对文件进行操作

1.读文件对话框

 connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","D:\\桌面存储文件夹\\");

        ui->lineEdit->setText(path);

读写文件

//读取内容 放入
        QFile file(path);//默认格式是utf-8
        file.open(QIODeviceBase::ReadOnly);

        //按行读
        QByteArray array1;
        while (!file.atEnd()) {
            array1+=file.readLine();
        }
        //全读
        QByteArray array=file.readAll();

        ui->textEdit->setText(array1);

        file.close();
        //进行写文件
        file.open(QIODeviceBase::Append);//追加写,用writeonly的话 会将之前的内容清楚
        file.write("aaaa");
        file.close();

效果图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.QfileInfo

读取文档的一些信息

QFileInfo info(path);
        qDebug()<<"大小" <<info.size()<<"后缀名"<<info.suffix();
            qDebug()<<"创建日期"<<info.birthTime().toString("yyyy/MM/dd hh:mm:ss");

end();
pic.save(“D:\桌面存储文件夹\ppp.ziliang”);


通过事件进行调用

```c++
void paintEvent(QPaintEvent *event);

void Widget::paintEvent(QPaintEvent *event)
   {
    QPainter pp2(this);
    QPicture pc;
    pc.load("D:\\桌面存储文件夹\\ppp.ziliang");
    pp2.drawPicture(0,0,pc);


};

11.Qfile对文件进行操作

1.读文件对话框

 connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","D:\\桌面存储文件夹\\");

        ui->lineEdit->setText(path);

读写文件

//读取内容 放入
        QFile file(path);//默认格式是utf-8
        file.open(QIODeviceBase::ReadOnly);

        //按行读
        QByteArray array1;
        while (!file.atEnd()) {
            array1+=file.readLine();
        }
        //全读
        QByteArray array=file.readAll();

        ui->textEdit->setText(array1);

        file.close();
        //进行写文件
        file.open(QIODeviceBase::Append);//追加写,用writeonly的话 会将之前的内容清楚
        file.write("aaaa");
        file.close();

效果图

[外链图片转存中…(img-FjIauy9g-1706259486159)]

2.QfileInfo

读取文档的一些信息

QFileInfo info(path);
        qDebug()<<"大小" <<info.size()<<"后缀名"<<info.suffix();
            qDebug()<<"创建日期"<<info.birthTime().toString("yyyy/MM/dd hh:mm:ss");
  • 37
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值