Russian Qt Forum
Апрель 24, 2024, 03:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QML и resolution independence  (Прочитано 7578 раз)
vregess
Гость
« : Сентябрь 09, 2014, 12:43 »

Разъясните, кто в теме. Хочется иметь одинаковые размеры элементов на разных экранах для мобильного приложения.

Вот такой пример:

Код:
Item {
    width: 400
    height: 400

    ToolBar {
        id: toolBar
        anchors {left: parent.left; right: parent.right}
        height: 96
        RowLayout { ToolButton {text: "12"} }
    }

    Calendar {
        focus: true
        anchors {top: toolBar.bottom; left: parent.left; right: parent.right; bottom: parent.bottom}
    }
}


toolBar выглядит большим в qmlscene, чуть меньше на планшете с PPI 162 и более-менне совпадает с задуманным на телефоне с PPI 323.
Высоту toolBar - 96, брал из документации по android, где высота action bar указана как 48dp (Density-Independent pixel).
48 * 2 = 96, т.к. 48 оказалось очень мелко (как потом окажется *2 это корректное преобразование, если я все правильно понял).

Вот тут http://blog.qt.digia.com/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
вроде написано, что Qt5 теперь работает с Device-Independent Pixel.
Как я понимаю, Density-Independent = Device-Independent.

Так в каких единицах задаются размеры в QML?
Нужно ли городить преобразование единиц измерения?

Судя по тесту, надо преобразовывать в dp (Density-independent pixel), иначе высота в 48 попугаев смотрелась бы одинаково на всех экранах.
О чем тогда пишут по этой ссылке?


Провел такой эксперимент: выводил
Код
C++ (Qt)
QGuiApplication::primaryScreen()->devicePixelRatio()
QGuiApplication::primaryScreen()->logicalDotsPerInch()
QGuiApplication::primaryScreen()->physicalDotsPerInch()
Screen.pixelDensity (QML)
 
на разных устройствах.


PC:
devicePixelRatio        1
logicalDotsPerInch    96
physicalDotsPerInch  72.01772525849334
Screen.pixelDensity:  2.84 (physicalDotsPerInch / 25.4)

телефон с PPI 323:
devicePixelRatio       1
logicalDotsPerInch    144
physicalDotsPerInch  Infinity / 351.53782569631625 / 320
Screen.pixelDensity:  Infinity / 6.52 (physicalDotsPerInch / 25.4)

планшет с PPI 162:
devicePixelRatio        1
logicalDotsPerInch     72
physicalDotsPerInch   Infinity / 165.7143765614354
Screen.pixelDensity:  Infinity / 13.84 (physicalDotsPerInch / 25.4)

для телефона/планшета первое значение physicalDotsPerInch выводилось по Component.onCompleted, а второе по клику на кнопке.
Оказалось есть баг https://bugreports.qt-project.org/browse/QTBUG-35701. Поэтому я попробовал взять DPI на андройде нативным способом - это третье значение для телефона (320).

в общем сейчас преобразую размеры по формуле:
Код
C++ (Qt)
height = dp * physicalDotsPerInch / 160 * devicePixelRatio
 
где dp это наш размер.

Код
C++ (Qt)
height = 48 *physicalDotsPerInch / 160 * devicePixelRatio.
win: height = 48 * 72 / 160 * 1 = ~22
phone: height = 48 * 320 / 160 * 1 = 96
tablet: height = 48 * 162 / 160 * 1 = ~49
 

на iOS возможности проверить нет, на реальном девайсе. Там по идее devicePixelRatio будет = 2 и какой-то свой physicalDotsPerInch.

Корректно ли так преобразовывать и вообще как с этим бороться?
Записан
navrocky
Moderator
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #1 : Сентябрь 09, 2014, 13:06 »

Я не долго думая для себя написал функцию по аналогии того как это сделано в Blackberry SDK:

Utils.js
Код
.pragma library
 
var currentDensity = 1.0;
 
// convert pixel value to device units
function du(pixel) {
   return Math.ceil(currentDensity * pixel);
}

И везде через неё преобразовываю все размеры компонентов, шрифтов, радиусов и т.д.

Разбирательства с установкой правильного currentDensity я оставил на потом. Так что всё в процессе.
« Последнее редактирование: Сентябрь 09, 2014, 13:09 от navrocky » Записан

Гугль в помощь
vregess
Гость
« Ответ #2 : Сентябрь 09, 2014, 13:36 »

Я не долго думая для себя написал функцию по аналогии того как это сделано в Blackberry SDK:
И везде через неё преобразовываю все размеры компонентов, шрифтов, радиусов и т.д.
Разбирательства с установкой правильного currentDensity я оставил на потом. Так что всё в процессе.

Я тоже так сначала сделал, потом переделал в:
Код
C++ (Qt)
   Units units;
   ctx->setContextProperty(QStringLiteral("dp"), units.dpFactor());
   ctx->setContextProperty(QStringLiteral("mm"), units.mmFactor());
...
 
param: 42*mm
param2: 64*dp
 
Мне показалось это нагляднее, может чуток быстрее.
Но вопрос корректности преобразования пока открыт, хотя бы выяснить какими единицами оперирует QML.
Записан
kibsoft
Хакер
*****
Offline Offline

Сообщений: 625


Просмотр профиля WWW
« Ответ #3 : Сентябрь 09, 2014, 16:42 »

Код:
dp * physicalDotsPerInch / 160 * devicePixelRatio
На разных девайсах проверяли? Нормально работает? На планшетах?
Мне, чтобы нормально показывать и на телефонах, и на планшетах пришлось java код подключить.
Записан

http://kibsoft.ru - Download the Qt Media Encoding Library here

The apps that were written using QtMEL:
http://srecorder.com - Screen recording software
vregess
Гость
« Ответ #4 : Сентябрь 09, 2014, 16:53 »

На разных девайсах проверяли? Нормально работает? На планшетах?
Мне, чтобы нормально показывать и на телефонах, и на планшетах пришлось java код подключить.

Проверил пока только на одном телефоне и одном планшете. Вроде сносно. Скоро еще на паре устройств проверю.
Я тоже задействовал java - получаю physicalDotsPerInch от нее (в описании бага по ссылке есть код получения android.util.DisplayMetrics::densityDpi).
Правда на десктопе пришлось devicePixelRatio установить в 2, чтоб не мелко было.
Записан
kandrey
Гость
« Ответ #5 : Сентябрь 29, 2014, 20:29 »

я вот так задаю dp и sp

    readonly property var dir: ["mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi", "xxxxhdpi"]
    readonly property var ppiScales: [16/2, 16/3, 16/4, 16/6, 16/8, 16/16]
    readonly property int ppi: Screen.pixelDensity * 25.4
    readonly property int ppiRange: {
        if (ppi >= 540) 5
        else if (ppi >= 360) 4
        else if (ppi >= 270) 3
        else if (ppi >= 180) 2
        else if (ppi >= 135) 1
        else 0
    }
    readonly property real dp: 8 / ppiScales[ppiRange]
    readonly property real sp: dp

    property real microFontSize: 12 * sp
    property real smallFontSize: 14 * sp
    property real mediumFontSize: 16 * sp
    property real largeFontSize: 20 * sp

и все размеры типа  48 * dp
картинки тоже из иллюстратора скриптом для разных ppi
images/dir[ppiRange]/image.png

вроде нормально на разных экранах
« Последнее редактирование: Сентябрь 29, 2014, 21:14 от kandrey » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.216 секунд. Запросов: 24.