前言:

先看一下 WPS 的登陆界面

多看两遍 你会发现他的细节真的很多
比如 鼠标 hover 阴影背景
切换的翻页效果

然后我想的是我也实现一下这个大体的效果吧
最后 这个翻页动画效果没有实现 。。。
我代码都是用 Qpainter 画出来的 实在不知道怎么实现 翻书动画效果了
QPropertyAnimation 这个类貌似不能给Qpainter 用
各位小伙伴如果有好的实现方法 可以在评论区告诉我

下面是我实现的效果 时间问题 没有美化 大体实现了 这个效果

支持 动态插入页面 删除页面 不需要修改 painter 部分

项目结构:

main 函数
一个 widget 主界面类
一个 customPainterLabel 类

没有 UI 文件 界面都是代码写的

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include "custompainterlabel.h"#include <QWidget>class QLabel;
class QPushButton;namespace Ui {class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private:QLabel* titleLabel;QPushButton* leftBtn;QPushButton* rightBtn;customPainterLabel* cPainterLabel;
};#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QSpacerItem>
#include <QDebug>
Widget::Widget(QWidget *parent) :QWidget(parent)
{titleLabel = new QLabel("盗版 WPS Office 账号登录");QFont labelFont;labelFont.setBold(true);labelFont.setPixelSize(22);titleLabel->setFont(labelFont);leftBtn = new QPushButton("<");rightBtn = new QPushButton(">");cPainterLabel = new customPainterLabel();cPainterLabel->setMinimumSize(500,500);QHBoxLayout *hLayout = new QHBoxLayout();hLayout->addWidget(leftBtn,1,Qt::AlignHCenter);hLayout->addWidget(cPainterLabel,5);hLayout->addWidget(rightBtn,1,Qt::AlignHCenter);QVBoxLayout *vLayout = new QVBoxLayout();vLayout->addWidget(titleLabel,1,Qt::AlignHCenter );vLayout->addLayout(hLayout);this->setLayout(vLayout);connect(leftBtn,&QPushButton::clicked,[=](){for(auto i = 0; i < cPainterLabel->getResourceSize();i++){if(cPainterLabel->getResourceIsSelect(i) && i != 0){cPainterLabel->setResourceIsSelect(i,false);cPainterLabel->setResourceIsSelect(--i,true);cPainterLabel->update();}}});connect(rightBtn,&QPushButton::clicked,[=](){for(auto i = 0; i < cPainterLabel->getResourceSize();i++){if(cPainterLabel->getResourceIsSelect(i) && i< cPainterLabel->getResourceSize()-1){cPainterLabel->setResourceIsSelect(i,false);cPainterLabel->setResourceIsSelect(++i,true);cPainterLabel->update();}}});
}Widget::~Widget()
{}

结构是这样的 中间的画布 是 customPainterLabel 类 左边和右边 各一个按钮 水平布局
这个水平布局和上面的 盗版wps label 是垂直布局

就构成了这个样子

上面的两个 点击按钮的信号槽是 Lambda 表达式形式
实现的内容就是切换页面

customPainterLabel.h

#ifndef CUSTOMPAINTERLABEL_H
#define CUSTOMPAINTERLABEL_H#include <QObject>
#include <QLabel>struct Resource
{QColor backgroundColor;bool isSelect;int ellipseRadius;QColor ellipseSelectColor;QColor ellipseColor;Resource(){backgroundColor = Qt::black;ellipseSelectColor = Qt::blue;ellipseColor = Qt::gray;isSelect = false;ellipseRadius = 5;}
};class customPainterLabel : public QLabel
{public:customPainterLabel();inline bool getResourceIsSelect(int index){if(index < 0 || index >= m_resourceVec.size())return false;return m_resourceVec.at(index).isSelect;}inline void setResourceIsSelect(int index,bool state){if(index < 0 || index >= m_resourceVec.size())return;m_resourceVec[index].isSelect = state;}inline int getResourceSize()const{return m_resourceVec.size();}protected:void paintEvent(QPaintEvent *e) override;void drawEllipseList(QPainter *p,int centerX,int centerY);void drawBackgroundList(QPainter *p,QRect rect);
private:QVector<Resource> m_resourceVec;
};#endif // CUSTOMPAINTERLABEL_H

customPainterLabel.cpp

