QT 之Qwidget的极致使用!!!

目录

Qwidget总介

PyQT的Qwidget的使用

Qwidget的另类用法

 Qwidget C++示例

Qwidget总介

        QWidget是Qt中所有用户界面对象的基类,主要用于界面显示。QWidget的底层机制是由QPaintDevice和QPaintEngine组成的。而QPaintDevice是一个抽象类,提供了绘制设备的接口,QPaintEngine也是一个抽象类,提供了绘制引擎的接口。所以Qwidget是主要用于界面显示和事件处理方面的,具体作用如下所示:

  • 它可以作为一个顶层窗口,也可以作为一个子窗口,通过设置父对象和窗口标识来控制。
  • 已可以设置各种属性,如大小、位置、字体、样式表、工具提示、窗口图标、窗口标题等。
  • 已可以接收鼠标、键盘和其他窗口事件,并根据事件类型调用相应的槽函数。
  • 它可以创建和使用信号和槽机制,实现对象之间的通信和交互。
  • 它可以作为其他控件的基类,如按钮、文本框、单选框等,实现更多的功能和效果。

        其中,QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间。QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。

        那么我们接着来说一说QWidget的子类,QWidget有很多子类,如QPushButton、QLabel、QLineEdit、QTextEdit、QCheckBox、QRadioButton等等。这些咱们都可以在如下的左边工具栏找到。

这里是QT关于QWidget的官方的文档说明

一般C++里面只需要拖动控件就能实现简单的界面设计,在这里我主要提一哈python里面的QT怎么使用Qwidget。

使用QWidget创建GUI界面的步骤如下:https://zhuanlan.zhihu.com/p/434909621

PyQT的Qwidget的使用

  1. 创建一个QWidget对象,它是pyqt5中所有的图形用户界面的基类。
  2. 设置窗口标题、大小和位置。
  3. 调用QWidget对象的show()方法将创建的窗口显示出来。
  4. 最后,调用应用程序对象的exec_()方法来运行程序的主循环,并使用sys.exit()方法确保程序能够完美的退出。

这里是一个简单的,用pyqt写的一个登录界面的代码:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton

