QT5入门学习(一)_qt5学习-程序员宅基地

技术标签: c++  QT  qt  

DAY01

添加按钮之前先包含头文件,在widget.h中#include<QPushButton>,第一个字母都是Q。继续在private:下面添加如下代码。

private:
    QPushButton b1;//可以直接使用
    QPushButton *b2;//不能直接使用。空指针,需要实际的内存。
    
    //按钮进行初始化,实例化,实例化的2种方式。
    b2 = new QPushButton("hello,qt");
    //b2->setText("hello,qt");
    b2->show();

界面如图所示,未达到预期效果,因为窗口2没有依附窗口1。
在这里插入图片描述
如果窗口需要依附另外一个窗口,需要给该窗口指定一个父类。让他依附于谁就把窗口类传给他。

b2 = new QPushButton("hello,qt",this);

用第一种方式创建按钮,没有用.show();也出现了
在这里插入图片描述父窗口显示的时候,子窗口也会随之显示。如果有100个窗口还要show100次,但是指定了this这个父类,子类就不需要show了。但是出现了hello qt被覆盖了,于是我们要改变按钮的位置。得出结论,窗口的坐标系原点在左上角,X轴向右递增,Y轴向下递增。
在这里插入图片描述
QT中的对象树。析构顺序和构造的顺序相反。QT的内存回收机制:1、使用的类是直接或者间接从QObject的派生。2、类在创建对象的时候指定父对象,在析构的时候首先析构子类对象。
在这里插入图片描述添加新文件不改变参数类型只改变父类对象。并且在头文件中添加析构函数。
在这里插入图片描述
析构过程:在widget.h中创建对象,之后运行项目。
在这里插入图片描述
运行结果如图所示。
在这里插入图片描述关闭UI界面的时候,默认被释放。
在这里插入图片描述

函数的使用

对于类来说,直接按下F1进入帮助文档,对于类的函数来说,指定完成参数之后按下F1进入帮助文档。
在这里插入图片描述
在这里插入图片描述
设置窗口的标题,在widget下用this指针指向本作用域。也可以在main函数中对窗口标题进行设置,直接用到w.resize(),w.setWindowTitle()函数。

//设置窗口的标题
this->setWindowTitle("环境监测系统");

设置固定的窗口大小。

 //设置固定的宽度和高度
 this->setFixedSize(200,300);

设置窗口图标

  //设置窗口图标
    this->setWindowIcon(QIcon("D:\\1.png"));

标准的信号和槽

点击一下b1按钮关闭对象。函数剖析:
信号和槽都是函数,1、信号只有函数声明没有函数定义。
2、槽函数需要声明也需要定义。只是个回调函数。

	//需求 b1 关闭窗口
    //connect (b1,发出信号,this,处理槽函数);
    connect (&b1,&QPushButton::clicked,this,&Widget::close);

更换需求:当按下b1的时候b2的显示内容改变。
槽函数的特性:
/*自定义槽函数
*1、槽函数在Qt5中可以任意成员函数,全局函数,静态函数 lambda表达式(隐式函数)
*2、槽函数需要与信号对应(返回值和参数)
*3、信号是没有返回值的,槽函数的返回值是:void
*4、void mysig(int,double,qstring);
* void mtslot(int double qstring);
*5、槽函数的信号是为了接收信号传过来的数据。
*6、槽函数的参数是不能够大于信号的参数个数,可以少于信号的参数个数。
*7、槽函数可以重载。
*/

功能实现:在widget中添加声明,之后再在widget.cpp中完成函数实现。

自定义信号

更换需求:仅仅显示一个界面。
重新添加一个subwidget.cpp和subwidget.h。在头文集中声明QpushButton,在CPP文件中实现。在主窗口中包含头文件。子窗口初始化代码:

Subwidget::Subwidget(QWidget *parent) : QWidget(parent)
{
    
    b1 = new QPushButton("中腾",this);
    b1->resize(100,100);
    setWindowTitle("软件园窗口");
    resize(400,600);
}

