QML實現的無邊框視窗的拉伸,拖拽,基本解決閃爍嚴重問題
阿新 • • 發佈:2019-01-06
使用qt製作的無邊框視窗,只需在其flag中加入FramelessWindowHint。
然而,無邊框視窗意味著,無法使用原有的邊框拉伸,拖拽功能。
在qwidget中,有很多實現的方法,比如重寫
+ mouseMoveEvent(QMouseEvent *event)+ mousePressEvent(QMouseEvent *event)
+ mouseReleaseEvent(QMouseEvent *event)
這幾個事件即可很容易的完成無邊框視窗的拉伸,拖拽功能。ps :重寫nativeEvent(const QByteArray &eventType, void *message
但是在qml,由於qwindow和qwidget的實現方式完全不同,而qquickwindow繼承自qwindow,使用上述的方法當然也可以如widget一樣的工作,然鵝經過測試閃爍嚴重,體驗極差,於是就有了另一種方法。
直接使用MouseArea進行拉伸,拖拽。
qml程式碼如下:
import QtQuick 2.7 /* ↑ ↑ ↑ ←|1| |2| |3|→ ←|4| |5| |6|→ ←|7| |8| |9|→ ↓ ↓ ↓ 分8個縮放區域 |5|為拖動區域 target 縮放目標 startPoint 滑鼠起始點 fixedPont 用於固定視窗的點 每一個area 大小 8 x 8 */ Item { id: area property var target: undefined; property point startPoint: Qt.point(0, 0); property point fixedPont: Qt.point(0, 0); MouseArea { id: area1 x: 0 y: 0 width: 8 height: 8 hoverEnabled: true onEntered: cursorShape = Qt.SizeFDiagCursor; onExited: cursorShape = Qt.ArrowCursor; onPressed: startPoint = Qt.point(mouseX, mouseY); onPositionChanged: { if(pressed) { var offsetX = mouse.x - startPoint.x; var offsetY = mouse.y - startPoint.y; if ((target.width - offsetX) >= target.minimumWidth) //如果本次調整小於最小限制,則調整為最小 { target.width -= offsetX; target.x += offsetX; } else { target.x += (target.width - target.minimumWidth); target.width -= (target.width - target.minimumWidth); } if ((target.height - offsetY) >= target.minimumHeight && offsetY != 0) { target.height -= offsetY; target.y += offsetY; } } } } MouseArea { id: area2 x: 8 y: 0 width: target.width - 16 height: 8 hoverEnabled: true onEntered: cursorShape = Qt.SizeVerCursor; onExited: cursorShape = Qt.ArrowCursor; onPressed: startPoint = Qt.point(mouseX, mouseY); onPositionChanged: { if(pressed) { var offsetY = mouse.y - startPoint.y; if ((target.height - offsetY) >= target.minimumHeight && offsetY != 0) { target.height -= offsetY; target.y += offsetY; } } } } MouseArea { id: area3 x: target.width - 8 y: 0 width: 8 height: 8 hoverEnabled: true onEntered: cursorShape = Qt.SizeBDiagCursor; onExited: cursorShape = Qt.ArrowCursor onPressed: { startPoint = Qt.point(mouseX, mouseY); fixedPont = Qt.point(target.x, target.y) } onPositionChanged: { if(pressed) { var offsetX = mouse.x - startPoint.x; var offsetY = mouse.y - startPoint.y; print (offsetX, offsetY) if ((target.width + offsetX) >= target.minimumWidth && offsetX != 0) { target.width += offsetX; target.x = fixedPont.x; } if ((target.height - offsetY) >= target.minimumHeight && offsetY != 0) { target.height -= offsetY; target.y += offsetY; } } } } MouseArea { id: area4 x: 0 y: 8 width: 8 height: target.height - 16 hoverEnabled: true onEntered: cursorShape = Qt.SizeHorCursor; onExited: cursorShape = Qt.ArrowCursor; onPressed: { startPoint = Qt.point(mouseX, mouseY); } onPositionChanged: { if(pressed) { var offsetX = mouse.x - startPoint.x; if ((target.width - offsetX) >= target.minimumWidth) { target.width -= offsetX; target.x += offsetX; } } } } MoveMouseArea { id: area5 x: 8 y: 8 width: area.target.width - 16 height: area.target.height - 16 target: area.target } MouseArea { id: area6 x: target.width - 8 y: 8 width: 8 height: target.height - 16 hoverEnabled: true property real fixedX: 0; onEntered: cursorShape = Qt.SizeHorCursor; onExited: cursorShape = Qt.ArrowCursor; onPressed: { startPoint = Qt.point(mouseX, mouseY); fixedPont = Qt.point(target.x, target.y) } onPositionChanged: { if(pressed) { var offsetX = mouse.x - startPoint.x; if ((target.width + offsetX) >= target.minimumWidth && offsetX != 0) { target.width += offsetX; target.x = fixedPont.x; } } } } MouseArea { id: area7 x: 0 y: target.height - 8 width: 8 height: target.height - 16 hoverEnabled: true property real fixedX: 0; onEntered: cursorShape = Qt.SizeBDiagCursor; onExited: cursorShape = Qt.ArrowCursor; onPressed: { startPoint = Qt.point(mouseX, mouseY); fixedPont = Qt.point(target.x, target.y) } onPositionChanged: { if (pressed) { var offsetX = mouse.x - startPoint.x; var offsetY = mouse.y - startPoint.y; if ((target.width - offsetX) >= target.minimumWidth && offsetX != 0) { target.width -= offsetX; target.x += offsetX; } if ((target.height + offsetY) >= target.minimumHeight && offsetY != 0) { target.height += offsetY; target.y = fixedPont.y; } } } } MouseArea { id: area8 x: 8 y: target.height - 8 width: target.height - 16 height: 8 hoverEnabled: true property real fixedX: 0; onEntered: cursorShape = Qt.SizeVerCursor; onExited: cursorShape = Qt.ArrowCursor; onPressed: { startPoint = Qt.point(mouseX, mouseY); fixedPont = Qt.point(target.x, target.y) } onPositionChanged: { if (pressed) { var offsetY = mouse.y - startPoint.y; if ((target.height + offsetY) >= target.minimumHeight && offsetY != 0) { target.height += offsetY; target.y = fixedPont.y; } } } } MouseArea { id: area9 x: target.width - 8 y: target.height - 8 width: 8 height: 8 hoverEnabled: true onEntered: cursorShape = Qt.SizeFDiagCursor; onExited: cursorShape = Qt.ArrowCursor onPressed: { startPoint = Qt.point(mouseX, mouseY); fixedPont = Qt.point(target.x, target.y) } onPositionChanged: { if(pressed) { var offsetX = mouse.x - startPoint.x; var offsetY = mouse.y - startPoint.y; if ((target.width + offsetX) >= target.minimumWidth && offsetX != 0) { target.width += offsetX; target.x = fixedPont.x; } if ((target.height + offsetY) >= target.minimumHeight && offsetY != 0) { target.height += offsetY; target.y = fixedPont.y; } } } } }
還有很多判斷minimum,maximum什麼的沒有寫全,但很簡單,就不多展示了。
其中的MoveMouseArea為:
import QtQuick 2.7 MouseArea { hoverEnabled: true property var target: undefined; property point startPoint: Qt.point(0, 0); property point offsetPoint: Qt.point(0, 0); onPressed: { cursorShape = Qt.SizeAllCursor; startPoint = Qt.point(mouseX, mouseY); } onPositionChanged: { if(pressed) { offsetPoint = Qt.point(mouse.x - startPoint.x, mouse.y - startPoint.y); target.x = target.x + offsetPoint.x; target.y = target.y + offsetPoint.y; } } onReleased: { cursorShape = Qt.ArrowCursor; } }
因為在其他地方並不需要拉伸操作,所以將區域|5|單獨作為一個qml檔案使用。
還有一點關於qml,閃爍嚴重的一部分原因是使用了anchors定位引起的,所以在視窗中的最底層的item使用座標方式進行定位。其他item則不用。
可以測試一下,還算可以,基本可以使用了,但仍然達不到widget那麼流暢完美的程度。