【项目开发】QT简单练习之QQ登录界面模仿

简介: 为了进一步加深对QT开发的理解,在学习完基础操作之后要进行一个简单的练习。

一.背景说明

为了进一步加深对QT开发的理解,在学习完基础操作之后要进行一个简单的练习。

二.开发流程

像往常创建一个窗口项目,这里对于练习来说Cmakeqmake都无所谓,可以任选其一,但是选择基类时要选择QWidget。

这里对这三种类型都进行说明:


QMainWindow:


QMainWindow 是一个为典型应用程序窗口提供主框架的类。

它通常包含菜单栏、工具栏、状态栏和中心部件(如 QTextEdit 或 QWebView)。

它还管理窗口的大小、最大化、最小化和关闭等标准窗口功能。

适用于主应用程序窗口。

QWidget:


QWidget 是所有用户界面类的基类。

它是一个轻量级的窗口或控件的基类,没有菜单栏、工具栏或状态栏。

QWidget 可以作为顶层窗口,也可以嵌入到其他窗口或控件中。

适用于自定义窗口或对话框。

QDialog:


QDialog 是一个提供对话框窗口的基类。

它通常用于模态对话框,可以包含按钮、输入字段和其他控件。

QDialog 可以有返回值,通常用于输入数据或显示信息。

适用于对话框窗口。

双击widget.ui文件,进入设计师界面,调整窗口大小,使其达到类似于我们要设计的目标界面大小:

向其中拖入控件进行设计。

常用控件如下:


       Vertical Layout:垂直布局


       Horizontal Layout:水平布局


       Horizontal Spacer:水平间隔


       Vertical Spacer:垂直间隔


       Push Button:按钮


       Tool Button:工具按钮


       Radio Button:单选按钮


       Line Edit:行编辑框


       Label:标签

笔者这里换了一些不同的图标。

同时将整体布局划分为上面的两个设置图标和下面整块的登录中心界面两个区域,分别拖Vertical Layout和Horizontal Layout分开设计。

首先在对象查看器中对控件对象进行修改名称,修改成简单易懂适合的

这里修改控件的大小

在属性栏Layout栏中修改控件的间距。

这里可以修改编辑框内容文本的位置

右键Widget主窗口对象,选择样式栏可以对样式进行定制化设置

参考如下:

/*设置工具按键背景颜色*/

QToolButton

{

background-color: rgba(0, 0, 0, 0);

border:none;

}

/*设置关闭按钮图标*/

QToolButton#close_toolButton

{

border-image: url(:/images/svg/RivetIconsClose.svg);

}

/*设置关闭按钮浮空显示*/

QToolButton#close_toolButton:hover

{

 

background-color: rgb(255, 0, 0);

border-image: url(:/images/svg/RivetIconsClose_white.svg);

}

 

/*设置设置按钮图标*/

QToolButton#proxy_toolButton

{

border-image: url(:/images/svg/MaterialSymbolsSettings.svg);

}

/*设置*/

QLabel#profile_label

{

background-color: rgb(255, 255, 255);

border-radius:40px;

}

/*设置文本编辑器*/

QLineEdit

{

border:none;

border-radius:20px;

}

/*设置按钮*/

QPushButton

{

background-color: rgba(0, 0, 0);

}

/*设置登录框*/

QPushButton#login_pushButton

{

color: rgb(255, 255, 255);

background-color: rgb(158, 218, 255);

border:none;

border-radius:10px;

}

选中特定对象,右键转到槽可以自动生成对应槽函数键入代码

widget.cpp内部:

#include "widget.h"

#include "./ui_widget.h"

//构造函数

Widget::Widget(QWidget *parent)

   : QWidget(parent)

   , ui(new Ui::Widget)

{

   ui->setupUi(this);

 

   //调用setWindowFlag方法,传入FramelessWindowHint参数,用于取消边框和标题栏

   setWindowFlag(Qt::FramelessWindowHint);

   //调用事件过滤器

   this->installEventFilter(new DragWidgetFilter(this));

}

