Qt实现简单的漫游器

这篇具有很好参考价值的文章主要介绍了Qt实现简单的漫游器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Qt的OpenGL窗口

 Qt主要是使用QOpenGLWidget来实现opengl的功能。
 QOpenGLWidget 提供了三个便捷的虚函数,可以重载,用来重新实现典型的OpenGL任务:

  • paintGL:渲染OpenGL场景。widget 需要更新时调用。
  • resizeGL:设置OpenGL视口、投影等。widget 调整大小(或首次显示)时调用。
  • initializeGL:设置OpenGL资源和状态。第一次调用 resizeGL() / paintGL() 之前调用一次。
  • 如果需要从paintGL()以外的位置触发重新绘制(典型示例是使用计时器设置场景动画),则应调用widget的update()函数来安排更新。
  • 调用paintGL()、resizeGL()或initializeGL()时,widget 的OpenGL呈现上下文将变为当前。如果需要从其他位置(例如,在 widget 的构造函数或自己的绘制函数中)调用标准OpenGL API函数,则必须首先调用makeCurrent()。
  • QOpenGLFunctions_X_X_Core 提供OpenGL X.X版本核心模式的所有功能。是对OpenGL函数的封装:
  • initializeOpenGLFunctions:初始化OpenGL函数,将Qt里的函数指针指向显卡的函数。
#include <QOpenGLWidget> 
#include <QOpenGLFunctions_3_3_Core> class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core 
{ 
Q_OBJECT 
public: 
explicit MyOpenGLWidget (QWidget *parent = nullptr); 
protected: 
virtual void initializeGL(); 
virtual void resizeGL(int w, int h); 
virtual void paintGL(); 
};
void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
}
void MyOpenGLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}
void MyOpenGLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

Qt实现简单的漫游器,qt,OpenGL,qt,开发语言

以上是最简单的实现版本。

GLSL的实现

 由于是最简单的漫游器,所以我们实现的版本只需要一个顶点着色器和一个片段着色器即可。
shapes.vert

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;

out vec2 texCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;


void main(){
    gl_Position = projection * view * model * vec4(aPos, 1.0f);
    texCoord = aTexCoord;
}

shapes.frag

#version 330 core
out vec4 FragColor;
in vec2 texCoord;

uniform sampler2D texturewall;
uniform sampler2D texturesmile;
uniform sampler2D textureSmall;

uniform float ratio;
void main(){
    FragColor = mix(texture(texturewall,texCoord),texture(texturesmile,texCoord),ratio);
}

摄像机类的实现

 这边实现了一个可以对模型进行上下左右移动,移动视角,放大缩小的操作。
摄像机类初始化了几个变量

// 默认值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;

偏航角默认为90度,灵敏度主要用于控制鼠标移动时视角的变化量。

#ifndef CAMERA_H
#define CAMERA_H


#include<QMatrix4x4>

#include <vector>

// 移动方向枚举量. 是一种抽象,以避开特定于窗口系统的输入方法
// 我们这里是WSAD
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT
};

// 默认值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;


// 一个抽象的camera类,用于处理输入并计算相应的Euler角度、向量和矩阵,以便在OpenGL中使用
class Camera
{
public:
    // camera Attributes
    QVector3D Position;
    QVector3D Front;
    QVector3D Up;
    QVector3D Right;
    QVector3D WorldUp;
    // euler Angles
    float Yaw;
    float Pitch;
    // camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // constructor with vectors
    Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // constructor with scalar values
    Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = QVector3D(posX, posY, posZ);
        WorldUp = QVector3D(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // returns the view matrix calculated using Euler Angles and the LookAt Matrix
    QMatrix4x4 GetViewMatrix()
    {
        QMatrix4x4 theMatrix;
        theMatrix.lookAt(Position, Position + Front, Up);
        return theMatrix;
    }

    // 处理从任何类似键盘的输入系统接收的输入。接受摄像机定义枚举形式的输入参数(从窗口系统中提取)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
    }