主窗口头文件包含代码:

	QPushButton *b3; //作用显示子窗口
    //子窗口的对象
    Subwidget subW;

主窗口cpp文件包含代码:

//b3显示子窗口Subwidget --subW
    b3 = new QPushButton("软件园",this);
    b3->resize(150,150);
    b3->move(200,200);
   //注意这里是创建的指针类型的b3不需要取地址符。
   connect(b3,&QPushButton::clicked,this,&Widget::slotHindMe);

然后从中腾返回主窗口的实现。要发送一个信号回到主窗口。

Subwidget::Subwidget(QWidget *parent) : QWidget(parent)
{
    
    b1 = new QPushButton("中腾",this);
    b1->resize(100,100);
    setWindowTitle("软件园窗口");
    resize(400,600);
    //给主窗口发送信号
    connect(b1,&QPushButton::clicked,this,&Subwidget::myslot);
}
void Subwidget::myslot()
{
    
    //发送信号
    emit sigSub();
}

在主窗口widget中实现:

connect(&subW,&Subwidget::sigSub,this,&Widget::slotShowMe);
void Widget::slotShowMe()
{
    
        //显示自己
        show();
        //显示软件园
        subW.hide();
}

重载的信号槽

信号槽不仅仅能发送一个信号,可以发送多个信号,发送多个信号的时候要用到函数指针,对多个信号进行重载,其次,还要声明作用域。如果信号和槽发生重载,要定义函数指针显示定义。

void Subwidget::myslot()
{
    
    //发送信号
    emit sigSub();
    emit sigSub(250,"你是250");
}
   connect(b3,&QPushButton::clicked,this,&Widget::slotHindMe);
   void (Subwidget::*MySigSub)()=&Subwidget::sigSub;
   connect(&subW,MySigSub,this,&Widget::slotShowMe);
   void (Subwidget::*MySigPlus)(int ,QString)=&Subwidget::sigSub;
   connect(&subW,MySigPlus,this,&Widget::slotSubMag);

拓展:1、信号可以连接信号
2、一个信号可以连接多个槽函数
3、多个信号可以连接一个槽函数
4、槽函数可以使用lambda表达式

lambda表达式

[=](){}值传递的方式,可以使用到函数外的参数。[&](){}引用外部的地址。[this](){}可以使用当前类的成员变量。[a](){}值传递的方式,可以传递a的值,大括号只能使用a。
使用lambad表达式作为槽函数。

第一天的复习内容

1、创建QT程序

1、一个Qt程序的组成部分:应用程序类,窗口类
2、应用程序类的个数:有且只有一个,QApplication a;
3、如何查看对应的模块:
光标移动到类上,F1
qmake += 模块的名字

2、第一个Qt程序

1>在窗口中添加按钮
类名:QPushButton
设置按钮显示的内容:setText
移动按钮的位置:move
按钮设置父窗口:setParent
设置窗口的大小:resize(),resizeFixed()
2>Qt的坐标体系:
坐标原点:左上角
x轴延伸方向:向右
y轴延伸方向:向下
3>Qt的内存回收机制
满足什么条件不需要用户手动释放内存?
1.从QObject类直接或间接派生。
2.从直接或间接派生出的类,指定父对象。

3、信号和槽

1>.格式:connect(信号发出者对象(指针),&className::clicked,信号接收者对象(指针),&classB::slot);
2>.标准信号槽的使用:
3>.自定义槽函数:
1:返回值void
2:可以重载
3:需要和信号对应,个数<=信号的参数个数
4>.自定义信号
1:返回值void
2:可以重载
3:需要使用一个关键字声明:signals;
4:不需要函数定义
5>.单参数的信号(槽)
1:重载的时候:信号槽发生了重载,需要使用函数指针。
2:Qt4信号槽的使用
SIGNAL(信号的函数名()),SLOT(槽函数名(int,long))
connect 连接 重载过的信号和槽的解决方法。

