Qt on Android:建立可伸縮介面

來源:互聯網
上載者:User

標籤:qt for android   qt on android   android   

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

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);    //case 1. background    QLabel *label = new QLabel("Hello Scalable Label");    layout->addWidget(label, 1);    /* top right bottom left */    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}");    //case 2. image    QLabel *head = new QLabel;    QPixmap orig(":/head.png");    orig.setDevicePixelRatio(SizeUtil::instance().dpiFactor());    head->setPixmap(orig);    layout->addWidget(head);    //case 3. text button    QHBoxLayout *hlayout = new QHBoxLayout;    layout->addLayout(hlayout);    QPushButton *button = new QPushButton("Text Button");    hlayout->addWidget(button);    hlayout->addStretch(1);}Widget::~Widget(){}

    這就是代碼的全部了,雖然簡單,基本可以說明問題了。


    部落格之星評選,點擊投我一票,謝謝。投過了也可以點哦,每天都可以投投一票。

    完整的項目代碼可以在這裡下載:點擊下載。


------------回顧一下 Qt on Android 系列:

  • Qt on Android:圖文詳解Hello World全過程
  • Windows下Qt 5.2 for Android開發入門
  • Qt for Android 部署流程分析
  • Qt on Android:將Qt調試資訊輸出到logcat中
  • Qt on Android: Qt 5.3.0 發布,針對 Android 改進說明
  • Qt on Android Episode 1(翻譯)
  • Qt on Android Episode 2(翻譯)
  • Qt on Android Episode 3(翻譯)
  • Qt on Android Episode 4(翻譯)
  • Qt for Android 編譯純C工程
  • Windows下Qt for Android 編譯安卓C語言可執行程式
  • Qt on Android: Android SDK安裝
  • Qt on Android: http下載與Json解析
  • Qt on Android 之設定應用程式名稱為中文
  • Qt on Android:讓 Qt Widgets 和 Qt Quick 應用全螢幕顯示
  • Qt on Android:怎樣適應不同的螢幕尺寸
  •  Qt on Android:使用JNI與第三方jar包
  • 《Qt on Android核心編程》介紹
  • Qt on Android:資源檔系統qrc與assets

  • Qt on Android:建立可伸縮介面

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.