使用 Qt 来开发 Android 应用,也须要适配不一样移动设备,适配多种多样的屏幕和分辨率。此次咱们大概来说一下如何使用 Qt 提供的机制来建立可伸缩的界面。html
DPI
必需要解释一下 DPI 。mysql
DPI , dot per inch ,即每英寸包含的点数。还有一个概念是 PPI ,即每英寸包含的像素数。android
这个值越大,像素密度越大,小尺寸的屏幕就能够有大分辨率。好比有的 Android 手机, 3.7 吋屏幕就能提供 960x540 的分辨率,而有的手机, 5 吋屏幕却提供 800x480 的分辨率。这两种不一样屏幕的尺寸和分辨率的手机,5 吋屏看起来会有颗粒感,而 3.7 吋看起来则很是细腻。这就是像素密度带来的差异。web
DPI 对界面的影响是酱紫的:一样分辨率(按像素来讲)的图片,在 DPI 越大的屏幕上,看起来就越小。sql
三类可伸缩元素
一个 Qt 移动应用,大概有三类可伸缩 UI 元素:架构
咱们分别来看一下。app
文字
对于文字来说,咱们只须要设置特定的文本显示和输入控件所使用的字体(QFont)的 pointSize 便可。像 QLabel 、 QPushButton 、 QLineEdit 等等都适用这种方式。oop
QFont 的大小有两种表达方式: pixelSize 和 pointSize 。 pointSize 会根据应用所在的设备的 DPI 来调整字体,使得在不一样 DPI 的设备上看起来效果一致。学习
Qt 里面能够单独改变一个 Widget 使用的字体,也能够经过 QApplication 来提供全局的字体,这样那些没有专门设置的 Widget ,就会使用全局的字体。字体
图片
前面咱们说了,一样分辨率的图片,屏幕 DPI 越大,人眼看过去,就以为越小。
Qt 能够处理这种状况,咱们以 QPixmap 为例来讲明。
QPixmap 有两个方法:
- void setDevicePixelRatio(qreal scaleFactor)
- qreal QPixmap::devicePixelRatio() const
这两个方法操做一个叫做 device pixel ratio 的属性,这个属性指定了设备相关的像素和设备无关的像素之间的换算比率。咱们能够经过调整它来改变一个图片在手机屏幕上看起来的效果。
QImage 类一样有这两个方法。你们能够查阅 Qt 帮助来看 API 的细节。
那如何获取一个设备的 devicePixelRation 呢?
QScreen 有个方法能够返回这个值:qreal QScreen::devicePixelRatio() const
QGuiApplication 、 QWindow 这两个类也有同名的方法。
咱们也能够本身计算,使用 QScreen 的 logicalDotsPerInch() 方法结合一个常见的 DPI (好比 72)来计算,下面是示例代码:
- float SizeUtil::dpiFactor()
- {
- QScreen *screen = qApp->primaryScreen();
- return 72 / screen->logicalDotsPerInch();
- }
我在后面的示例中用了上面的方法。
要说明的是,Qt 的内建控件在使用 QPixmap 和 QImage 时,会结合 devicePixelRation 来决定这个控件的大小,咱们的示例里使用 QLabel 来显示图片。
背景
背景要么是某种颜色,要么是一张图片。当使用图片作背景时,面临拉伸问题。 Android 使用 9patch 图片来解决这个问题, Qt 也提供了相似的东西:border-image 。
在基于 Qt Widgets 的应用里,咱们能够经过 qss 来设置 border-image ,进而构造可伸缩的背景。

上图是 Qt 帮助里的,四条线把一张图片切成了 9 份,使用时,能够保持四个角不变,其它部分经过拉伸或平铺填充来适应界面空间大小。
好啦,基本的背景就这么多了,咱们来看一个简单的例子。
可伸缩界面示例
咱们先看效果后看代码。
效果图
下图是 PC 上的运行效果:

下图是手机上的效果,此时图片没有设置 devicePixelRatio 。

没有设置 devicePixelRatio ,图片看起来要小不少,对比它和文字,能够明显看出来比例失调。
下图是设置了 devicePixelRatio 的效果,看起来一致了。

代码分析
建立了一个基于 Qt Widgets 的 应用,名字是 scalabeUI ,建立了两个文件 sizeUtil.h 和 sizeUtil.cpp 。
项目里用到了两个图片资源:

图片我加到了 qrc 里。
sizeUtil.h 以下:
- #ifndef SIZEUTIL_H
- #define SIZEUTIL_H
- #include <QFont>
- #include <QString>
-
- class SizeUtil
- {
- private:
- SizeUtil(){}
- SizeUtil(const SizeUtil &);
- SizeUtil & operator=(const SizeUtil&);
- public:
- ~SizeUtil(){}
- static SizeUtil & instance();
- int defaultFontHeight();
- int widthWithDefaultFont(const QString &text);
- int widthWithFont(const QString &text, int fontPointSize);
- int fontHeight(int fontPointSize);
- float dpiFactor();
- };
-
- #endif // SIZEUTIL_H
sizeUtil.cpp 以下:
- #include "sizeUtil.h"
- #include <QApplication>
- #include <QFontMetrics>
- #include <QScreen>
-
- SizeUtil & SizeUtil::instance()
- {
- static SizeUtil util;
- return util;
- }
-
- int SizeUtil::defaultFontHeight()
- {
- return qApp->fontMetrics().height();
- }
-
- int SizeUtil::widthWithDefaultFont(const QString &text)
- {
- return qApp->fontMetrics().boundingRect(text).width();
- }
-
- int SizeUtil::widthWithFont(const QString &text, int fontPointSize)
- {
- QFont f = qApp->font();
- f.setPointSize(fontPointSize);
- QFontMetrics fm(f);
- return fm.boundingRect(text).width();
- }
-
- int SizeUtil::fontHeight(int fontPointSize)
- {
- QFont f = qApp->font();
- f.setPointSize(fontPointSize);
- QFontMetrics fm(f);
- return fm.height();
- }
-
- float SizeUtil::dpiFactor()
- {
- QScreen *screen = qApp->primaryScreen();
- return 72 / screen->logicalDotsPerInch();
- }
SizeUtil 类主要是用来计算文本的像素大小。
新建项目向导给咱们生成了 widget.cpp 和 widget.h ,我修改了一下 widget.cpp ,针对文字、图片、背景三种状况,作了处理。代码以下:
- #include "widget.h"
- #include <QVBoxLayout>
- #include <QHBoxLayout>
- #include <QLabel>
- #include <QPushButton>
- #include "sizeUtil.h"
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- {
- QVBoxLayout *layout = new QVBoxLayout(this);
-
-
- QLabel *label = new QLabel("Hello Scalable Label");
- layout->addWidget(label, 1);
-
- label->setStyleSheet(
- "QLabel{border-image:url(:/bkgnd.9.png) 38 6 6 16;"
- " border-left-width: 16; border-top-width: 38;"
- " border-right-width: 6; border-bottom-width: 6}");
-
-
- QLabel *head = new QLabel;
- QPixmap orig(":/head.png");
- orig.setDevicePixelRatio(SizeUtil::instance().dpiFactor());
- head->setPixmap(orig);
- layout->addWidget(head);
-
-
- QHBoxLayout *hlayout = new QHBoxLayout;
- layout->addLayout(hlayout);
- QPushButton *button = new QPushButton("Text Button");
- hlayout->addWidget(button);
- hlayout->addStretch(1);
- }
-
- Widget::~Widget()
- {
-
- }
这就是代码的所有了,虽然简单,基本能够说明问题了。
博客之星评选,点击投我一票,谢谢。投过了也能够点哦,天天均可以投投一票。
完整的项目代码能够在这里下载:点击下载。
其余精彩文章文章