6>.拓展:
a.信号可以链接信号(参数的对应)。
b.一个信号可以链接多个槽函数
c.多个信号可以链接同一个槽函数
d.槽函数可以使用lambda表达式

4、QMainWindow
	1>.菜单栏
	2>.工具栏
	3>.浮动窗口和核心部件
	4>.状态栏
5、QDialog
	1>.模态对话框
	2>.非模态对话框
	3>.标准对话框和文件对话框

Day_1 课程总结精炼


	Me wo;
	Beauty sweet;//小红
	Beauty sweet1;//小紫
//场景:
1>. 我 看到 美女 之后 ,我直流口水    //自己给自己发信号
connect(&wo,&Me::seeBeauty,&wo,&Me::mouthWatering);
2>.我 调戏 美女 , 美女抽我		//我发信号,其他人接收
connect(&wo,&Me::molestBeauty,&sweet,&Beauty::beatSomebody);
3>.我给两个美女些情书,一个同意,一个拒绝  //槽函数的参数个数<信号的参数个数
//1.信号和槽重载的时候,需要使用到函数指针
//2.同一个信号和槽,可以链接多个槽函数
void (Beauty::*slotAnswer)()=&Beauty::answer;
connect(&wo,&Me::writeLoveLetter,&sweet,slotAnswer);


void (Beauty::*slotAnswer1)(QString)=&Beauty::answer;
connect(&wo,&Me::writeLoveLetter,&sweet,slotAnswer);

4>.我拜托小红把情书给她的双胞胎妹妹小紫,小紫说我只喜欢会Qt的程序猿
//信号链接信号
connect(&wo,&Me::weituoLetter,&sweet1,&Beauty::sendLetter);

connect(&sweet1,&Beauty::sendLetter,&sweet,&Beauty::slotAnswer1);
	

DAY_02

QMainWindow

介绍UI界面,创建UI界面之后,如下:无法改变英文名,点击text输入中文,改变名称。
在这里插入图片描述
在这里插入图片描述

 connect(ui->actionopen,&QAction::triggered,this,[=]()
    {
    
        QString name =  QFileDialog::getOpenFileName(this,"打开文件","D:\\","Image(*.jpg *.png)");
        qDebug() << name;
    });

讲解了浮动窗口的应用,如何使用浮动窗口。设置状态为floating,默认状态为浮动。
下面勾选框设置允许停靠的位置。

1、资源文件的添加

在项目文件上右击添加新文件,选择天机resource file 添加新文件。添加成功后右击,加入前缀和反斜杠。把资源文件夹复制到工程文件夹下面,之后添加资源图片。

在这里插入图片描述在mainwindow.cpp中添加代码如下。

 ui->actionSave_as->setIcon(QIcon(":/IMAGE/3.png"));

即可显示出资源图片:
在这里插入图片描述
如果项目比较大,可以添加不同的前缀来添加文件。

资源文件的更简单的使用方法:左侧选择中标签,之后在资源管理中找到icon,在normal中添加资源中的图片

在这里插入图片描述

2、对话框-QDialog

模态&非模态对话框
非模态对话框:打开之后可以其他界面进行其他操作。
模态对话框:打开之后不可以其他界面进行其他操作。

connect(ui->actionopen,&QAction::triggered,this,[=]()
    {
    
        //显示模态对话框 exec
        QDialog log(this);//定义一个父类对象,表示只有这一个窗口
        log.exec();//阻塞状态。
        QString name =  QFileDialog::getOpenFileName(this,"打开文件","D:\\","Image(*.jpg *.png)");
        qDebug() << name;
    });
    connect(ui->actionsave,&QAction::triggered,this,[=]()
    {
    
        //非模态对话框要保证在完成之前不被析构掉。只有当主窗口关闭之后才会被析构掉。
        QDialog *log =new QDialog(this);
        //显示非模态对话框 show()
        //设置对话框的属性
        log->show(); //非阻塞状态
        log->setAttribute(Qt::WA_DeleteOnClose);//让对话框删除。
        QString name =  QFileDialog::getOpenFileName(this,"打开文件","D:\\","Image(*.jpg *.png)");
        qDebug() << name;
    });

