linux系统中使用QT实现APP开发的基本方法

news2024/11/16 7:54:57

      大家好,今天主要和大家分享一下,如何使用QT进行APP的主界面开发的方法。

目录

第一:APP界面开发基本简介

第二:滑动界面实现

第三:APP界面开发实现

第四:APP主界面测试


 

第一:APP界面开发基本简介

      在QT C++提供了像QStackedWdget 与 QTableView 这种控 件可以方便的切换页面,但是这种切换页面的方法比较生硬,不能像手机一样滑动,往往这种 界面就会给用户较差的体验感。

      在 Qt C++编程滑动屏幕界面这方面里,笔者也参考过许多网上的文章。发现很多都是使用 QPainter 结合 QMouseMove 事件来重绘屏幕或者移动屏幕的,这种方式代码量较长,而且不容 易移植。很多都是固定了界面的页数及大小,不能使用布局等等。于是笔者结合自己的开发经 验自己写一个滑动界面的类,可以很方便的增加页面,能跟随页面的大小变化而变化,是笔者 原创的一个作品,可以方便大家移植到需要写 APP 主界面的程序里。同时笔者也花了时间写了 一个好看的车载音乐主界面(只有界面,非功能的实现,笔者模仿网上的车载界面,用 Qt 实现 的),读者可以参考源代码来开发自己的界面。同时也是笔者带领读者开发 APP 主界面的入门 操作。

第二:滑动界面实现

      本节代码程序是滑动页面的设计:

1 #include "slidepage.h"
2 #include <QDebug>
3 #include <QPropertyAnimation>
4 
5 SlidePage::SlidePage(QWidget *parent):
6 QWidget(parent),
7 pageIndex(0),
8 pageCount(0),
9 draggingFlag(false)
10 {
11 pageIndicator.clear();
12 this->setMinimumSize(400, 300);
13 this->setAttribute(Qt::WA_TranslucentBackground, true);
14
15 scrollArea = new QScrollArea(this);
16 scrollArea->setAlignment(Qt::AlignCenter);
17
18 mainWidget = new QWidget();
19 mainWidget->setStyleSheet("background: transparent");
20
21 scrollArea->setWidget(mainWidget);
22 scrollArea->setStyleSheet("background: transparent");
23
24 bottomWidget = new QWidget(this);
25 bottomWidget->setStyleSheet("background: transparent");
26
27 bottomHBoxLayout = new QHBoxLayout();
28 bottomWidget->setLayout(bottomHBoxLayout);
29 bottomHBoxLayout->setContentsMargins(0, 0, 0, 0);
30 bottomHBoxLayout->setAlignment(Qt::AlignCenter);
31
32 /* 关闭滚动条显示 */
33 scrollArea->setVerticalScrollBarPolicy(
34 Qt::ScrollBarAlwaysOff);
35 scrollArea->setHorizontalScrollBarPolicy(
36 Qt::ScrollBarAlwaysOff);
37
38 /* 滚屏对象 */
39 scroller = QScroller::scroller(scrollArea);
40 QScroller::ScrollerGestureType gesture =
QScroller::LeftMouseButtonGesture;
41 scroller->grabGesture(scrollArea, gesture);
42
43 /* 获取属性 */
44 QScrollerProperties properties = scroller->scrollerProperties();
45
46 /* 设置滑动的时间,值越大,时间越短 */
47 properties.setScrollMetric(QScrollerProperties::SnapTime, 0.5);
48
49 /* 设置滑动速度 */
50 properties.setScrollMetric(QScrollerProperties::MinimumVelocity,
1);
51 scroller->setScrollerProperties(properties);
52
53 /* 布局 */
54 hBoxLayout = new QHBoxLayout();
55
56 hBoxLayout->setContentsMargins(0, 0, 0, 0);
57 hBoxLayout->setSpacing(0);
58
59 mainWidget->setLayout(hBoxLayout);
60
61 /* 定时器,用于判断用户是否是拖动屏幕,区分滑动,超过 300ms 表示拖动 */
62 timer = new QTimer(this);
63
64 connect(scrollArea->horizontalScrollBar(),
SIGNAL(valueChanged(int)), this, SLOT(hScrollBarValueChanged(int)));
65 connect(scroller, SIGNAL(stateChanged(QScroller::State)), this,
SLOT(onStateChanged(QScroller::State)));
66 connect(timer, SIGNAL(timeout()), this, SLOT(onTimerTimeOut()));
67 connect(this, SIGNAL(currentPageIndexChanged(int)), this,
SLOT(onCurrentPageIndexChanged(int)));
68 }
69
70 SlidePage::~SlidePage()
71 {
72 }
73
74 void SlidePage::addPage(QWidget *w)
75 {
76 /* 布局里添加页面 */
77 hBoxLayout->addWidget(w);
78 /* 页数加一 */
79 pageCount++;
80 QLabel *label = new QLabel();
81 label->setPixmap(QPixmap(":/icons/indicator1.png"));
82 pageIndicator.append(label);
83 bottomHBoxLayout->addWidget(label);
84 }
85
86 void SlidePage::resizeEvent(QResizeEvent *event)
87 {
88 Q_UNUSED(event)
89 scrollArea->resize(this->size());
90 /* mainWidget 需要比 scrollArea 小 */
91 mainWidget->resize(this->width() * pageCount, this->height() - 4);
92 if (pageCount == 0)
93 qDebug()<<"当前页面总数为 0,请使用 addPage()方法添加页面再使用!
"<<endl;
94 else
95 onCurrentPageIndexChanged(0);
96 bottomWidget->setGeometry(0, this->height() - 20, this->width(),
20);
97 }
98
99 void SlidePage::hScrollBarValueChanged(int)
100 {
101 /* 滑动时判断当前页的下标 */
102 pageIndex= scrollArea->horizontalScrollBar()->value() /
this->width();
103 pageIndex = scrollArea->horizontalScrollBar()->value()
104 >= (pageIndex * this->width() + this->width() * 0.5) ?
pageIndex + 1 : pageIndex;
105
106 }
107
108 void SlidePage::onStateChanged(QScroller::State state)
109 {
110 static int pressedValue = 0;
111 static int releasedValue = 0;
112 static int currentPageIndex = 0;
113
114 /* 如果页面数为 0,返回,不做任何操作 */
115 if (pageCount == 0)
116 return;
117
118 /* 松开 */
119 if (state == QScroller::Inactive) {
120 /* 停止定时器,防止检测到界面是缓慢拖动状态 */
121 timer->stop();
122 /* 记录松开时的坐标 */
123 releasedValue = QCursor::pos().x();
124
125 if (pressedValue == releasedValue)
126 return;
127
128 /* 判断按下与松开的距离,首先先判断是不是拖动状态,如果是拖动状态,
pageIndex 不会变化 */
129 if (!draggingFlag) {
130 if (pressedValue - releasedValue > 20 && currentPageIndex ==
pageIndex)
131 pageIndex++;
132 else
133 pageIndex--;
134 }
135
136 /* 页面下标判断 */
137 if (pageIndex == -1)
138 pageIndex = 0;
139
140 if (pageIndex >= pageCount)
141 pageIndex = pageCount - 1;
142
143 /* 动画 */
144 QPropertyAnimation *animation = new 
QPropertyAnimation(scrollArea->horizontalScrollBar(), "value");
145 animation->setDuration(200);
146 
animation->setStartValue(scrollArea->horizontalScrollBar()->value());
147 animation->setEasingCurve(QEasingCurve::OutCurve);
148 animation->setEndValue(pageIndex * this->width());
149 animation->start();
150
151 if (currentPageIndex != pageIndex) {
152 /* 发送当前页面的位置信号 */
153 emit currentPageIndexChanged(pageIndex);
154 }
155
156 /* 重新赋值*/
157 pressedValue = 0;
158 releasedValue = 0;
159 draggingFlag = false;
160 }
161
162 /* 按下 */
163 if (state == QScroller::Pressed) {
164 pressedValue = QCursor::pos().x();
165 currentPageIndex = scrollArea->horizontalScrollBar()->value() /
this->width();
166 /* 按下如果超过 300ms,表示用户在拖动 */
167 timer->start(300);
168 }
169 }
170
171 void SlidePage::onTimerTimeOut()
172 {
173 /* 拖动标志位 */
174 draggingFlag = true;
175 timer->stop();
176 }
177
178 int SlidePage::getPageCount()
179 {
180 return pageCount;
181 }
182
183 int SlidePage::getCurrentPageIndex()
184 {
185 return pageIndex;
186 }
187
188 void SlidePage::onCurrentPageIndexChanged(int index)
189 {
190 for (int i = 0; i < pageIndicator.count(); i++) {
191 if (i == index)
192 
pageIndicator[i]->setPixmap(QPixmap(":/icons/indicator2.png"));
193 else
194 
pageIndicator[i]->setPixmap(QPixmap(":/icons/indicator1.png"));
195 }
196 }

分析:滑动界面部分是由 QScroller 类控制。同时通过设置 QScrollArea-> horizontalScrollBar()这个 滚动条的 value 值就可以控制界面所处位置了。原理看似简单,详细需要查看程序,请读者带 着程序的原理通过细读程序源码来分析。 注意!运行这个项目时,您会发现这是一个空白的窗口!因为这只是一个滑动页面的类, 我们还没有在里面添加内容!所以接着往下看,我们先开发一页 APP 界面。 运行项目效果如下。因为我们还没有给滑动页面类加内容。所以是无法滑动的。继续往下 看。