    // 处理从鼠标输入系统接收的输入。需要x和y方向上的偏移值。
    void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true)
    {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw   += xoffset;
        Pitch += yoffset;

        // 确保当投球超出边界时,屏幕不会翻转
        if (constrainPitch)
        {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // 使用更新的Euler角度更新前、右和上矢量
        updateCameraVectors();
    }

    // 处理从鼠标滚轮事件接收的输入。仅需要在垂直车轮轴上输入
    void ProcessMouseScroll(float yoffset)
    {
        Zoom -= (float)yoffset;
        if (Zoom < 1.0f)
            Zoom = 1.0f;
        if (Zoom > 75.0f)
            Zoom = 75.0f;
    }

private:
    // 根据相机的(更新的)Euler角度计算前矢量
    void updateCameraVectors()
    {
        // calculate the new Front vector
        float PI=3.1415926;
        QVector3D front;
        front.setX(cos(Yaw*PI/180.0) * cos(Pitch*PI/180.0));
        front.setY( sin(Pitch*PI/180.0));
        front.setZ(sin(Yaw*PI/180.0) * cos(Pitch*PI/180.0));
        front.normalize();
        Front = front;
        // also re-calculate the Right and Up vector
        Right = QVector3D::crossProduct(Front, WorldUp);
        // 标准化向量,因为向上或向下看得越多,向量的长度就越接近0,这会导致移动速度变慢。
        Right.normalize();
        Up    = QVector3D::crossProduct(Right, Front);
        Up.normalize();
    }
};
#endif

简单的漫游器

 漫游器的实现主要是通过Qt的窗口事件触发后将触发产生的位置偏量给摄像机类进行计算,从摄像机类中得到视图矩阵将模型的位置进行改变。
myopenglwidget.h


#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H


#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
#include <QElapsedTimer>
#include "camera.h"

class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    enum Shape
    {
        None,
        Circle,
        Rect,
        Triangle
    };
    explicit MyOpenGLWidget(QWidget *parent = nullptr);
    ~MyOpenGLWidget();

    void DrawShape(Shape shape);
    void setWireFrameMode(bool enterWireframe);
    void onTimeout();
protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();
signals:
private:
    Shape m_shape;
    QOpenGLShaderProgram shaderProgram;
    QOpenGLTexture *textureWall;
    QOpenGLTexture *textureSmile;
    QOpenGLTexture *textureSmall;
    QTimer *m_timer;
    QElapsedTimer m_time;

    Camera m_camera;

    // QWidget interface
protected:
    void keyPressEvent(QKeyEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;
};

#endif // MYOPENGLWIDGET_H

myopenglwidget.cpp

#include "myopenglwidget.h"
#include <QImage>
#include <QKeyEvent>

float vertices[] = {
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
    0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,

    -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
    -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,

    -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
    -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
    0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

    -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
    0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
    0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
    0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
    -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,

    -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
    -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
    -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};

QVector<QVector3D> cubePositions= {
    QVector3D( 0.0f, 0.0f, 0.0f),
    QVector3D( 2.0f, 5.0f, -15.0f),
    QVector3D(-1.5f, -2.2f, -2.5f),
    QVector3D(-3.8f, -2.0f, -12.3f),
    QVector3D( 2.4f, -0.4f, -3.5f),
    QVector3D(-1.7f, 3.0f, -7.5f),
    QVector3D( 1.3f, -2.0f, -2.5f),
    QVector3D( 1.5f, 2.0f, -2.5f),
    QVector3D( 1.5f, 0.2f, -1.5f),
    QVector3D(-1.3f, 1.0f, -1.5f)
};

#define TIMEOUT 100

unsigned int indices[] = { // note that we start from 0!
    0, 1, 3, // first triangle
    1, 2, 3 // second triangle
};

unsigned int VBO, VAO ,EBO;

float ratio = 0.5;
QPoint deltaPos;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
    : QOpenGLWidget{parent}
{
    setFocusPolicy(Qt::StrongFocus);
    setMouseTracking(true);

    m_timer = new QTimer(this);
    connect(m_timer,&QTimer::timeout,this,&MyOpenGLWidget::onTimeout);
    m_timer->start(TIMEOUT);
    m_time.start();

    m_camera.Position = QVector3D(0.0,0.0,3.0);
}

MyOpenGLWidget::~MyOpenGLWidget()
{
    if(!isValid()) return;
    makeCurrent();
    glDeleteBuffers(1,&VBO);
    glDeleteBuffers(1,&EBO);
    glDeleteVertexArrays(1,&VAO);
    doneCurrent();
}