3、QMessageBox

实现包含的头文件 #include
实现代码:

 QMessageBox::about(this,"about","++++++");

实现现象:
在这里插入图片描述
四种消息提示符:
在这里插入图片描述
如果执行了OK之后会出现的界面情况,最后一个参数为默认按钮,添加成功之后的界面,按下回车,按钮会响应回车按键:

 if(QMessageBox::Ok == QMessageBox::critical(this,"error","系统文件错误!!!",QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Cancel))
       {
    
                   //显示模态对话框 exec
                   QDialog log(this);
                   log.exec();//阻塞

       }

4、颜色和字体对话框

所需要包含的头文件:
#include
#include
返回值是QColor 获得颜色对话框。之后打印出红绿蓝的颜色属性。

        QColor color = QColorDialog::getColor();
        qDebug()<<color.red()<<color.green()<<color.blue();

返回值是QFont 获得字体的对话框,之后打印出字体属性(斜体,字体大小,加粗);

       bool ok;
       QFont font = QFontDialog::getFont(&ok,QFont("华文彩云"),this,"我的字体设置");
       if(ok)
       {
    
         qDebug()<<font.family()<<font.italic()<<font.pointSize()<<font.bold();
       }

5、布局

在开始布局之前首先为每一组控件创建一个父窗口。设置完成之后,界面如图所示。
在这里插入图片描述
为窗口设定最大宽度、高度和最小宽度、高度,来让界面固定大小。
在这里插入图片描述
网格布局:让每行每列的对齐,可以显示当行多列,每一列的宽度是相等的。
美化完成之后,选中对话框可以设置最后的间距大小,可以设置和边界的最后距离。
在这里插入图片描述布局的时候,就是布局套布局,一层层布局下去。

6、按钮控件

1–PushButton按钮。
首先拖拽一个Button按钮放在UI界面上,在.cpp文件中,按下F1进入帮助文档,查看帮助文档信息,查看父类,在点击Signals。查看可以使用的信号。

在这里插入图片描述

每个控件放置在界面内一定要布置布局。
信号操作使用的实例:

 connect(ui->radioButton,&QAbstractButton::clicked,this,[=]()
    {
    
        QMessageBox::information(this,"打印正确","hhhh");
    });

单选框和复选框:
在这里插入图片描述
复选框使用示例,打印出控件的状态:

 connect(ui->checkBox,&QCheckBox::stateChanged,this,[=](int state)
    {
    
        qDebug()<<state;
    });

7、控件介绍

在QListWidget:控件中添加图片和文字。

	ui->listWidget->addItem("软件创业园");
    ui->listWidget->addItem(new QListWidgetItem(QIcon("D:\\1.png"),"Lufft"));

效果如下图所示:
在这里插入图片描述
table widget的使用:

 	//1、指定行数
    ui->tableWidget->setRowCount(5);
   //2、指定列数
    ui->tableWidget->setColumnCount(3);
    QStringList list;
    list<<"姓名"<<"性别"<<"年龄";
    ui->tableWidget->setHorizontalHeaderLabels(list);

测试结果:
在这里插入图片描述

滚动条区域:Scroll Area
在这里插入图片描述

Tool Box:
就像QQ列表的使用一样,点击一次按钮,就打开一次列表界面,使用效果如下图所示:
在这里插入图片描述在这里插入图片描述

TabWidget:分开显示界面。
在这里插入图片描述

栈窗口:Stacked Widget
结果如下图所示:通过按键按钮,然后切换不同的界面。与QTabWidget 的区别是:这个控件和按钮是独立的,而QTabWidget是有联系的。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
序号是当前窗口的currentIndex:

 connect(ui->musicBtn,&QPushButton::clicked,this,[=]()
    {
    
        ui->stackedWidget->setCurrentIndex(0);
    });
     connect(ui->otherBtn,&QPushButton::clicked,this,[=]()
    {
    
        ui->stackedWidget->setCurrentIndex(1);
    });
     connect(ui->movieBtn,&QPushButton::clicked,this,[=]()
    {
    
        ui->stackedWidget->setCurrentIndex(2);
    });