第三:APP界面开发实现

     实现了一个车载音乐界面的界面开发。注意只是界面开发,不实现其功能。读者可 以参考来实现自己的界面。开发界面除了自己的想法,还需要有美工基础,我们前面已经学习 过布局了,APP 界面,主要都是一些布局的设计。

项目运行后,可以看到这样的一页这样的 APP 主界面,注意不能点击,这只是界面而已! 读者就可以仿照这样的一个 APP 界面来开发自己的应用界面了。开发时再通过链接到界面上的 按钮的点击信号,比如点击按钮后打开新的页面,这样就可以完成一个完整的点击交互事件了!

第四:APP主界面测试

     

 项目文件夹下内容解释: 03_appmainview.pro 项目下:

1、 appdemo 文件夹为车载音乐 APP 页面,只是界面,不带实际功能!

2、 slidepage 文件夹为笔者原创的一个滑动页面类,在这个类里,我们可以使用 addPage()方法 来添加页面,当添加的页面大于 2 页时,就可以滑动切换页面了。

3、 Headers 文件夹为 03_appmainview.pro 的头文件。

4、 Sources 文件夹为 03_appmainview.pro 的源文件。

 

总结:读者可以运行程序来体验滑动效果及界面设计的效果。 可以交叉编译到开发板上运行,无论是界面设计感还是流畅度都很不错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARP渗透与攻防(一)之ARP原理

ARP原理 前言 ARP攻击就是通过伪造IP地址和MAC地址实现ARP欺骗&#xff0c;能够在网络中产生大量的ARP通信量使网络阻塞&#xff0c;攻击者只要持续不断的发出伪造的ARP响应包就能更改目标主机ARP缓存中的IP-MAC条目&#xff0c;造成网络中断或中间人攻击。ARP攻击主要是存在…

CSS3基础内容

目录 CSS基本样式 选择器分类 标签选择器 类选择器 利用类选择器画三个盒子 多类名 id选择器 id选择器和类选择器的区别 通配符选择器 CSS字体属性 字体粗细font-weight 字体样式 CSS文本属性 CSS的引入方式 行内样式表&#xff08;行内式&#xff09; 内部样式表…

2023年集卡活动简记

文章目录支付宝总评&#xff1a;【强烈推荐】年味浓&#xff0c;必中奖&#xff0c;单倍金额不算少。只关注开奖可以除夕当天玩儿。集卡分1.88元难度&#xff1a;【非常低】必中奖时间投入&#xff1a;【较少】无需打开其他App&#xff0c;比较轻松。操作体验&#xff1a;【好】…

深度理解卷积神经网络

神经网络包括卷积层&#xff0c;池化层&#xff0c;全连接层。一个最简单的神经元结构&#xff0c;假如有三个输入&#xff0c;都对应一个权重参数&#xff0c;然后通过权重加起来&#xff0c;经过一个激活函数&#xff0c;最后输出y。CNN中独特的结构就是卷积层&#xff0c;就…

拓展:阿里巴巴中文站架构演进分析【部分】

文章目录前言阿里巴巴中文站架构发展历程阿里巴巴第五代架构数据架构的复杂前言 由学习整理而来&#xff0c;并非有意抄袭。如果有冒犯行为&#xff0c;请及时联系作者进行处理&#xff01; 阿里巴巴中文站架构发展历程 时间关键技术1999第一代网站架构Perl&#xff0c;CGl&…

【实操案例八】元组、集合操作 实例代码及运行效果图!

任务一&#xff1a;我的咖啡馆你做主 方法一&#xff1a;使用列表 # 任务一&#xff1a;我的咖啡馆你做主 # 方法一&#xff1a;使用列表lst[蓝山,卡布奇诺,拿铁,皇家咖啡,女王咖啡,美丽与哀愁]for i in lst:print(lst.index(i)1,.,i,end\t) print()while True:chice int(in…

SpringCloud+Ribbon 报错:java.net.unknownhostexception:XXX

SpringCloudRibbon 报错&#xff1a;java.net.unknownhostexception:XXX 问题分析&#xff1a; 网上很多的说法是依赖冲突导致&#xff0c;原因是什么呢&#xff1a;如果你的org.springframework.cloud:spring-cloud-starter-netflix-eureka-client 依赖中包含了ribbon依赖&…

常用JVM配置参数简介

既然学习JVM&#xff0c;阅读GC日志是处理Java虚拟机内存问题的基础技能&#xff0c;它只是一些人为确定的规则&#xff0c;没有太多技术含量。 既然如此&#xff0c;那么在IDE的控制台打印GC日志是必不可少的了。现在就告诉你怎么打印。 &#xff08;1&#xff09;如果你用的是…

