大家好,今天主要和大家分享一下,如何使用QT进行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 的源文件。
总结:读者可以运行程序来体验滑动效果及界面设计的效果。 可以交叉编译到开发板上运行,无论是界面设计感还是流畅度都很不错。