赞
踩
qt的无边框窗口可以很方便的设置样式,但是窗口设置成无边框后就无法拖动和拉伸了,之前参考过一些晚上的教程,大体方向是对的,但是细节上有很多问题,这里分享我写的无边框窗口。
新建一个QT工程,主界面是QWidget,命名为frameless
frameless的构造函数里添加 setWindowFlag(Qt::FramelessWindowHint);
现在运行就成无边框模式了,但是你会发现现在没有关闭按键,并且无法拖动拉伸。
我们先实现拖动功能。重载鼠标事件,增加一个变量记录上一次的位置,一个bool值标记左键被按下
#include <QtWidgets/QMainWindow>
#include "ui_frameless.h"
#include <QMouseEvent>class frameless : public QMainWindow
{
Q_OBJECTprivate:
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *event);public:
frameless(QWidget *parent = Q_NULLPTR);private:
Ui::framelessClass ui;QPoint last_point_; //记录放大之前的位置
QPoint last_position_; //窗口上一次的位置
bool left_button_pressed_ = false; //鼠标左键按下
};
增加鼠标事件的实现
void frameless::mouseMoveEvent(QMouseEvent * event)
{
if ((event->buttons() == Qt::LeftButton) && left_button_pressed_)
{
move(event->globalPos() - last_position_);
}
}void frameless::mouseReleaseEvent(QMouseEvent *)
{
left_button_pressed_ = false;
}void frameless::mousePressEvent(QMouseEvent * event)
{
if (event->buttons() == Qt::LeftButton) {
left_button_pressed_ = true;
last_position_ = event->globalPos() - pos();
}
}
现在运行,可以拖动自如了。
接下来实现拉伸功能。思路如下,将窗口分成九个部分,
左上角(1,1)、中上(1,2)、右上角(1,3)
左中 (2,1)、 中间(2,2)、右中 (2,3)
左下角(3,1)、中下(3,2)、 右下角(3,3)
1.当鼠标移动时候,首先判断这个光标处于哪个区域
2.当鼠标移动到不同区域,鼠标的形状是不同变化的。
3.根据(2,2)之外的区域,计算初鼠标移动的偏移量,来重新设置窗口的坐标。
代码如下
namespace {
const int kMouseRegionLeft = 10;
const int kMouseRegionTop = 10;
const int kMouseRegionButtom = 10;
const int kMouseRegionRight = 10;
}
void frameless::mouseMoveEvent(QMouseEvent * event)
{
//最大化状态时不能拉伸
if (isMaximized())
{
return;
}
//根据位置设置鼠标样式
SetMouseCursor(event->pos().x(), event->pos().y());if ((event->buttons() == Qt::LeftButton) && left_button_pressed_)
{
QPoint point_offset = event->globalPos() - last_position_;
if (mouse_press_region_ == kMousePositionMid)
{
setCursor(Qt::ArrowCursor);
move(point_offset + last_point_);
}
else
{
QRect rect = geometry();
switch (mouse_press_region_)
{
case kMousePositionLeftTop:
rect.setTopLeft(rect.topLeft() + point_offset);
break;
case kMousePositionTop:
rect.setTop(rect.top() + point_offset.y());
break;
case kMousePositionRightTop:
rect.setTopRight(rect.topRight() + point_offset);
break;
case kMousePositionRight:
rect.setRight(rect.right() + point_offset.x());
break;
case kMousePositionRightButtom:
rect.setBottomRight(rect.bottomRight() + point_offset);
break;
case kMousePositionButtom:
rect.setBottom(rect.bottom() + point_offset.y());
break;
case kMousePositionLeftButtom:
rect.setBottomLeft(rect.bottomLeft() + point_offset);
break;
case kMousePositionLeft:
rect.setLeft(rect.left() + point_offset.x());
break;
default:
break;
}
setGeometry(rect);
last_position_ = event->globalPos();
}
}
}void frameless::mouseReleaseEvent(QMouseEvent *)
{
left_button_pressed_ = false;
}void frameless::mousePressEvent(QMouseEvent * event)
{
if (event->buttons() == Qt::LeftButton) {
left_button_pressed_ = true;
last_point_ = pos();
last_position_ = event->globalPos();
mouse_press_region_ = GetMouseRegion(event->pos().x(), event->pos().y());
}
}void frameless::SetMouseCursor(int x, int y)
{
Qt::CursorShape cursor;
int region = GetMouseRegion(x, y);
switch (region)
{
case kMousePositionLeftTop:
case kMousePositionRightButtom:
cursor = Qt::SizeFDiagCursor; break;
case kMousePositionRightTop:
case kMousePositionLeftButtom:
cursor = Qt::SizeBDiagCursor; break;
case kMousePositionLeft:
case kMousePositionRight:
cursor = Qt::SizeHorCursor; break;
case kMousePositionTop:
case kMousePositionButtom:
cursor = Qt::SizeVerCursor; break;
case kMousePositionMid:
cursor = Qt::ArrowCursor; break;
default:
break;
}
setCursor(cursor);
}int frameless::GetMouseRegion(int x, int y)
{
int region_x = 0, region_y = 0;
if (x < kMouseRegionLeft)
{
region_x = 1;
}
else if (x > (width() - kMouseRegionRight))
{
region_x = 3;
}
else
{
region_x = 2;
}
if (y < kMouseRegionTop)
{
region_y = 1;
}
else if (y > (height() - kMouseRegionButtom))
{
region_y = 3;
}
else
{
region_y = 2;
}
return region_y * 10 + region_x;
}
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_frameless.h"
#include <QMouseEvent>class frameless : public QMainWindow
{
Q_OBJECTpublic:
frameless(QWidget *parent = Q_NULLPTR);private:
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *event);
/**
* @brief 根据鼠标的设置鼠标样式,用于拉伸
*/
void SetMouseCursor(int x, int y);
/**
* @brief 判断鼠标的区域,用于拉伸
*/
int GetMouseRegion(int x, int y);
private:
/**
* @brief 鼠标区域,将窗口分成了9个部分
*/
enum MousePosition
{
kMousePositionLeftTop = 11,
kMousePositionTop = 12,
kMousePositionRightTop = 13,
kMousePositionLeft = 21,
kMousePositionMid = 22,
kMousePositionRight = 23,
kMousePositionLeftButtom = 31,
kMousePositionButtom = 32,
kMousePositionRightButtom = 33,
};Ui::framelessClass ui;
QPoint last_point_; //记录放大之前的位置
QPoint last_position_; //窗口上一次的位置
bool left_button_pressed_; //左键按下int mouse_press_region_ = kMousePositionMid; //鼠标点击的区域
};
现在已经可以实现拉伸了,但是我们会发现鼠标样式的改变不灵敏,解决这个问题很简单
构造函数里添加如下代码
//设置鼠标追踪
setMouseTracking(true);
设置之前,mouseMoveEvent只会在有按键按下的时候触发,设置这个函数之后,mouseMoveEvent会触发的更频繁,能够进准的监控鼠标的移动。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。