- 1. main.qml
Wenn Sie sich aus irgendeinem Grund dazu entschließen, die Fensterrahmen des Standardsystems aufzugeben und alle Fenstertitelleisten selbst in QML zu implementieren, können Sie dies problemlos mit QML implementieren, was meiner Meinung nach noch einfacher als in C ++ sein wird. Als Referenz können Sie den Artikel zur Anpassung von Anwendungsfenstern im AIMP-Stil lesen. Es gibt eine beträchtliche Menge an Code zum Implementieren der Mechanik zum Verschieben des Fensters sowie zum Ändern der Größe. Der Vorteil von QML liegt in diesem Fall darin, dass QML sofort das Layout der Anwendung bereitstellt, d. h. Sie können mit Hilfe von MouseArea und Ankern sofort die notwendige Verarbeitung beim Klicken und Bewegen der Maus ohne spezielle Berechnungen für die Position von bestimmen den Cursor im Fensterbereich.
Und die Mechanik zur Berechnung von Größen- und Positionsänderungen ähnelt der, die im Artikel zum Anpassen einer Anwendung in C ++ verwendet wurde. Das heißt, es ist notwendig, sich die Position zu merken, an der die Maustaste gedrückt wurde, und dann die Größe des Anwendungsfensters zu ändern und relativ zu dieser Position zu verschieben, bis die Maustaste losgelassen wird.
Wie Sie in der obigen Abbildung sehen können, müssen Sie 5 MouseAreas erstellen, von denen vier für die Größenänderung der Anwendung und die fünfte zentrale für das Verschieben der Anwendung verantwortlich sind. Das heißt, es ist möglich, die Anwendung zu verschieben, indem Sie die Maustaste irgendwo im fünften zentralen Bereich gedrückt halten.
Wenn Sie eine spezielle Titelleiste benötigen, kann diese auch für das Verschieben des Anwendungsfensters verantwortlich sein. Das heißt, es ist nicht erforderlich, den gesamten mittleren Bereich bewegungsempfindlich zu machen.
main.qml
Die Anwendung wird standardmäßig erstellt und nur die Datei main.qml wird geändert, was ich als Beispiel geben werde.
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 ApplicationWindow { id: mainWindow visible: true width: 640 height: 480 flags: Qt.FramelessWindowHint // Отключаем обрамление окна // Объявляем свойства, которые будут хранить позицию зажатия курсора мыши property int previousX property int previousY MouseArea { id: topArea height: 5 anchors { top: parent.top left: parent.left right: parent.right } // Устанавливаем форму курсора, чтобы было понятно, что это изменение размера cursorShape: Qt.SizeVerCursor onPressed: { // Запоминаем позицию по оси Y previousY = mouseY } // При изменении позиции делаем пересчёт позиции окна, и его высоты onMouseYChanged: { var dy = mouseY - previousY mainWindow.setY(mainWindow.y + dy) mainWindow.setHeight(mainWindow.height - dy) } } // Аналогичные расчёты для остальных трёх областей ресайза MouseArea { id: bottomArea height: 5 anchors { bottom: parent.bottom left: parent.left right: parent.right } cursorShape: Qt.SizeVerCursor onPressed: { previousY = mouseY } onMouseYChanged: { var dy = mouseY - previousY mainWindow.setHeight(mainWindow.height + dy) } } MouseArea { id: leftArea width: 5 anchors { top: topArea.bottom bottom: bottomArea.top left: parent.left } cursorShape: Qt.SizeHorCursor onPressed: { previousX = mouseX } onMouseXChanged: { var dx = mouseX - previousX mainWindow.setX(mainWindow.x + dx) mainWindow.setWidth(mainWindow.width - dx) } } MouseArea { id: rightArea width: 5 anchors { top: topArea.bottom bottom: bottomArea.top right: parent.right } cursorShape: Qt.SizeHorCursor onPressed: { previousX = mouseX } onMouseXChanged: { var dx = mouseX - previousX mainWindow.setWidth(mainWindow.width + dx) } } // Центральная область для перемещения окна приложения // Здесь уже потребуется использовать положение как по оси X, так и по оси Y MouseArea { anchors { top: topArea.bottom bottom: bottomArea.top left: leftArea.right right: rightArea.left } onPressed: { previousX = mouseX previousY = mouseY } onMouseXChanged: { var dx = mouseX - previousX mainWindow.setX(mainWindow.x + dx) } onMouseYChanged: { var dy = mouseY - previousY mainWindow.setY(mainWindow.y + dy) } } }
Огромное спасибо
Драсте, спасибо за хороший урок.
Это скорее всего баг Qt под конкретной операционной системой. Какую используете?
Дело в том, что я проверил Ваш код под свой рабочей системой (KDE Neon 5.8) и всё работает стабильно, без нареканий. То есть минимизация окна происходит без проблем. Под Windows проверить не могу, на данный момент у меня нет рабочих установок этой системы.
Использую Windows 7 Ultimate.
Тогда это однознано баг, я бы глянул на официальном багтрекере Qt, есть ли информация об этом баге, и возможно стоит создать таск с этим багом.
Спасибо! Этим и займусь. Ещё попробую скинуть проект другу, посмотрю, как QT будет справляться там.
После отключения системного обрамления не работают minimumHeight и minimumWidth. Что делать?
Задать свои property в окне и проверять их в методах изменения размера для topArea, bottomArea, rightArea, leftArea.
Еще не могли бы подсказать как сделать чтобы отображалась иконка, так как она тоже исчезла. Весь интернет обыскал так и не нашел решения.
Какая иконка? Которая была в оформлении окна? Ну всё логично, оформление отключили - иконка исчезла. Хотите иконку, придётся самосттоятельно добавить её в левый верхний угол окна через какой-нибудь QML тип Image.
Извиняюсь за не точность. Я имел в виду иконку в Taskbar.
Вы же под Windows пишете? Есть такой класс QWinTaskbarButton, у него есть property overlayIcon . Возможно, стоит поработать с этим клсассом и установить туда иконку. Вот в этой статье есть пример работы с этим QWinTaskbarButton .
Огромное спасибо, работает.
Я бы вместо совытий mouseXChanged и mouseYChanged использовал positionChanged, так как у двух первых есть один недостаток, они производные от mouseX и Y которые содержат текущие координаты X и Y соответсвенно - это значит что они обновляются (записываются) регулярно при нажатой кнопки мыши (если свойство hoverEnabled будет true то они будут обновляться и без нажатия кнопок мыши). Это значит, что эти свойства вызывают ложную логику, если вы еще не двигали курсор мыши, а просто нажали кнопку мыши. В то время как positionChanged срабатывает только когда положение курсора в действительности было изменено при нажатой кнопки мыши (если hoverEnabled = false, опять же).
Здравствуйте. Сделал подобным образом ресайз и в Qt Widgets, и в QML. Везде получаю, что при изменении размера через левую или верхннюю границы проихсодит мерцание подобно как на этом видео . Всё перелопатил, нигде ответа не нашел. Не знаете как это победить?
Добрый день. Нет, если сами по себе координаты при ресайзе все подсчитываются правильно, то это уже проблема графической подсистемы в ОС и работы с X11, если вы конечно под Linux собирали проект. В том видео в исходниках крутят платформозависимые флаги. На тему тех флагов есть Bug на багтрекере Qt . Возможно также локальная проблема с конкретным дистрибутивом, если на мейнстримовых дистрибутивах всё работает хорошо. В общем скорее всего это та помойка, в которой не хотелось бы копаться.