#include "custompainterlabel.h"#include <QPainter>
#include <QPaintEvent>
#include <QDebug>#define ELLIPSE_SPACE 30
customPainterLabel::customPainterLabel()
{Resource r1;r1.backgroundColor = Qt::red;Resource r2;r2.backgroundColor = Qt::green;Resource r3;r3.backgroundColor = Qt::blue;Resource r4;r4.backgroundColor = Qt::black;r4.isSelect = true;Resource r5;r5.backgroundColor = Qt::magenta;m_resourceVec<< r1 << r2 << r3 << r4 << r5 ;
}void customPainterLabel::paintEvent(QPaintEvent *e)
{QPainter p(this);auto w = this->width();auto h = this->height();p.save();drawEllipseList(&p,w/2,h - h/10);drawBackgroundList(&p,QRect(w/2 -180,h/2-180,360,360));p.restore();p.setPen(QPen(Qt::black));p.drawRect(0,0,this->rect().width()-2,this->rect().height()-2);
}void customPainterLabel::drawEllipseList(QPainter *p, int centerX, int centerY)
{int size = m_resourceVec.size();if(size <= 0)return;int startX = centerX - (size / 2) * ELLIPSE_SPACE;for(auto i = 0; i< size;i++){if(m_resourceVec.at(i).isSelect)p->setBrush(QBrush(m_resourceVec.at(i).ellipseSelectColor));elsep->setBrush(QBrush(m_resourceVec.at(i).ellipseColor));p->drawEllipse(QPoint(startX + i * ELLIPSE_SPACE,centerY),m_resourceVec.at(i).ellipseRadius,m_resourceVec.at(i).ellipseRadius);}update();
}void customPainterLabel::drawBackgroundList(QPainter *p, QRect rect)
{int size = m_resourceVec.size();if(size <= 0)return; 先找到被选中的那个 然后画出来int isSelectedIndex = -1;for(auto i = 0; i < size; i++){if(m_resourceVec.at(i).isSelect){isSelectedIndex = i;p->setBrush(QBrush(m_resourceVec.at(i).backgroundColor));p->drawRect(rect);}} 依次从中间画左边的for(auto i = isSelectedIndex-1,j = 1; i >=0; i--,j++){p->setBrush(QBrush(m_resourceVec.at(i).backgroundColor));int startX = rect.topLeft().x() - 20 * j;int startY = rect.topLeft().y() + 20 * j;p->drawRect(startX,startY,20,rect.height() - 40 * j);} 依次从中间画右边的for(auto i = isSelectedIndex+1,j=1; i<size; i++,j++){p->setBrush(QBrush(m_resourceVec.at(i).backgroundColor));int startX = rect.topRight().x() + 20 *(j-1);int startY = rect.topRight().y() + 20 * j;p->drawRect(startX,startY,20,rect.height() - 40 *j);}update();}

Resource 这个结构体就是中间的页面
我现在是给了个背景色 可以给 图片 或者 widget 都可以
时间原因 我简单写了下

QVector m_resourceVec; 就是管理页面资源的容器

当想增加页面 只需要添加一个进容器
删除页面 就减少一个 比较方便

画中间的内容 用的 paintEvent

主要的两个函数 一个 是画下面的当前选择的条目

drawEllipseList

另一个就是画中间的 ‘页’

drawBackgroundList

先说 第一个

思路就是 先判断有几个页面 就是几个点
然后 找到中间的点 比如有6个 找到第三个
往前面数3个 每个都有间距 算出第一个的坐标

然后 从第一个位置开始画 直到画到最后一个
如果当前页是选中了的 就换个颜色

下面的 实现思路类似 先找到 当前选中的页面 把他先画出来

然后在找 这个选中页面的左边的页面 画出来
然后在找 这个选中页面的右边的页面 画出来

只需要画一小部分就行 后面的遮挡了不用画

这里面用到一些 数值 比如20啊 啥的 都是 间距 之类的 我也没用宏
写 的不规范 大家知道就行了

void customPainterLabel::drawBackgroundList(QPainter *p, QRect rect)
{int size = m_resourceVec.size();if(size <= 0)return; 先找到被选中的那个 然后画出来int isSelectedIndex = -1;for(auto i = 0; i < size; i++){if(m_resourceVec.at(i).isSelect){isSelectedIndex = i;p->setBrush(QBrush(m_resourceVec.at(i).backgroundColor));p->drawRect(rect);}} 依次从中间画左边的for(auto i = isSelectedIndex-1,j = 1; i >=0; i--,j++){p->setBrush(QBrush(m_resourceVec.at(i).backgroundColor));int startX = rect.topLeft().x() - 20 * j;int startY = rect.topLeft().y() + 20 * j;p->drawRect(startX,startY,20,rect.height() - 40 * j);} 依次从中间画右边的for(auto i = isSelectedIndex+1,j=1; i<size; i++,j++){p->setBrush(QBrush(m_resourceVec.at(i).backgroundColor));int startX = rect.topRight().x() + 20 *(j-1);int startY = rect.topRight().y() + 20 * j;p->drawRect(startX,startY,20,rect.height() - 40 *j);}update();}

理类上下一步要实现 翻页的动画 我这没有
我也想不出啥好的实现办法了
大家有好的实现办法 可以在评论区告诉我 我继续实现一下