Combobox:
下拉框选择123进入电影界面。
在这里插入图片描述

 connect(ui->comboBox,&QComboBox::currentTextChanged ,this,[=]()
     {
    
         ui->stackedWidget->setCurrentIndex(2);
     });

Qlabel类

在Qt中,QPixmap代表的是一张图片。如何插入图片呢?
首先添加资源文件,在UI界面添加lable控件,之后添加代码:

ui->image->setPixmap(QPixmap(":/IMAGE/3.png"));

结果显示如下:
在这里插入图片描述

为了显示动图:要在头文件添加 #include,之后添加如下代码:

	 QMovie* movie = new QMovie(":/IMAGE/4.gif");
     ui->image->setMovie(movie);
     movie->start();

显示动态小猫咪如下图所示:
在这里插入图片描述

DAY_03

自定义控件:封装一个控件的时候,先对疯转搞的控件进行处理。
首先添加一个文件,在文件中创建一部分控件。紧接着在主窗口把主窗口提升为之前设置的子窗口,默认选择全局包含,这样在之后的创建过程中,其他控件也可以提升为之前的子控件。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在smallwidget中先对里面的控件进行处理,添加如下代码:

  void(QSpinBox::*sigValueChange)(int) = &QSpinBox::valueChanged;
   connect(ui->spinBox,sigValueChange,ui->horizontalSlider,&QSlider::setValue;
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

实现功能数字变化,滑块也变化。滑块变化,数字也变化。
在这里插入图片描述

小技巧:在使用控件的时候,做错了,重新更改边框,在widget右击变形为。。。

事件

在项目中添加新的C++文件,在C++文件上继承Qlabel,之后重写被保护的虚函数,虚函数的查看,在Qlabel中按下F1。QLabel是从QWidget中派生的。
在这里插入图片描述

在这里插入图片描述
实际上这些事件都是回调函数,我们只需要对这些函数进行功能实现即可。

QString 字符串的拼接

//字符串的拼接 QString().arg()
   //%1,%2,%3 --占位符
    QString str = QString("%3,%2,%1").arg(1).arg("123").arg('a');

拼接后的结果如图所示:
在这里插入图片描述
鼠标事件的代码:

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


// QWidget 默认不追踪鼠标事件的
Mylabel::Mylabel(QWidget *parent) : QLabel(parent)
{
    
       //设置窗口追踪鼠标键
    this->setMouseTracking(true);
}
//进入和离开都是在边界的那一瞬间完成的。
//鼠标进入
void Mylabel::enterEvent(QEvent *)
{
    
    setText("鼠标进入");
}
//鼠标离开
void Mylabel::leaveEvent(QEvent *)
{
    
    setText("鼠标离开~");
}
//鼠标按下
void Mylabel::mousePressEvent(QMouseEvent *ev)
{
    
   //字符串的拼接 QString().arg()
   //%1,%2,%3 --占位符
    QString btn;
    if(ev->button()==Qt::LeftButton)
    {
    
        btn = "LeftButton";

    }
    else if(ev->button()==Qt::RightButton)
    {
    
        btn = "RightButton";
    }
    else if(ev->button()==Qt::MidButton)
    {
    
        btn = "MidButton";
    }
    QString str = QString("MousePress[%3]:(%1,%2)").arg(ev->x()).arg(ev->y()).arg(btn);
    setText(str);

}
//鼠标释放 这是个瞬间的状态
void Mylabel::mouseReleaseEvent(QMouseEvent *ev)
{
    
    //字符串的拼接 QString().arg()
    //%1,%2,%3 --占位符
     QString btn;
     if(ev->button()==Qt::LeftButton)
     {
    
         btn = "LeftButton";

     }
     else if(ev->button()==Qt::RightButton)
     {
    
         btn = "RightButton";
     }
     else if(ev->button()==Qt::MidButton)
     {
    
         btn = "MidButton";
     }
     QString str = QString("MouseRelease[%3]:(%1,%2)").arg(ev->x()).arg(ev->y()).arg(btn);
     setText(str);
}
//鼠标移动    移动操作比较特殊 要按位与操作才能捕捉鼠标对象。这是个持续的状态。
void Mylabel::mouseMoveEvent(QMouseEvent *ev)
{
    
    //字符串的拼接 QString().arg()
    //%1,%2,%3 --占位符
     QString btn;
     if(ev->buttons()&Qt::LeftButton)
     {
    
         btn = "LeftButton";
 
     }
     else if(ev->buttons()&Qt::RightButton)
     {
    
         btn = "RightButton";
     }
     else if(ev->buttons()&Qt::MidButton)
     {
    
         btn = "MidButton";
     }
     QString str = QString("MousePress[%3]:(%1,%2)").arg(ev->x()).arg(ev->y()).arg(btn);
     setText(str);
}

定时器

使用方法一:
首先包含timerevent 的头文件,其次在窗口的构造函数中启动定时器。id = startTimer(100);参数100代表100ms触发一次。添加代码如下 实现启动定时器。当num>=100的时候关闭定时器。

 //每触发一次定时器,就进入一次函数
        static int num = 0;
        QString str = QString("%1:%2").arg("Time out").arg(num++);
        if(num >= 100)
        {
    
            //关闭定时器
            killTimer(id);
        }

在这里插入图片描述

使用方法2:
首先包含头文件QTimer,在构造函数中创建一个对象,创建对象完成之后,mylabel构造函数中添加如下代码,启动定时器:

//第二种定时器的使用方式
    QTimer *timer = new QTimer(this);
    timer->start(100);

    connect(timer,&QTimer::timeout,this,[=]()
    {
    
        static int number=0;
        QString str = QString("%1:%2").arg("Time out").arg(number++);
        this->setText(str);
    });

在这里插入图片描述

QPrinter

首先在widget.cpp中包含头文件“#include ”,如果我们想在当前窗口绘图的话,我们需要重载一个虚函数。

protected:
    /*
    * 1-回调函数
    * 2-此函数不需要用户调用,在刷新的时候回自动调用
    *       1.窗口显示的试试
    *       2.最大化,最小化
    *       3.窗口被遮挡重现显示的试试
    *       4.用户强制刷新的时候
    * 3-如果想使用画家类画图,操作必须在paintevent完成
    */
     void paintEvent(QPaintEvent *event);
void Widget::paintEvent(QPaintEvent *)
{
    
    //创建画家类对象
    QPainter p(this);  //指定绘图设备,不是父对象
    // 创建新画笔  -- 轮廓
    QPen pen;
    pen.setColor(/*Qt::green*/QColor(0,255,0));
    pen.setWidth(10);
    pen.setStyle(Qt::DotLine);
    //闭合区域使用画刷 -- 填充闭合区域
    //QBrush brush(Qt::blue);
    QBrush brush(QPixmap(":/IMAGE/3.png"));
    p.setBrush(brush);
    //将新画笔设置给画家类
    p.setPen(pen);
    //画背景图
    p.drawPixmap(0,0,QPixmap(":/IMAGE/3.png"));
    //画直线
    p.drawLine(QPoint(100,100),QPoint(300,500));
    //画椭圆
    p.drawEllipse(QPoint(200,100),100,50);
    //画矩形
    p.drawRect(400,200,200,200);
    //写字
    QFont font("华文彩云",48,75,true); //定义字体类
    p.setFont(font);//调用字体类
    p.drawText(100,400,"我是你哥哥");
}

强制刷新界面

首先定义变量x;在UI界面添加按键,添加按键之后,创建槽函数。

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

        //刷新窗口
        update();//系统调用paintEvent

    });

