Qt on Android:建立可伸縮界面

  使用 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)來計算,下面是示例代碼:

 

[cpp]  view plaincopy在CODE上查看代碼片派生到個人代碼片
  1. float SizeUtil::dpiFactor()  
  2. {  
  3.     QScreen *screen = qApp->primaryScreen();  
  4.     return 72 / screen->logicalDotsPerInch();  
  5. }  

 

    我在後面的示例中用了上面的方法。

    要說明的是,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 以下:

 

[cpp]  view plaincopy在CODE上查看代碼片派生到個人代碼片
  1. #ifndef SIZEUTIL_H  
  2. #define SIZEUTIL_H  
  3. #include <QFont>  
  4. #include <QString>  
  5.   
  6. class SizeUtil  
  7. {  
  8. private:  
  9.     SizeUtil(){}  
  10.     SizeUtil(const SizeUtil &);  
  11.     SizeUtil & operator=(const SizeUtil&);  
  12. public:  
  13.     ~SizeUtil(){}  
  14.     static SizeUtil & instance();  
  15.     int defaultFontHeight();  
  16.     int widthWithDefaultFont(const QString &text);  
  17.     int widthWithFont(const QString &text, int fontPointSize);  
  18.     int fontHeight(int fontPointSize);  
  19.     float dpiFactor();  
  20. };  
  21.   
  22. #endif // SIZEUTIL_H  


    sizeUtil.cpp 以下:

 

 

[cpp]  view plaincopy在CODE上查看代碼片派生到個人代碼片
  1. #include "sizeUtil.h"  
  2. #include <QApplication>  
  3. #include <QFontMetrics>  
  4. #include <QScreen>  
  5.   
  6. SizeUtil & SizeUtil::instance()  
  7. {  
  8.     static SizeUtil util;  
  9.     return util;  
  10. }  
  11.   
  12. int SizeUtil::defaultFontHeight()  
  13. {  
  14.     return qApp->fontMetrics().height();  
  15. }  
  16.   
  17. int SizeUtil::widthWithDefaultFont(const QString &text)  
  18. {  
  19.     return qApp->fontMetrics().boundingRect(text).width();  
  20. }  
  21.   
  22. int SizeUtil::widthWithFont(const QString &text, int fontPointSize)  
  23. {  
  24.     QFont f = qApp->font();  
  25.     f.setPointSize(fontPointSize);  
  26.     QFontMetrics fm(f);  
  27.     return fm.boundingRect(text).width();  
  28. }  
  29.   
  30. int SizeUtil::fontHeight(int fontPointSize)  
  31. {  
  32.     QFont f = qApp->font();  
  33.     f.setPointSize(fontPointSize);  
  34.     QFontMetrics fm(f);  
  35.     return fm.height();  
  36. }  
  37.   
  38. float SizeUtil::dpiFactor()  
  39. {  
  40.     QScreen *screen = qApp->primaryScreen();  
  41.     return 72 / screen->logicalDotsPerInch();  
  42. }  


    SizeUtil 類主要是用來計算文本的像素大小。

 

    新建項目嚮導給咱們生成了 widget.cpp 和 widget.h ,我修改了一下 widget.cpp ,針對文字、圖片、背景三種狀況,作了處理。代碼以下:

 

[cpp]  view plaincopy在CODE上查看代碼片派生到個人代碼片
  1. #include "widget.h"  
  2. #include <QVBoxLayout>  
  3. #include <QHBoxLayout>  
  4. #include <QLabel>  
  5. #include <QPushButton>  
  6. #include "sizeUtil.h"  
  7.   
  8. Widget::Widget(QWidget *parent)  
  9.     : QWidget(parent)  
  10. {  
  11.     QVBoxLayout *layout = new QVBoxLayout(this);  
  12.   
  13.     //case 1. background  
  14.     QLabel *label = new QLabel("Hello Scalable Label");  
  15.     layout->addWidget(label, 1);  
  16.     /* top right bottom left */  
  17.     label->setStyleSheet(  
  18.                 "QLabel{border-image:url(:/bkgnd.9.png) 38 6 6 16;"  
  19.                 " border-left-width: 16; border-top-width: 38;"  
  20.                 " border-right-width: 6; border-bottom-width: 6}");  
  21.   
  22.     //case 2. image  
  23.     QLabel *head = new QLabel;  
  24.     QPixmap orig(":/head.png");  
  25.     orig.setDevicePixelRatio(SizeUtil::instance().dpiFactor());  
  26.     head->setPixmap(orig);  
  27.     layout->addWidget(head);  
  28.   
  29.     //case 3. text button  
  30.     QHBoxLayout *hlayout = new QHBoxLayout;  
  31.     layout->addLayout(hlayout);  
  32.     QPushButton *button = new QPushButton("Text Button");  
  33.     hlayout->addWidget(button);  
  34.     hlayout->addStretch(1);  
  35. }  
  36.   
  37. Widget::~Widget()  
  38. {  
  39.   
  40. }  

 

    這就是代碼的所有了,雖然簡單,基本能夠說明問題了。

 

    博客之星評選,點擊投我一票,謝謝。投過了也能夠點哦,天天均可以投投一票。

    完整的項目代碼能夠在這裏下載:點擊下載

其餘精彩文章文章

 

在 android dialog中使用Autocompletetext 
大型網站架構設計-Solr mysql哈希索引
android學習筆記(32)網格視圖(GridView )和圖形切換器(ImageSwi...
android學習筆記(31)可展開的列表組件(ExpandableListView )
相關文章
相關標籤/搜索