VS2019+QT6.24学习心得3

一、vs+qt自定义控件制作和出现“无法打开源文件”解决办法

        QT创建自定义控件见此视频所示:第三天02_自定义控件__onekeybatch_哔哩哔哩_bilibili

vs也与此类似。

        两者创建过程中都会遇到的一个问题:1.无法打开源文件“.h”   2.main文件和父窗口cpp文件都无法打开包括文件“.h”

        解决方法:1.对于qt制作的一般没有此问题,若出现问题。

               (1)在父窗口添加子窗口头文件。(2)默认编译完成的ui_XXX.h中显示的自定义控件类名称为#include<XXX>,显示无法识别,但主动修改成#include"XXX"可以识别。

        2.vs+qt出现此问题,编译显示错误,点击取消后会进入一个ui_“父窗口名”.h的文件

 (也可在外部引用依赖项找到)修改#include<XXX>为#include"XXX"

但是主动修改成#include"XXX"可以识别,请每次编译后都要手动修改。

解决方案:1.在qt中完成自定义控件界面设计,用vs打开qt项目进行编译,最终没有错误。

2.vs+qt进行页面设计是不要勾选全局。

二、QString字符串拼接

        1、

2、    // 字符串拼接 QString().arg()
          // %1, %2, %3 -- 占位符

 

三、鼠标事件

1.QMouseEven的button和buttons,要分清两者使用区别(瞬间和持续状态)

//鼠标进入
void MyLabel::enterEvent(QEnterEvent*)
{
	setText("你好!!!!!!!!"); 
}
void MyLabel::leaveEvent(QEvent*)
{
	setText("拜拜");
}
void MyLabel::mousePressEvent(QMouseEvent* ev)
{
	QString btn;
    if (ev->button() == Qt::LeftButton)
    {
        btn = "LeftButton";
    }
    else if (ev->button() == Qt::RightButton)
    {
        btn = "RightButton";
    }
    else if (ev->button() == Qt::MiddleButton)
    {
        btn = "MiddleButton";
    }
	QString str = QString("MousePree[%3]:(%1, %2)").arg(ev->x()).arg(ev->y()).arg(btn);
	setText(str);
}
void MyLabel::mouseReleaseEvent(QMouseEvent* ev)
{
    QString btn;
    if (ev->button() == Qt::LeftButton)
    {
        btn = "LeftButton";
    }
    else if (ev->button() == Qt::RightButton)
    {
        btn = "RightButton";
    }
    else if (ev->button() == Qt::MiddleButton)
    {
        btn = "MiddleButton";
    }
    QString str = QString("MouseRelease[%3]:(%1, %2)").arg(ev->x()).arg(ev->y()).arg(btn);
    setText(str);
}
void MyLabel::mouseMoveEvent(QMouseEvent* ev)
{
    QString btn;
    if (ev->buttons() & Qt::LeftButton)
    {
        btn = "LeftButton";
    }
    else if (ev->buttons() & Qt::RightButton)
    {
        btn = "RightButton";
    }
    else if (ev->buttons() & Qt::MiddleButton)
    {
        btn = "MiddleButton";
    }
    QString str = QString("MouseMove[%3]:(%1, %2)").arg(ev->x()).arg(ev->y()).arg(btn);
    setText(str);
}

2.设置定时器

        两种定时器#include<QTimerEvent>和#include <QTimer>

private:
    int id;
    int id1;   

 // 启动定时器
// 参数 1: 触发定时器的时间, 单位: ms
// 参数2: 使用默认值
// 返回值: 定时器ID
     id = startTimer(100);
     id1 = startTimer(3000);

//判断定时器后进行不同定时器操作,每触发一次定时器, 进入该函数中
void MyLabel::timerEvent(QTimerEvent* e)
{
    QString str;
    if (e->timerId() == id)
    {
        static int num = -100;
        str = QString("%1: %2").arg("Time out: ").arg(num++);
        if (num > 100)
        {
            // 关闭定时器
            killTimer(id);
        }

    }
    else if (e->timerId() == id1)
    {
        static int num1 = 10000;
        str = QString("%1: %2").arg("Time out: ").arg(num1++);
        if (num1 >= 10000 + 1000)
        {
            // 关闭定时器
            killTimer(id1);
        }
    }

    setText(str);
}


    // 第二种定时器用法#include <QTimer> 利用信号进行操作,也比较简单
    QTimer * timer = new QTimer(this);
    timer->start(100);
    connect(timer, &QTimer::timeout, this, [=]()
    {
        static int number = 0;
        this->setText(QString::number(number++));
            if (number > 50)
    {
        // 关闭定时器
                timer->stop();
                number = 0;
                timer->start();
    }
    });

四、绘图

1.回调函数与虚函数

回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

模块A有一个函数foo,它向模块B传递foo的地址,然后在B里面发生某种事件时,通过A里面传过来的foo地址调用foo,通知A发生了什么事情,让A作出相应反应,那么foo就称为回调函数。下面是回调函数的简单实例:

#include <iostream>  
using namespace std;  
  