再完成槽函数之后,在 void Widget::paintEvent(QPaintEvent *)添加如下代码。

 int width = this->width();
    int height = this->height();
    x+=5;
    //提供笑脸
    if(x>this->width())
    {
    
        x=20;
    }
    p.drawPixmap(x,100,QPixmap(":/IMAGE/1.png"));

单击按键移动可以实现图片一直向右移动,即使跑出界面,也可以再进入界面。
在这里插入图片描述

绘图设备

在widget添加如下代码:

 ui->setupUi(this);
    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.jpg");

    //指定绘图设备 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.jpg");
    
    //在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.jpg");

显示picture

void Widget::paintEvent(QPaintEvent *event)
{
    
    QPainter p(this);
    QPicture pic;
    pic.load("D:\\mypic.jpg");
    p.drawPicture(100,100,pic);

}

实现画图功能

在这里插入图片描述

不规则窗口

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QMouseEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    
    ui->setupUi(this);
    //加载图片
    pix.load("D:\\3.png");
    //去掉边框函数
    this->setWindowFlag(Qt::FramelessWindowHint);
    //设置背景透明函数
    this->setAttribute(Qt::WA_TranslucentBackground);
}
Widget::~Widget()
{
    
    delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
    
    //在窗口中把图片画出来
    QPainter p(this);
    p.drawPixmap(0,0,pix);

}
void Widget::mousePressEvent(QMouseEvent *event)
{
    
    if(event->button() == Qt::LeftButton)
    {
    
       //求差值  左键按下的点减去窗口左上角的点的坐标
       pq = event->globalPos() - this->frameGeometry().topLeft();

    }
    else if(event->button() == Qt::RightButton)
    {
    
        // close window
        this->close();
    }
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
    
    //move x,y 使用屏幕坐标系
    //e->x(),e->y()  窗口的坐标系 Widget
    this->move(e->globalPos() - pq);

}