class Login(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Login')
        self.resize(300, 150)

        self.username_label = QLabel('Username:', self)
        self.username_label.move(50, 30)
        self.username_input = QLineEdit(self)
        self.username_input.move(120, 30)

        self.password_label = QLabel('Password:', self)
        self.password_label.move(50, 70)
        self.password_input = QLineEdit(self)
        self.password_input.setEchoMode(QLineEdit.Password)
        self.password_input.move(120, 70)

        self.login_button = QPushButton('Login', self)
        self.login_button.move(120, 110)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    login = Login()
    login.show()
    sys.exit(app.exec_())

Qwidget的另类用法

        另外,由于某些工程项目的需要,我们往往会对控件进行提升,比如这里的QPushbutton

 我们可以将其提升到其他类型,诸如以下的比如QMenu

        另外Qwidget还提供了互相调用的且实例化的路径,就比如说咱们要从一个软件页面跳转到另一个软件页面的时候,就可以将通过新建一个QWidget页面来实现,原来的Qmainwindow也是继承的Qwidget,所以主页面能调动子页面。

 就比如说这里:我设计了两个页面,一个是登陆界面,一个是主程序页面

        我们可以自定义一个从Qwidget继承的类,重写其paintEventO事件,利用Qt的绘图功能绘制组件外观并实现需要的其他功能。你可以在QtDesigner中将一个Qwidget提升为你自定义的类,或者其他的类,如QMainWindow 、QDialog等,以便使用更多的属性和方法。也可以使用样式表、信号和槽、事件过滤器等技术来改变Qwidge的外观和行为。

如果要重写paintEvent,我们需要以下几个步骤:

  • 在你的Qwidget子类的头文件中声明一个虚函数槽void paintEvent(QPaintEvent *event)。
  • 在你的Qwidget子类的源文件中定义这个函数,并在函数体中实例化一个QPainter对象,指定this为绘图设备。
  • 使用QPainter对象的各种方法来设置画笔、画刷、字体等属性,并调用drawXXX()函数来绘制你想要的内容。
  • 如果需要,你还可以使用setRenderHint()函数来设置抗锯齿等效果,或者使用translate()、save()、restore()等函数来移动或保存画家状态。

 Qwidget C++示例

        这里是我的登录界面的代码:

#include "mywindows.h"
#include "ui_mywindows.h"
#include <QDebug>
#pragma execution_character_set("utf-8")//加上这个后,下面代码中使用中文就不会报错
#include "opencv_basic.h"
#include "ui_opencv_basic.h"
#include <QMessageBox>

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

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

/*
        //输入信号,触发方式,执行任务
        this->w=new enter;//实例化页面二
        connect(ui->pushButton,&QPushButton::clicked,[=]{
            this->hide();//隐藏当前页面;还没有释放
            this->w->show();//显示页面2
        });
*/

void mywindows::on_pushButton_clicked()
{
    QString username= ui->lineEdit->text();
    QString password= ui->lineEdit_2->text();
    if(username==QString ("1") && password==QString("1"))//设置密码
    {
        qDebug() <<u8"登录成功";
       this->A=new opencv_basic;//实例化页面二
        this->hide();//隐藏当前页面;还没有释放
        this->A->show();//显示页面2
    }
    else
    {
        qDebug() <<u8"登录失败" ;
        QWidget *parent=new QWidget;
        QMessageBox::information(parent,u8"提示",u8"密码输入错误",u8"确定",u8"取消");
    }
}

        这是我主程序的代码,主要是一个简单的opencv灰度变换,还有文件夹创建,选择等常用操作。

#include "opencv_basic.h"
#include "ui_opencv_basic.h"
#include <QDir>
#include <QDebug>
#include <iostream>
#include <QString>//字符串转换操作
#include <QMessageBox>//添加警告框
#include <QFileDialog>//添加自选文件夹
#pragma execution_character_set("utf-8")

opencv_basic::opencv_basic(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::opencv_basic)
{
    ui->setupUi(this);
    //on_pushButton_clicked();
}

QString path = "F:/test_images/";

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

int i=0;


//读取绝对路径下的第一张图片的路径并且返回
std::string file_read(int &i)
{
/*可以读取绝对路径下的第一张图片*/
//获取应用程序可执行文件的文件路径:    //QDir::currentPath();//获取当前工程目录
QDir dir(path);
QStringList filename ;
filename << "*.png" << "*.jpg";//可叠加,可使用通配符筛选
QStringList results;
results = dir.entryList(filename,QDir::Files | QDir::Readable,QDir::Name);

//增加一个判定
int a=results.size();
//qDebug()<<a;打印出来有几张图片
qDebug()<<"i"<<i;
if(i+1>a)
{
    QWidget *parent=new QWidget;
    QMessageBox::information(parent,u8"提示",u8"图片读取错误",u8"确定",u8"取消");
    qDebug()<<i;
    i--;//回到上一张
}

//qDebug()<<results;//results里就是获取的所有文件名了,这里的qdebug是将运行的路径进行输出
QString st=results.at(i);
QString rt=path;
qDebug()<<rt+st;
std::string str1=rt.toStdString();
std::string str2 = st.toStdString();
std::string str3=str1+str2;
return str3;
}

//这个函数是显示原图,值得注意的是,在转化8位3通道的图像时,OpenCV和QImage使用的红蓝通道是相反的,需要使用rgbSwapped方法互换一下
void opencv_basic::on_pushButton_clicked()
{
    std::string str3=file_read(i);
    cv::Mat srcimage=cv::imread(str3);
    /*--------------------------------------------------------*/
   // cv::Mat srcimage=cv::imread("../opencv_basic/2.jpg");
    //cv::imshow("原始图片",src);R
    //Mat转QImage 像素   oldlabel放置原图
       QImage disimage = QImage(srcimage.data,srcimage.cols,srcimage.rows,srcimage.cols*srcimage.channels(),QImage::Format_RGB888);
       QImage imag =disimage.rgbSwapped();//将红蓝通道对换
       disimage = imag.scaled(ui->label->width(),ui->label->height(),Qt::KeepAspectRatio);
       ui->label->setPixmap(QPixmap::fromImage(disimage));
}

//这个函数是对图像进行模糊化和灰度化
void opencv_basic::on_pushButton_2_clicked()
{
    std::string str3=file_read(i);
    cv::Mat srcimage=cv::imread(str3);
    //cv::imshow("原始图片",src);
    cv::Mat img_resize,img_Gray,img_blur;
    //cv::resize(srcimage, img_resize,cv::Size(), 0.5, 0.5);
    cvtColor(srcimage, img_Gray, cv::COLOR_BGR2GRAY);
    GaussianBlur(img_Gray, img_blur, cv::Size(3, 3), -1, -1);//高斯模糊化

    //Mat转QImage 像素   oldlabel放置原图
      // QImage disimage = QImage(img_blur.data,img_blur.cols,img_blur.rows,img_blur.cols*img_blur.channels(),QImage::Format_Grayscale8);
    //Mat转QImage 像素   oldlabel放置灰度图
    QImage disimage = QImage(img_blur.data,img_blur.cols,img_blur.rows,img_blur.cols*img_blur.channels(),QImage::Format_Grayscale8);
    ui->label_2->setPixmap(QPixmap::fromImage(disimage.scaled(ui->label_2->width(),ui->label_2->height(),Qt::KeepAspectRatio)));//,Qt::KeepAspectRatio在后面加上这个就可以保证图片不变形
}

//下一张的按键
void opencv_basic::on_pushButton_4_clicked()
{
    i++;
    file_read(i);
}

//上一张的按键
void opencv_basic::on_pushButton_5_clicked()
{
    i--;
    if(i<=0)
    {
        i=0;
    }
    file_read(i);
}

//增加一个警告框用来提示是否存在文件夹,如果没有就创建
void opencv_basic::on_pushButton_3_clicked()
{
       QDir *temp = new QDir;
       bool exist = temp->exists("F:/test_images");
       if(exist)
        {// QMessageBox::warning(this,"创建文件夹","文件夹已经存在!");//会显示中文乱码
          QMessageBox::information(this,u8"提示",u8"创建成功",u8"确定",u8"取消");
       }
       else
       {
           bool ok = temp->mkdir("F:/test_images");
           if( ok )
              // QMessageBox::warning(this,"创建文件夹","文件夹创建成功!");
           QMessageBox::information(this,u8"提示",u8"创建失败!",u8"确定",u8"取消");
       }

}

void opencv_basic::on_action_triggered()
{
    path = QFileDialog::getExistingDirectory(this,"请选择要打开文件路径","./");
    qDebug()<<"filename : "<<path;
}

具体详情可以参考我的这篇博客

QT与Opencv的联合应用_qt联合opencv_Helloorld_1的博客-CSDN博客

以上就是我目前对Qwidget的理解!!!

猜你喜欢

转载自blog.csdn.net/Helloorld_1/article/details/131951689