void MyOpenGLWidget::DrawShape(Shape shape)
{
    m_shape=shape;
    update();
}

void MyOpenGLWidget::setWireFrameMode(bool enterWireframe)
{
    makeCurrent();
    if(enterWireframe)
        glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    else
        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    update();
    doneCurrent();
}

void MyOpenGLWidget::onTimeout()
{
    update();
}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    //创建VBO和VAO对象,并赋予ID
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);

    //绑定VAO和VBO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)0);
    //开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)(3*sizeof(float)));
    //开启VAO管理的第三个属性值
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER,0);

    bool success;
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":Shaders/shapes.vert");
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":Shaders/shapes.frag");
    success = shaderProgram.link();
    if(!success)
    {
        qDebug()<<"Error:"<<shaderProgram.log();
    }

    shaderProgram.bind();
    shaderProgram.setUniformValue("ratio",ratio);
    shaderProgram.setUniformValue("texturewall",0);
    shaderProgram.setUniformValue("texturesmile",1);
    shaderProgram.setUniformValue("textureSmall",2);

    unsigned int EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    textureWall = new QOpenGLTexture(QImage(":Images/images/wall.jpg").mirrored());
    textureSmile = new QOpenGLTexture(QImage(":Images/images/awesomeface.png").mirrored());
    textureSmall = new QOpenGLTexture(QImage(":Images/images/small.png").mirrored());
    glBindVertexArray(0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}

void MyOpenGLWidget::paintGL()
{
    QMatrix4x4 model;
    QMatrix4x4 view;
    QMatrix4x4 projection;

    view=m_camera.GetViewMatrix();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderProgram.bind();
    projection.perspective(m_camera.Zoom,(float)width()/(height()),0.1,100.0);
    shaderProgram.setUniformValue("projection", projection);
    shaderProgram.setUniformValue("view", view);

    glBindVertexArray(VAO);
    //glDrawArrays(GL_TRIANGLES, 0, 3);
    switch(m_shape)
    {
    case Rect:
        textureWall->bind(0);
        textureSmile->bind(1);
        textureSmall->bind(2);

        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


        foreach (auto item, cubePositions)
        {
            model.setToIdentity();
            model.translate(item);

            shaderProgram.setUniformValue("model", model);
            glDrawArrays(GL_TRIANGLES,0,36);
        }
        break;
    case None:
        break;
    case Triangle:
        break;
    case Circle:
        break;
    }

}

void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{
    float deltatime=TIMEOUT / 1000.0;
    switch(event->key())
    {
    case Qt::Key_Up:ratio += 0.1;break;
    case Qt::Key_Down:ratio -= 0.1;break;
    case Qt::Key_W: m_camera.ProcessKeyboard(FORWARD,deltatime);break;
    case Qt::Key_S: m_camera.ProcessKeyboard(BACKWARD,deltatime);break;
    case Qt::Key_D: m_camera.ProcessKeyboard(RIGHT,deltatime);break;
    case Qt::Key_A: m_camera.ProcessKeyboard(LEFT,deltatime);break;
    }

    if(ratio > 1) ratio = 1;
    if(ratio < 0) ratio = 0;

    makeCurrent();
    shaderProgram.bind();
    shaderProgram.setUniformValue("ratio",ratio);
    update();
    doneCurrent();
}

void MyOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    static QPoint lastPos(width()/2,height()/2);
    auto currentPos=event->pos();
    deltaPos=currentPos-lastPos;
    lastPos=currentPos;

    m_camera.ProcessMouseMovement(deltaPos.x(),-deltaPos.y());
    update();
}

void MyOpenGLWidget::wheelEvent(QWheelEvent *event)
{   
    m_camera.ProcessMouseScroll(event->angleDelta().y()/120);
    update();
}

完整代码链接文章来源地址https://www.toymoban.com/news/detail-660447.html