实现用鼠标移动图标功能,单击右键实现关闭图片功能。
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_46152793/article/details/118496597

智能推荐

Java8 parallelStream——共享线程池对性能解析_jdk8 parallelstream 性能-程序员宅基地

文章浏览阅读3.3k次,点赞2次,收藏8次。最近做压测中发现一个应用中cpu过高,导致接口超时rt情况有些不大稳定,jstack打印线程一直在parallelStream相关的代码出进行计算。故对parallelStream相关做一下研究,找一下优化方法。java8并行流parallelStream,相信很多人都喜欢用,特别方便简单。但是有多少人真正知道里面采用的共享线程池对密集型任务,高并发下的性能影响呢可能你的一个应用里面..._jdk8 parallelstream 性能

C++ 11 创建和使用 unique_ptr_unique_ptr创建空节点-程序员宅基地

文章浏览阅读292次。https://www.cnblogs.com/DswCnblog/p/5628195.htmlunique_ptr 不共享它的指针。它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法。只能移动unique_ptr。这意味着,内存资源所有权将转移到另一 unique_ptr,并且原始 unique_ptr 不再拥有此资源。我们建议..._unique_ptr创建空节点

NetCoreAPI配置全局路由_selector.attributeroutemodel.template-程序员宅基地

文章浏览阅读853次。1:新增类:RouteConvention,继承自IApplicationModelConvention/// <summary> /// 全局路由前缀配置 /// </summary> public class RouteConvention : IApplicationModelConvention { /// <summary> /// 定义一个路由前缀变量 /// </su_selector.attributeroutemodel.template

算 数-程序员宅基地

文章浏览阅读64次。从woody那里copy一段最简的fib代码[code="ruby"]x,y = 0,1 Array.new(10) {|i| [0,1].include?(i) ? 1 : (x,y = y,x+y)&&(x+y) } [/code]生成了这么多,太多了,中途终止了,不知道多少条。[code="ruby"] 1, 1, 2, ..._359579325206583560961765665172189099052367214309267232255589801

Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!-程序员宅基地

