[Qt]不带标题栏(FramelessWindowHint)的窗体移动及调整大小
Qt窗体若设置了
setWindowFlags (Qt::FramelessWindowHint);
运行后该窗体是无法进行移动和调整大小的,那要如何才能让它和普通窗体一样进行移动和调整其大小的呢?方案如下:
void QFramelessWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
this->m_drag = true;
this->dragPos = event->pos();
this->resizeDownPos = event->globalPos();
this->mouseDownRect = this->rect();
}
}
void QFramelessWindow::mouseMoveEvent(QMouseEvent * event)
{
if (resizeRegion != Default)
{
handleResize();
return;
}
if(m_move) {
move(event->globalPos() - dragPos);
return;
}
QPoint clientCursorPos = event->pos();
QRect r = this->rect();
QRect resizeInnerRect(resizeBorderWidth, resizeBorderWidth, r.width() - 2*resizeBorderWidth, r.height() - 2*resizeBorderWidth);
if(r.contains(clientCursorPos) && !resizeInnerRect.contains(clientCursorPos)) { //调整窗体大小
ResizeRegion resizeReg = getResizeRegion(clientCursorPos);
setResizeCursor(resizeReg);
if (m_drag && (event->buttons() & Qt::LeftButton)) {
resizeRegion = resizeReg;
handleResize();
}
}
else { //移动窗体
setCursor(Qt::ArrowCursor);
if (m_drag && (event->buttons() & Qt::LeftButton)) {
m_move = true;
move(event->globalPos() - dragPos);
}
}
}
void QFramelessWindow::mouseReleaseEvent(QMouseEvent *event)
{
m_drag = false;
if(m_move) {
m_move = false;
handleMove(event->globalPos()); //鼠标放开后若超出屏幕区域自动吸附于屏幕顶部/左侧/右侧
}
resizeRegion = Default;
setCursor(Qt::ArrowCursor);
}
void QFramelessWindow::setResizeCursor(ResizeRegion region)
{
switch (region)
{
case North:
case South:
setCursor(Qt::SizeVerCursor);
break;
case East:
case West:
setCursor(Qt::SizeHorCursor);
break;
case NorthWest:
case SouthEast:
setCursor(Qt::SizeFDiagCursor);
break;
default:
setCursor(Qt::SizeBDiagCursor);
break;
}
}
ResizeRegion QFramelessWindow::getResizeRegion(QPoint clientPos)
{
if (clientPos.y() <= resizeBorderWidth) {
if (clientPos.x() <= resizeBorderWidth)
return NorthWest;
else if (clientPos.x() >= this->width() - resizeBorderWidth)
return NorthEast;
else
return North;
}
else if (clientPos.y() >= this->height() - resizeBorderWidth) {
if (clientPos.x() <= resizeBorderWidth)
return SouthWest;
else if (clientPos.x() >= this->width() - resizeBorderWidth)
return SouthEast;
else
return South;
}
else {
if (clientPos.x() <= resizeBorderWidth)
return West;
else
return East;
}
}
void QFramelessWindow::handleMove(QPoint pt)
{
QPoint currentPos = pt - dragPos;
if(currentPos.x()<desktop->x()) { //吸附于屏幕左侧
currentPos.setX(desktop->x());
}
else if (currentPos.x()+this->width()>desktop->width()) { //吸附于屏幕右侧
currentPos.setX(desktop->width()-this->width());
}
if(currentPos.y()<desktop->y()) { //吸附于屏幕顶部
currentPos.setY(desktop->y());
}
move(currentPos);
}
void QFramelessWindow::handleResize()
{
int xdiff = QCursor::pos().x() - resizeDownPos.x();
int ydiff = QCursor::pos().y() - resizeDownPos.y();
switch (resizeRegion)
{
case East:
{
resize(mouseDownRect.width()+xdiff, this->height());
break;
}
case West:
{
resize(mouseDownRect.width()-xdiff, this->height());
move(resizeDownPos.x()+xdiff, this->y());
break;
}
case South:
{
resize(this->width(),mouseDownRect.height()+ydiff);
break;
}
case North:
{
resize(this->width(),mouseDownRect.height()-ydiff);
move(this->x(), resizeDownPos.y()+ydiff);
break;
}
case SouthEast:
{
resize(mouseDownRect.width() + xdiff, mouseDownRect.height() + ydiff);
break;
}
case NorthEast:
{
resize(mouseDownRect.width()+xdiff, mouseDownRect.height()-ydiff);
move(this->x(), resizeDownPos.y()+ydiff);
break;
}
case NorthWest:
{
resize(mouseDownRect.width()-xdiff, mouseDownRect.height()-ydiff);
move(resizeDownPos.x()+xdiff, resizeDownPos.y()+ydiff);
break;
}
case SouthWest:
{
resize(mouseDownRect.width()-xdiff, mouseDownRect.height()+ydiff);
move(resizeDownPos.x()+xdiff, this->y());
break;
}
}
}
本文的方案还附加了一个自动吸附功能,各位如果不需要的话,可以移除。
附上全局枚举及变量:
enum ResizeRegion
{
Default,
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest
};
bool m_drag, m_move;
QPoint dragPos, resizeDownPos;
const int resizeBorderWidth = 5;
ResizeRegion resizeRegion;
QRect mouseDownRect;
最后郑重提醒:别忘了在构造函数加上这句setMouseTracking(true); 切记切记!!!