到了这里,关于Qt实现简单的漫游器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenGL 网格拾取坐标(Qt)

    有时候我们希望通过鼠标来拾取某个网格中的坐标,这就涉及到一个很有趣的场景:光线投射,也就是求取一条射线与网格的交点,这里如果我们采用普通遍历网格中的每个面片的方式,当网格的面片数据量很大时计算效率就很存在问题,因此这里我们使用一种更为理想的方

    2024年01月17日
    浏览(36)
  • QT支持多种开发语言

    QT主要是一个C++应用程序框架,但它也提供了对其他一些编程语言的官方或非官方支持。以下是QT支持的一些语言版本及其特点。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1.Python (PyQt)  : PyQt是QT的官方Python绑定,允许Python开发者使用QT库来创建

    2024年04月29日
    浏览(48)
  • QT+OpenGL鼠标操作和模型控制

    本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主 需要将世界坐标转换为视口坐标 理论有点小复杂 Mouse Picking with Ray Casting - Anton’s OpenGL 4 Tutorials (antongerdelan.net) 参考这篇文章 这部分不懂的话,暂时是没关系的,可以接着往下看

    2024年02月12日
    浏览(39)
  • 在QT中使用OPENGL的步聚

    OPENGL初始化:   初始化OpenGL函数 : initializeOpenGLFunctions 初始化各种flag :  glEnable 创建各种缓存对象 : VAO,VBO 创建并链接shader :  QOpenGLShaderProgram::addShaderFromSourceCode  QOpenGLShaderProgram::Link 启用shader :  QOpenGLShaderProgram::bind 启用缓存 :     m_vao.bind(); 绑定缓存(加载不变的数据)

    2024年02月09日
    浏览(33)
  • 【QT项目:视频播放器——Qt opengl编程】通过shader完成显示yuv

    通过Qt opengl不是为了3D绘制,而是为了将视频绘制起来 使用opengl 可以极大降低yuv转rgb的转换开销 1、为什么用QT的opengl 简单,界面可以自动叠加 void paintGL(); // 具体的绘制写在该函数里 void initializeGL(); // 材质初始化 void resizeGL(int width, int height); // 当窗口发生变化(缩放) QO

    2023年04月09日
    浏览(51)
  • QT with OpenGL(IBL-镜面反射)

    Cubemap增加是否生成mipmap选项 prefilterMap Shader 其中获取采样方向,以及确定采样层级是较为关键的部分。 重要性采样 效果展示 mipmap 0 mipmap 1 mipmap 2 mipmap 3 mipmap 4 mipmap 5 --全黑(就不截图了) mipmap 4.9 可以看出没有被渲染的mipmap层级存在(不会报错),但值为纯黑。 因此如果渲染

    2024年02月01日
    浏览(36)
  • Qt中使用OpenGL的三种方式

    1.继承QOpenGLWidget并重写基类如下函数  通过使用QOpenGLContext来操作OPENGL函数   2. 继承QOpenGLFunctions类可直接使用OPENGL函数   直接使用OPENGL函数  3. 继承QOpenGLWidget 与QOpenGLExtraFunctions  在OPENGL中使用Shader 最终效果 

    2024年02月14日
    浏览(51)
  • 使用OpenGL 和 opengl ES 渲染YUV图片文件的QT示例

    头文件:CPlayWidget.h cpp文件:CPlayWidget.cpp 默认打开 ./test.yuv文件 头文件:CPlayWidget.h  与上面没有差别 cpp文件:只替换了着色器代码:

    2024年01月20日
    浏览(38)
  • Qt实现简单拼图游戏

    自己简单实现了下拼图功能.本来开始只是想显示个图片的。 ![请添加图片描述](https://img-blog.csdnimg.cn/c71922e2babf4404bf2805129f13ff76.gif 提示:以下是本篇文章正文内容,下面案例可供参考 代码如下(示例): 代码如下(示例): 代码如下(示例): 代码如下(示例): 源码下载

    2024年02月12日
    浏览(43)
  • Qt实现简单计算器

    三级项目想用Qt做界面。 为了熟悉一下Qt操作,历时8h做了个计算器。 没用到数据库,布的控件也比较简单。 所以calculator.pro和widget.ui就不放了(太长了占地方) 文件压缩包放在下一篇了,需要自取。 自学时间较短,有很多不足欢迎指正。 ⭐:del按键上的图片用的是绝对路

    2024年02月11日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包