typedef int(*CallBack)(char *p);//声明CallBack 类型的函数指针  
int A(char *p)  
{  
    cout<<"A"<<endl;  
    cout<<p<<endl;  
    return 0;  
}  
int B(CallBack lpCall,char *p)  
{  
    cout<<"B"<<endl;  
    cout<<p<<endl;  
    lpCall(p);    //借助回调完成的功能,也就是A函数来处理的.  
    return 0;  
}  
void main()  
{  
    char *p="hello!";  
    B(A,p);  
}

一个虚函数调用 * 实际上是一个回调。
调用者在对象的虚函数表中查找相应的条目并调用它。这与回调函数的行为完全相同,只是成员函数指针的语法比较笨拙。虚函数将工作卸载到编译器,这使它们成为一个非常优雅的解决方案。

2.窗口刷新事件

        窗口刷新:QWidget::update(), QWidget::repaint(),但一般使用update()可以最小化闪烁。

        对于回调函数如果用户强制刷新会在刷新后被调用,可以用此性质使用虚函数刷新。

void paintEvent(QPaintEvent*);

connect(ui->ButtonMove, &QPushButton::clicked, this, [=]()
    {
        // 刷新窗口
         update();   // 系统调用paintEvent 函数
     });

void Widget::paintEvent(QPaintEvent*)
{
    //创建画家类对象
    QPainter p(this); //指定绘图设备
    x += 5;
    if(x>this->width())
    {
        x = 20;
    }
    p.drawPixmap(x, 100, QPixmap(":/Image/sunny.png"));

}

3. 绘图设备

         大概采用以下几种绘图方式

// QWidget
// QPixmap QImage QPicture QBitmap(黑白图片)
// QBitmap 父类 QPixmap
// QPixmap -- 图片类, 主要用来显示, 它针对于显示器显示做了特殊优化, 依赖于平台的, 只能在主线程中使用(UI线程)
// QIamge -- 图片类 , 不依赖有平台, (图片传输 , 可以在多线程中对其进行操作)

 指定绘图设备

// 指定绘图设备 1. 构造函数中(参数是绘图设备)// 2. begin(参数是绘图设备)//    end();

但是采用begin的方式发现setpen函数不起作用

// 在QPixmap中画图
    QPixmap pix(300, 300);  // 纸的大小
    pix.fill(Qt::red);
    QPainter p(&pix);
    p.setPen(QPen(Qt::green, 10));
    p.drawRect(10, 10, 280, 280);
    p.drawEllipse(150, 150, 50, 50);
    pix.save("D:\\mypixmap.png");

    // 指定绘图设备 1. 构造函数中(参数是绘图设备)
    // 2. begin(参数是绘图设备)
     //    end();
     // 在QImage中画图
    QImage img(300, 300, QImage::Format_RGB32);  // 纸的大小
    img.fill(Qt::red);
    p.begin(&img);
    p.setPen(QPen(Qt::green, 10));
    p.drawRect(10, 10, 280, 280);
    p.drawEllipse(150, 150, 50, 50);
    p.end();
    img.save("D:\\myImage.png");

    // 在QPicture中画图
    // 1. 保存的是绘图步骤 -- 画家类
    // 2. 不是图片, 二进制文件(save保存生成的文件)
    // 3. 不依赖平台
   QPicture pic;  // 纸的大小
   p.begin(&pic);
   p.setPen(QPen(Qt::green, 10));
   p.drawRect(10, 10, 280, 280);
   p.drawEllipse(150, 150, 50, 50);
   p.end();
   pic.save("D:\\mypic.aaa");

上述代码只有。setPen QPixmap才起作用,QImage不起作用。

        

// 在QPixmap中画图
    QPixmap pix(300, 300);  // 纸的大小
    pix.fill(Qt::red);
    QPainter p(&pix);
    p.setPen(QPen(Qt::green, 10));
    p.drawRect(10, 10, 280, 280);
    p.drawEllipse(150, 150, 50, 50);
    pix.save("D:\\mypixmap.png");

    // 指定绘图设备 1. 构造函数中(参数是绘图设备)
    // 2. begin(参数是绘图设备)
     //    end();
     // 在QImage中画图
    QImage img(300, 300, QImage::Format_RGB32);  // 纸的大小
    img.fill(Qt::red);
    QPainter painter(&img);
    painter.setPen(QPen(Qt::green, 10));
    painter.drawRect(10, 10, 280, 280);
    painter.drawEllipse(150, 150, 50, 50);
    
    img.save("D:\\myImage.png");

    // 在QPicture中画图
    // 1. 保存的是绘图步骤 -- 画家类
    // 2. 不是图片, 二进制文件(save保存生成的文件)
    // 3. 不依赖平台
    QPicture pic;  // 纸的大小
    p.begin(&pic);
    p.setPen(QPen(Qt::green, 10));
    p.drawRect(10, 10, 280, 280);
    p.drawEllipse(150, 150, 50, 50);
    p.end();
    pic.save("D:\\mypic.aaa");

上述代码QPixmap和QImage的setPen都起作用作用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值