Qt on Android:建立可伸縮介面,qtandroid

來源:互聯網
上載者:User

Qt on Android:建立可伸縮介面,qtandroid

  使用 Qt 來開發 Android 應用,也需要適配不同行動裝置,適配多種多樣的螢幕和解析度。這次我們大概來講一下如何使用 Qt 提供的機制來建立可伸縮的介面。

DPI

    必須要解釋一下 DPI 。

    DPI , dot per inch ,即每英寸包含的點數。還有一個概念是 PPI ,即每英寸包含的像素數。

    這個值越大,像素密度越大,小尺寸的螢幕就可以有大解析度。比如有的 Android 手機, 3.7 吋螢幕就能提供 960x540 的解析度,而有的手機, 5 吋螢幕卻提供 800x480 的解析度。這兩種不同螢幕的尺寸和解析度的手機,5 吋屏看起來會有顆粒感,而 3.7 吋看起來則非常細膩。這就是像素密度帶來的差別。

    DPI 對介面的影響是醬紫的:同樣解析度(按像素來說)的圖片,在 DPI 越大的螢幕上,看起來就越小。

三類可伸縮元素

    一個 Qt 行動裝置 App,大概有三類可伸縮 UI 元素:

 

  • 文字
  • 圖片
  • 背景

 

    我們分別來看一下。

文字

    對於文字來講,我們只需要設定特定的文本顯示和輸入控制項所使用的字型(QFont)的 pointSize 即可。像 QLabel 、 QPushButton 、 QLineEdit 等等都適用這種方式。

    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
  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
  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
  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
  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 )

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.