文章浏览阅读280次。本文原题“从实践角度重新理解BIO和NIO”,原文由Object分享,为了更好的内容表现力,收录时有改动。1、引言这段时间自己在看一些Java中BIO和NIO之类的东西,也看了很多博客,发现各种关于NIO的理论概念说的天花乱坠头头是道,可以说是非常的完整,但是整个看下来之后,发现自己对NIO还是一知半解、一脸蒙逼的状态(请原谅我太笨)。基于以上原因,..._java bio粘包处理

Python3.9环境搭建RobotFramework_python-3.9.9-amd64用那个版本ride-程序员宅基地

文章浏览阅读9k次,点赞2次,收藏12次。Robot Framework是一个基于Python的,可扩展的关键字驱动的测试自动化框架,用于端到端验收测试和验收测试驱动开发(ATDD)。_python-3.9.9-amd64用那个版本ride

随便推点

Hbase相关操作_hbase 查询-程序员宅基地

文章浏览阅读2.4k次。1.进入shellhbase(main):003:0>hbase shell2.查看所有表hbase(main):003:0> list3.根据rowKey查询某个记录hbase(main):003:0>get '表名','rowKey'4.常用过滤器过滤方式是通过value过滤,匹配出value含7259的数据。scan 'buss_surface', FILTER=>"ValueFilter(=,'substring:7259')"过滤方式是通_hbase 查询

噪声:Practical Poissonian-Gaussian noise modeling and fitting for single-image raw-data-程序员宅基地

文章浏览阅读2k次,点赞4次,收藏16次。Practical Poissonian-Gaussian noise modeling and fitting for single-image raw-data文章目录Practical Poissonian-Gaussian noise modeling and fitting for single-image raw-dataPoissonian-Gaussian ModelingThe Noise Profile AlgorithmWavelet domain analysisSegmentat_practical poissonian-gaussian noise modeling and fitting for single-image ra

计算机开机最快设置,w7提高开机速度如何操作_win7电脑怎么开机更快-程序员宅基地

文章浏览阅读4k次。由于win7电脑使用时间过长或者存放时间久了,难免会出现硬件各方面的老化或者堆积了大量的垃圾,因此就会导致电脑开机时的速度有所降低,对此有些用户就想,在不更换硬件的条件下,有没有方法能够提高一下开机速度,那么win7电脑提高开机速度如何操作呢?这里小编就来告诉大家win7电脑开机更快操作步骤。具体方法:1、在任意界面按下:windows键+R,然后在框内输入msconfig,点确定2、然后选择“启..._如何提高w7系统的开机速度

1688API接口:item_search - 按关键字搜索商品_1688 一件代发 api-程序员宅基地

文章浏览阅读672次。今天分享的是1688平台API,item_search - 按关键字搜索商品接口1688的API开发接口,我们需要做下面几件事情。1)开放平台注册开发者账号;2)然后为每个1688应用注册一个应用程序键(App Key) ;3)下载1688API的SDK并掌握基本的API基础知识和调用;4)利用SDK接口和对象,传入AppKey或者必要的时候获取并传入SessionKey来进行程序开发;5)利用1688平台的文档中心和API测试工具,对接口进行测试。从而了解返回信息,方便程序获取1688_1688 一件代发 api

vue-property-decorator使用指南_vue-property-decorator emit update-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏12次。在Vue中使用TypeScript时,非常好用的一个库,使用装饰器来简化书写。一、安装npmi-Svue-property-decorator@Prop @PropSync @Provide @Model @Watch @Inject @Provide @Emit @Component(provided byvue-class-component) Mixins(the helper function namedmixinsprovided byvue-cla..._vue-property-decorator emit update

(七)用ChartDirector绘制实时图表-程序员宅基地

文章浏览阅读467次。本示例演示如何用Web图表控件 ChartDirector 绘制一个配置有刷新率的实时图表。在本例中,由一个计时器驱动的随机数生成器生成新的数据值,新产生的值会转换到数据数组中,然后显示在图表上。图表由一个秒表进行更新,这样图表的刷新率可独立于数据率。此外,这个图表支持暂停以方便用户查看,但是后台的数据仍然在继续更新。图表刷新计时器调用CChartViewer.update..._c++ chartdirect updateviewport