//析构函数

Widget::~Widget()

{

   delete ui;

}

//当检测到勾选同意协议之后,登录按钮变色

void Widget::on_radioButton_clicked()

{

   if(ui->radioButton->isChecked())

   {

       ui->login_pushButton->setStyleSheet("background-color:rgb(0,141,235)");

       ui->login_pushButton->setEnabled(true);

   }

   else

   {

       ui->login_pushButton->setStyleSheet("background-color:rgb(158,218,255)");

       ui->login_pushButton->setEnabled(false);

   }

}

 

//点击登录按钮后输出

void Widget::on_login_pushButton_clicked()

{

   qDebug()<<"登录";

}

 

//点击关闭按钮后关闭窗口

void Widget::on_close_toolButton_clicked()

{

   this->close();

}

widget.h内容:

#ifndef WIDGET_H

#define WIDGET_H

 

#include <QWidget>

#include <QEvent>

#include <QMouseEvent>

 

QT_BEGIN_NAMESPACE

namespace Ui {

class Widget;

}

QT_END_NAMESPACE

 

class Widget : public QWidget

{

   Q_OBJECT

 

public:

   Widget(QWidget *parent = nullptr);

   ~Widget();

 

private slots:

   void on_radioButton_clicked();

 

   void on_login_pushButton_clicked();

 

   void on_close_toolButton_clicked();

 

private:

   Ui::Widget *ui;

};

 

//主要完成事件过滤,当鼠标拖动时窗口跟随移动

class DragWidgetFilter : public QObject

{

public:

   DragWidgetFilter(QObject* parent = nullptr)

       : QObject(parent), isDragging(false) {}//构造函数

 

   //这里override是高速编译器重写基类中的重名方法

   bool eventFilter(QObject* object, QEvent* event) override

   {

       //dynamic_cast<>()是动态类型转换操作符

       //这里将object对象转换为QWidget*类型并赋值给w

       auto w = dynamic_cast<QWidget*>(object);

       if (!w)

       {

           return false;

       }

 

       //匹配传入的event下的type()方法传出的值

       switch (event->type())

       {

       //鼠标点击了

       case QEvent::MouseButtonPress:

       {

           auto ev = dynamic_cast<QMouseEvent*>(event);

           if (!ev || ev->button() != Qt::LeftButton)

           {

               return false;

           }

           isDragging = true;

           startPos = ev->globalPosition().toPoint();

           windowPos = w->frameGeometry().topLeft();

       } break;

       //鼠标移动了

       case QEvent::MouseMove: {

           auto ev = dynamic_cast<QMouseEvent*>(event);

           if (!ev || !(ev->buttons() & Qt::LeftButton) || !isDragging)

           {

               return false;

           }

           const QPoint currentPos = ev->globalPosition().toPoint();

           const QPoint diff = currentPos - startPos;

           const QPoint newWindowPos = windowPos + diff;

           // Optionally check if new position is within screen boundaries

           // before calling move.

           w->move(newWindowPos);

       } break;

       //鼠标松开

       case QEvent::MouseButtonRelease:

       {

           auto ev = dynamic_cast<QMouseEvent*>(event);

           if (ev && ev->button() == Qt::LeftButton && isDragging)

           {

               isDragging = false;

           }

       } break;

 

       default:

           break;

       }

       //当匹配不到上面任何一个类型时,则调用基类的eventFilter函数

       return QObject::eventFilter(object, event);

   }

 

private:

   bool isDragging;

   QPoint startPos;

   QPoint windowPos;

};

 

#endif // WIDGET_H


                                                                                                                                                                                                                                    未完待续。。。




相关文章
|
2天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
4天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1540 5
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
7天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
585 22
|
4天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
201 3
|
10天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
11天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
581 5
|
23天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
7天前
|
XML 安全 Java
【Maven】依赖管理,Maven仓库,Maven核心功能
【Maven】依赖管理,Maven仓库,Maven核心功能
235 3
|
9天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
328 2