Qt 纯代码模仿 WPS 登录界面相关推荐

  1. Swift - 一个纯代码实现的登录界面(带猫头鹰动画效果)

    这个是一个可爱的登录框页面,动画效果仿自国外网站readme.io.在GitHub上有人写了个objective-C版本,这里我翻译成Swift版的分享给大家. 效果图如下: (1)当输入用户名时,猫 ...

  2. pyqt5登录界面设计——模仿qq登录界面,可登录注册(数据库)

    pyqt5登录界面设计--模仿qq登录界面 一.简单易用的可直接登录的界面--账号密码程序写死 1.1.效果图: 1.2.视频效果图 3.代码说明 4.使用示例 5.全部源码见: 二.带数据库的可登录 ...

  3. 项目实战:Qt5/Quick:模仿扣扣登录界面[小程序]

    项目实战:Qt5/Quick:模仿扣扣登录界面[小程序] 目录 编辑环境: 项目: 项目简介: 其他: 1.项目运行效果 2.项目思路分析 3.项目主要源码部分 4.整个项目源码共享 编辑环境: wi ...

  4. QT纯代码打造音乐播放器

    QT纯代码打造音乐播放器 在.pro文件中添加 QT = prmultimedia 然后就是在.h文件中添加相关库函数 我添加的库函数 有些是不需要的,可以自定义删除修改 我是为方便以后扩展功能就留下 ...

  5. java代码完全手写模仿qq登录界面

    这是我模仿QQ2015版界面,实现的基本功能有登陆验证,重置等,当然直接复制代码运行是不一样的,还要注意自己插入自己的图片. 结果截图如下所示: import java.awt.BorderLayou ...

  6. Qt模仿QQ登录界面(一)

    这两天研究qt,练习时做了个仿QQ登录界面,我这次实现的比较简单,先在这里记录一下,以后有空了会继续完善的. (一)效果图 这里使用我的qq号测试的如图: (二)工程文件 (三)代码实现 mainwi ...

  7. QT纯代码设计UI界面Demo

    目录 一.前言 二.界面 三.源码简析 四.Demo/源码 一.前言 UI的设计方法有几种: ①一种是使用Qt Designer,也就是可视化设计,这在小型项目中常见,优点就是可观简便: ②另一种就是 ...

  8. label qt 自动换行_QT编写一个登录界面

    前言 继上篇:一起学Qt之基础篇---入门 今天上手实操用QT编写一个登录界面~ 系统权限这个词大家肯定不陌生,你进入一个网站也是,如果不登录,就是以游客的身份进去的,要想看到某些信息肯定需要进行登录 ...

  9. Android 模仿QQ登录界面解决软键盘遮挡问题

    Android 软件盘弹出可能会遮挡住界面上的某些控件.当 windowSoftInputMode 为 adjustPan 时,一般不会挡住 EditText,但是假如 EditText 下面是一个登 ...

最新文章

  1. 《Python数据分析与挖掘实战》一第1章 数据挖掘基础1.1 某知名连锁餐饮企业的困惑...
  2. JQuery对checkbox操作 (循环)
  3. keypair java_如何在Java中序列化和反序列化RSA KeyPair
  4. IDM下载速度慢解决方案全网搜集持续更新
  5. Oracle归档目录 和 DB_RECOVERY_FILE_DEST
  6. java计算器简单吗,java简单计算器
  7. JAVA设计模式 - 建造者模式
  8. 详解如何正确使用Tuxera NTFS For Mac软件
  9. 虚幻引擎游戏技能系统文档
  10. chrome 迅雷下载 支持插件, 让chrome支持迅雷
  11. 不用if比较两个数大小
  12. html在线调查,HTML5 调查问卷表单
  13. python的标准随机数生成器模块_Python:带均值和标准差的随机数生成器
  14. 软件测试多长时间可以学习,软件测试学习多长时间啊?好学吗?
  15. SQL“除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效“ 解决方法
  16. 带你刷笔试关的小怪|详解指针习题和面试题【C语言/指针/进阶】
  17. Godot Engine:将Sprite和刚体保持同一轴心
  18. python爬虫小工具——下载助手
  19. 洛谷题目P1425 小鱼的游泳时间
  20. 微信小程序转二维码两种方法

热门文章

  1. 掌上聊app v1.5.5
  2. 古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
  3. blender动画制作
  4. 台达PLC伺服追剪程序,电子凸轮,全部源代码,PLC程序和触 摸屏程序,DVP15MC。
  5. Excel如何快速统计某列数据出现次数
  6. 《最好的告别》:如何优雅地走向生命终点
  7. lua 调用c++ dll, 提示:%1 不是有效的 Win32 应用程序。
  8. 美团笔试(测试开发)
  9. outlook邮件撤回
  10. hbase报错: ERROR: Can‘t get master address from ZooKeeper; znode data == null