mafulechka
mafulechka18 березня 2020 р. 06:01

Користувальницькі оформлення вікон на стороні клієнта Qt 5.15

Це свіжі новини про нову функцію в Qt 5.15, яка дуже порадувала.

Зазвичай оформлення вікон були досить нудною річчю. Заголовок, обмежити, мінімізувати, максимізувати, змінити розмір, вийти... і все.


Однак, останнім часом програми все частіше і частіше включають інтерфейс користувача (application specific UI) і оформлення тем. Пара скріншотів для пояснення, про що тут йдеться:

MacOS займається цим досить давно.

... і Chrome, і будь-який інший веб-браузер.

Вбудовування меню в оформлення може заощадити багато місця на екрані.

... або це може бути важливим для брендингу або дизайну.
На жаль, подібні речі раніше не були можливі з Qt.
Однак можна було прибрати оформлення з вікна, тобто:

Window {
    flags: Qt.FramelessWindowHint
}

Але це тільки залишило вас із вікном без оформлення. Таким чином, це не могло бути переміщене або змінене. Якщо б ви спробували реалізувати рух вікна або змінити розмір, схопивши мишу і вручну встановивши розмір і положення вікна, ви швидко виявили б, що це не дуже добре. Менеджери вікон зазвичай мають дуже специфічну поведінку при переміщенні або зміні розмірів вікон. Звичайні дії: перетягування вгору, щоб максимізувати, перетягування ліворуч/праворуч на плитку, прив'язка до інших вікон або панелі завдань, зміна розмірів двох вікон одночасно, якщо вони розташовані поруч один з одним і так далі.

Заради справедливості, раніше був наданий один помічник - QSizeGrip. Він дозволяє змінити розмір будь-якого заданого кута вікна, але працює тільки з кутами, а не з межами вікна, і доступний тільки для програм віджетів.

У Qt 5.15 було додано два нових методи QWindow: startSystemMove і startSystemResize. Ці методи просять віконний менеджер вступити у володіння та розпочати власну операцію зміни розміру чи переміщення. Це означає, що прив'язка, розбиття на тайли і так далі повинні працювати просто чарівним чином, а реалізація заголовка в QML стає майже однорядковою:

DragHandler {
    onActiveChanged: if (active) window.startSystemMove();
    target: null
}

Помістивши цей фрагмент коду елемент QtQuick, всі тригер операції перетягування викличуть операцію переміщення власного вікна.
startSystemResize працює аналогічно, за винятком того, що він приймає аргумент Qt::Edges, який є бітовим полем меж вікна, які ви захопили, тобто для нижнього правого кута, ви б викликали:

startSystemResize(Qt.RightEdge | Qt.BottomEdge)

Це також дуже зручно, так як ви можете легко мати один обробник для всіх чотирьох меж вікна і просто створити аргумент кордону наступним чином:

DragHandler {
    id: resizeHandler
    grabPermissions: TapHandler.TakeOverForbidden
    target: null
    onActiveChanged: if (active) {
        const p = resizeHandler.centroid.position;
        let e = 0;
        if (p.x < border) e |= Qt.LeftEdge;
        if (p.x >= width - border) e |= Qt.RightEdge;
        if (p.y < border) e |= Qt.TopEdge;
        if (p.y >= height - border) e |= Qt.BottomEdge;
        window.startSystemResize(e);
    }
}

Якщо ви хочете отримати повний приклад того, як це можна використовувати, було зроблено макет браузера з використанням нового API.

Зверніть увагу, що, хоча це кроссплатформенний API, не всі платформи підтримують його. startSystemMove в даний час підтримується в Wayland, X11, macOS і Windows, а startSystemResize, з іншого боку, підтримується в Wayland, X11 і Windows, але не в macOS.

Щоб упоратися з цим, обидва методи повертають логічне значення, яке вказує, чи була операція підтримана чи ні. Це означає, що якщо ви хочете реалізувати зміну розміру і в macOS, вам доведеться перевірити значення startSystemResize, що повертається, і постаратися зробити все можливе, щоб реалізувати запасний варіант у разі збою, тобто:

if (!window.startSystemResize(edges)) {
    // your fallback code for setting window.width/height manually
}

Подальша робота в Qt буде полягати в тому, щоб надати запасні варіанти або абстракції, які зробили б цю роботу за вас, але, принаймні, ніщо не повинно завадити вам зробити це самостійно.

Інша область покращення - узгодження з віконним менеджером у тому, чи слід використовувати оформлення на стороні клієнта або сервері. Деякі програми можуть захотіти підтримувати обидва режими і дозволити віконному менеджеру вирішувати, але це неможливо. Після встановлення FramelessWindowHint оформлення на стороні сервера не буде.

Третя область – тінь вікна. Принаймні на Wayland тінь має бути намальована як частина оформлення вікна. І хоча можна малювати тіні за допомогою QtQuick, в даний час немає способу повідомити плагін QPA, яка частина поверхні є тінню, а яка - віконною рамкою, що означає, що, якщо ви спробуєте намалювати тіні, менеджер вікон в даний час буде розглянути тіньову частину вікна, і це зіпсує мозаїку та прив'язку з іншими вікнами. На інших платформах диспетчер вікон зазвичай малює тіні навіть для вікон, оформлених на стороні клієнта, тому цю проблему складно вирішити.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
d
  • dsfs
  • 26 квітня 2024 р. 04:56

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
d
  • dsfs
  • 26 квітня 2024 р. 04:45

C++ - Тест 002. Константы

  • Результат:50бали,
  • Рейтинг балів-4
d
  • dsfs
  • 26 квітня 2024 р. 04:35

C++ - Тест 001. Первая программа и типы данных

  • Результат:73бали,
  • Рейтинг балів1
Останні коментарі
k
kmssr08 лютого 2024 р. 18:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 01:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 10:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 08:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 грудня 2023 р. 21:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi02 травня 2024 р. 14:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderChe30 квітня 2024 р. 04:22
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…
G
Gar22 квітня 2024 р. 05:46
Clipboard Как скопировать окно целиком в clipb?
Павел Дорофеев
Павел Дорофеев14 квітня 2024 р. 02:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex04 квітня 2024 р. 04:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Слідкуйте за нами в соціальних мережах