Elasticsearch7.8.0版本高级查询—— 分页查询文档

目录一、初始化文档数据二、分页查询文档2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; { "name":"zhangsan", "ag…

数据分析-深度学习 Pytorch Day8

一。什么是循环神经网络&#xff1a;循环神经网络&#xff08;Rerrent Neural Network, RNN&#xff09;&#xff0c;历史啊&#xff0c;谁发明的都不重要&#xff0c;说了你也记不住&#xff0c;你只要记住RNN是神经网络的一种&#xff0c;类似的还有深度神经网络DNN&#xff…

广州周立功CanTest卡使用教程一

网上有不少Can采集平台,包括Ardunio,Can卡,也有不少人用Freescale自己DIY一个平台,这些都是相当不错,并且都有成熟的代码,这里介绍在汽车诊断软件领域普遍都会选择的Can卡使用。 大家是不是对这个节面非常熟悉,CAN-bus 通用测试软件是一个专门用来对所有的 ZLGCAN 系列板…

【Python】基于经典网络架构训练图像分类模型——图像识别模型与训练策略(2023年1月22日,大年初一,春节快乐,兔年大吉)

声明:仅学习使用~ 今天是大年初一,祝大家新年快乐!!! 这个练习使用的图片稍多,因此初次在PyCharm里面可能会需要一些时间。 (注释中包含遇到的一些错误以及修正,同时也含有一些输出,部分较长的输出以省略号的形式在注释里面展示了) 2023.1.22,大年初一,新年快乐…

LoadBalancer源码解析

文章目录一、背景二、总体流程三、源码解析1. lb拦截器配置2. LB拦截器实现3. LB执行前置处理4. 负载均衡5. LB执行http请求一、背景 Spring Cloud 2020版本以后&#xff0c;默认移除了对Netflix的依赖&#xff0c;其中就包括Ribbon&#xff0c;官方默认推荐使用Spring Cloud …

生物化学 电阻抗成像OpenEIT 番外篇 EIT公式

EIT简介 摘要电阻抗断层扫描&#xff08;EIT&#xff09;是一种成像方式&#xff0c;使用无害的电流探测患者或物体。电流通过放置在靶表面上的电极馈送&#xff0c;数据由在电极处测量的电压组成&#xff0c;这些电压由一组线性独立的电流注入模式产生。EIT旨在恢复目标内部电…

【MySQL】第八部分 加密和解密函数

【MySQL】第八部分 加密和解密函数 文章目录【MySQL】第八部分 加密和解密函数8. 加密和解密函数总结8. 加密和解密函数 函数用法PASSWORD(str)返回字符串str的加密版本&#xff0c;41位长的字符串。加密结果不可逆&#xff0c;常用于用户的密码加密.( 8.0 版本以上不能用)MD5…

海湾化学冲刺上交所上市:计划募资30亿元,华融曾是其股东

近日&#xff0c;青岛海湾化学股份有限公司&#xff08;下称“海湾化学”&#xff09;预披露招股书&#xff0c;准备在上海证券交易所主板上市。本次冲刺上市&#xff0c;海湾化学计划募资30亿元&#xff0c;将于37.5万吨/年环氧氯丙烷绿色循环经济项目&#xff08;一期&#x…

23种设计模式(十七)——状态模式【状态变化】

状态模式 文章目录 状态模式意图什么时候使用状态真实世界类比状态模式的实现状态模式的优缺点亦称:State 意图 对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。 状态模式的解决思想是:当控制一个对象状态转…

【沐风老师】教你用3dMax柱子插件Pillars打造欧式罗马柱建模(附柱子插件下载)

Pillars是一个很棒的3dMax插件。Pillars可以创建柱子、柱状物、栏杆、喷泉&#xff08;喷泉建筑的造型&#xff09;和各种类似形状的三维模型。它也会破坏&#xff08;打断&#xff09;这些模型。有了它&#xff0c;您只需在几秒钟内就能制作出外观精美的柱子和效果逼真的断面效…

4、JDK相关设置

文章目录4、JDK相关设置4.1 设置项目的JDK4.2 设置编译版本4.3 设置out目录【尚硅谷】idea实战教程-讲师&#xff1a;宋红康 生活是属于每个人自己的感受&#xff0c;不属于任何别人的看法 4、JDK相关设置 4.1 设置项目的JDK SDK&#xff1a;软件开发工具包 JDK&#xff1a;Ja…

灭火器摆放识别检测算法 yolo

灭火器摆放识别检测算法通过pythonyolo网络深度学习技术&#xff0c;自动对指定区域灭火器是否缺失进行识别&#xff0c;如果 没有检测到指定区域有灭火器&#xff0c;立即抓拍存档进行告警。YOLO系列算法是一类典型的one-stage目标检测算法&#xff0c;其利用anchor box将分类…