1,简介
之前介绍过实现无边框窗口的简单方法,包含了标题的拖拽、最大最小关闭按钮,双击最大化恢复等功能。
如图:
但是这个方案有一个缺陷,那就是不能自由缩放窗口尺寸。
如果默认尺寸不是很适合内容,那么只能选择最大化。
在网上找了一些方案,不是太理想。
要么是有细节处理不完美,要么是实现方式太过复杂,有一群类需要自己认真剥离出来。
而我直观感觉,应该是很简单就可以解决的,不就是拖拽时改变窗口大小嘛,于是试了试果然很简单。
效果个人感觉还OK,其中缩放图标依旧是自己PS画的
网上找了些带缩放的窗口,了解了大致样式,然后按照自己需要的图标大小画,这样比较清晰
2,效果
3,原理
原理很简单
就是底部做了一个水平布局的widget,最右侧放一个图片label,该label设置鼠标样式为缩放型。
给label过滤鼠标消息,按下、移动、弹起
在按下时记录按下位置;在移动时,计算相对按下时的鼠标偏移;在松开时设置窗口尺寸。
4,主要代码
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMouseEvent>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
bool eventFilter(QObject *obj, QEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private slots:
void on_btnMin_clicked();
void on_btnMax_clicked();
void on_btnExit_clicked();
private:
Ui::MainWindow *ui;
//标题拖动、双击最大化
bool mDrag;
QPoint mDragPos;
bool mIsMax;
QRect mLocation;
QFont mIconFont;
//与缩放相关的变量
int mZoom;
QRect mZoomLocation;
QPoint mZoomPos;
};
#endif // MAINWINDOW_H
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDesktopWidget>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint);
mLocation = this->geometry();
mIsMax = false;
mDrag = false;
mZoom = false;
ui->widgetTitle->installEventFilter(this);
ui->btnMin->setIcon(QIcon(":/image/min.png"));
ui->btnMax->setIcon(QIcon(":/image/max1.png"));
ui->btnExit->setIcon(QIcon(":/image/exit.png"));
//给缩放的图片label处理鼠标的按下、移动、弹起消息,进行缩放窗口功能
ui->labelZoom->installEventFilter(this);
ui->labelZoom->setCursor(Qt::SizeFDiagCursor);
setStyleSheet("QMainWindow{color:#E8E8E8;background:#43CD80;}");
//另外在设计器内查看widgetTitle样式,内有标题栏各个子控件的样式设置
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *obj, QEvent *e)
{
if (obj == ui->widgetTitle)
{
if(e->type() == QEvent::MouseButtonDblClick)
{
on_btnMax_clicked();
return true;
}
}
else if (obj == ui->labelZoom)
{
//实现拖动右下角缩放窗口
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent *event = (QMouseEvent *)e;
if (event->buttons() & Qt::LeftButton)
{
if(mIsMax)
{
//已最大化,就不让再拖动
return true;
}
mZoom = true;
mZoomLocation = geometry();
mZoomPos = event->globalPos();
return true;
}
}
else if(e->type() == QEvent::MouseMove)
{
QMouseEvent *event = (QMouseEvent *)e;
if (mZoom && (event->buttons() & Qt::LeftButton))
{
int dx = event->globalPos().x() - mZoomPos.x();
int dy = event->globalPos().y() - mZoomPos.y();
QRect rc = mZoomLocation;
rc.setRight(rc.right() + dx);
rc.setBottom(rc.bottom() + dy);
setGeometry(rc);
update();
return true;
}
}
else if(e->type() == QEvent::MouseButtonRelease)
{
mZoom = false;
return true;
}
}
return QObject::eventFilter(obj, e);
}
void MainWindow::mousePressEvent(QMouseEvent *e)//鼠标按下事件
{
if (e->button() == Qt::LeftButton)
{
mDrag = true;
mDragPos = e->globalPos() - pos();
e->accept();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *e)//鼠标移动事件
{
if (mDrag && (e->buttons() && Qt::LeftButton))
{
move(e->globalPos() - mDragPos);
e->accept();
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *e)//鼠标释放事件
{
mDrag = false;
}
void MainWindow::on_btnMin_clicked()
{
showMinimized();
}
void MainWindow::on_btnMax_clicked()
{
if (mIsMax)
{
setGeometry(mLocation);
ui->btnMax->setIcon(QIcon(":/image/max1.png"));
ui->btnMax->setToolTip(QStringLiteral("最大化"));
}
else
{
mLocation = geometry();
setGeometry(qApp->desktop()->availableGeometry());
ui->btnMax->setIcon(QIcon(":/image/max2.png"));
ui->btnMax->setToolTip(QStringLiteral("还原"));
}
mIsMax = !mIsMax;
}
void MainWindow::on_btnExit_clicked()
{
qApp->exit();
}
5,源码
Qt无边框窗口2 右下角缩放.rar:
链接:https://pan.baidu.com/s/1tLDEF5IDBg9wIG7zvCxdmA
提取码:0y6b