QT 播放器之无标题无边框类

在项目上右键,点击添加新文件

创建新的类文件

创建FramelessWindow类,并继承自QObject

创建后在构造函数添加一下代码,把窗口设置为无标题无边框类型,注册事件过滤器到当前类

    parentWidget=parent;
    parent->setWindowFlags(parent->windowFlags()|Qt::FramelessWindowHint);
    parent->installEventFilter(this);
 

设置按钮对应的最小化,最大化,恢复,关闭事件

    QAbstractButton *recoverButton=nullptr;
    QAbstractButton *maxButton=nullptr;
    QAbstractButton *minButton=nullptr;
    QAbstractButton *closeButton=nullptr;


void FramelessWindow::setMinButton(QAbstractButton *button)
{
    if(minButton!=nullptr)
    {
       disconnect(minButton,&QAbstractButton::clicked,parentWidget,&QWidget::showMinimized);
    }
    minButton=button;
    connect(button,&QAbstractButton::clicked,parentWidget,&QWidget::showMinimized);
}

void FramelessWindow::setMaxButton(QAbstractButton *button)
{
    if(maxButton!=nullptr)
    {
       disconnect(maxButton,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowMaximized);
    }
    this->maxButton=button;
    connect(button,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowMaximized);
}

void FramelessWindow::setRecoverButton(QAbstractButton *button)
{
    if(recoverButton!=nullptr)
    {
       disconnect(recoverButton,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowNormal);
    }
    this->recoverButton=button;
    connect(button,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowNormal);
}

void FramelessWindow::setCloseButton(QAbstractButton *button)
{
    if(closeButton!=nullptr)
    {
       disconnect(closeButton,&QAbstractButton::clicked,parentWidget,&QWidget::close);
    }
    this->closeButton = button;
    connect(button,&QAbstractButton::clicked,parentWidget,&QWidget::close);
}

添加拖动窗口的对象,添加前先监测一下是否已添加,注册事件过滤器到当前对象,并且把Widget默认设置为最前面

QVector<QWidget*> dragWidgets;
QPoint mousePos;

void FramelessWindow::addDragWidget(QWidget *widget)
{
    if(!dragWidgets.contains(widget))
    {
        dragWidgets.append( widget);
        widget->installEventFilter(this);
        widget->setWindowFlags(Qt::WindowStaysOnTopHint);
    }
}

设置边框可拖动的区域,因为每次改变大小都需要重新设置矩形,所以直接把设置做成了一个单独的函数

    enum MoveDirection
    {
        None,Left,Top,Right,Bottom,LeftTop,TopRight,RightBottom,LeftBottom
    };

QVector<QRect> rects;
QMargins margins;
MoveDirection direction;
MoveDirection directions[8];



void FramelessWindow::setMargins(int left, int top, int right, int bottom)
{
    isResize=true;
    parentWidget->setMouseTracking(true);
    margins= QMargins(left,top,right,bottom);
    UpdateRects();
}


void FramelessWindow::UpdateRects()
{
    rects.clear();
    rects.append(QRect(0,margins.top(),margins.left(),parentWidget->height()-margins.top()-margins.bottom()));
    rects.append(QRect(parentWidget->width()-margins.right(),margins.top(),margins.right(),parentWidget->height()-margins.top()-margins.bottom()));
    rects.append(QRect(margins.left(),0,parentWidget->width()-margins.left()-margins.right(),margins.top()));
    rects.append(QRect(margins.left(),parentWidget->height()-margins.bottom(),parentWidget->width()-margins.left()-margins.right(),margins.bottom()));

    rects.append(QRect(0,0,margins.left(),margins.top()));
    rects.append(QRect(0,parentWidget->height()-margins.bottom(),margins.left(),margins.bottom()));
    rects.append(QRect(parentWidget->width()-margins.right(),0,margins.right(),margins.top()));
    rects.append(QRect(parentWidget->width()-margins.right(),parentWidget->height()-margins.bottom(),margins.right(),margins.bottom()));
}

由于拖动和设置大小事件是共用的,所以需要一些变量来区分


    enum MoveOperation{
        MoveNode, MoveResize,MoveDrag
    };


    bool isResize=false;
    bool isMousePressed=false;

    MoveOperation operation;
    Qt::CursorShape cursors[8];

在构造函数初始化两个数组,都是一一对应的~

    int i=0;
    directions[i++] = Left;
    directions[i++] = Right;
    directions[i++] = Top;
    directions[i++] = Bottom;
    directions[i++] = LeftTop;
    directions[i++] = LeftBottom;
    directions[i++] = TopRight;
    directions[i++] = RightBottom;

    i=0;
    cursors[i++] = Qt::SizeHorCursor;
    cursors[i++] = Qt::SizeHorCursor;
    cursors[i++] = Qt::SizeVerCursor;
    cursors[i++] = Qt::SizeVerCursor;
    cursors[i++] = Qt::SizeFDiagCursor;
    cursors[i++] = Qt::SizeBDiagCursor;
    cursors[i++] = Qt::SizeBDiagCursor;
    cursors[i++] = Qt::SizeFDiagCursor;

这两个数组用来填充鼠标悬浮时候的状态,如果鼠标不在8个区域内就设置为Qt::ArrowCursor,如果鼠标进入到矩形内,那么改变鼠标的形状

void FramelessWindow::hoverMove(QPoint pos)
{
    if(isMousePressed)
    {
        return;
    }
    bool directionChanged=false;
    for(int i=0;i<8;i++)
    {
        if(rects[i].contains(pos))
        {
            directionChanged=true;
            direction=directions[i];
            parentWidget->setCursor(cursors[i]);
            break;
        }
    }
    if(!directionChanged)
    {
        direction=None;
        parentWidget->setCursor(Qt::ArrowCursor);
    }
}

 

 

接下来最重要的事件过滤器~

拖动窗口

  • 如果在可拖动对象内按下
  • 记录当前按下的坐标
  • 移动鼠标的时候 窗口坐标 + 当前鼠标坐标 - 上一次鼠标坐标
  • 记录当前移动后的鼠标坐标

缩放窗口

  • 需要先设置margins后才会开启
  • 鼠标按下后检测是否在某个矩形区域内
  • 如果在,记录鼠标坐标
  • 移动鼠标后通过resize函数设置窗口坐标和大小,并记录当前鼠标坐标

释放鼠标后,当前状态和鼠标形状之类的都会恢复初始状态

bool FramelessWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent* e = static_cast<QMouseEvent*>(event);

        if(isResize)
        {
            for(int i=0,count=rects.size();i<count;i++)
            {
                if(rects[i].contains(e->pos()))
                {
                    isMousePressed=true;
                    operation = MoveResize;
                    mousePos = e->globalPos();
                    break;
                }
            }
        }

        if(dragWidgets.contains(qobject_cast<QWidget *>(watched)))
        {
            isMousePressed=true;
            operation = MoveDrag;
            mousePos = e->globalPos();
        }
    }
    else if(event->type() == QEvent::MouseMove)
    {
        QMouseEvent* e = static_cast<QMouseEvent*>(event);
        if(operation == MoveDrag)
        {
            parentWidget->move(parentWidget->pos() + e->globalPos()-mousePos);
            mousePos = e->globalPos();
        }
        else if(isResize && operation == MoveResize)
        {
            resize(e->globalPos());
            mousePos=e->globalPos();
        }
    }
    else if(event->type() == QEvent::MouseButtonRelease)
    {
        operation = MoveNode;
        isMousePressed=false;
    }
    else if(isResize && event->type() == QEvent::HoverMove)
    {
        hoverMove(static_cast<QMouseEvent*>(event)->pos());
    }

    return QObject::eventFilter(watched,event);
}

resize设置窗口位置和窗口大小~

void FramelessWindow::resize(QPoint pos)
{
    int x,y,w,h;
    QPoint offset(mousePos-pos);

    x = parentWidget->x();
    y = parentWidget->y();
    w = parentWidget->width();
    h = parentWidget->height();

    switch(direction)
    {
    case Left:
    {
        x = parentWidget->x()-offset.x();
        w = parentWidget->width()+offset.x();
        break;
    }
    case Right:
    {
        w = parentWidget->width()-offset.x();
        break;
    }
    case Top:
    {
        y = parentWidget->y()-offset.y();
        h = parentWidget->height()+offset.y();
        break;
    }
    case Bottom:
    {
        h = parentWidget->height()-offset.y();
        break;
    }
    case LeftTop:
    {
        x = parentWidget->x()-offset.x();
        y = parentWidget->y()-offset.y();
        w = parentWidget->width()+offset.x();
        h = parentWidget->height()+offset.y();
        break;
    }
    case LeftBottom:
    {
        x = parentWidget->x()-offset.x();
        w = parentWidget->width()+offset.x();
        h = parentWidget->height()-offset.y();
        break;
    }
    case TopRight:
    {
        y = parentWidget->y()-offset.y();
        h = parentWidget->height()+offset.y();
        w = parentWidget->width()-offset.x();
        break;
    }
    case RightBottom:
    {
        w = parentWidget->width()-offset.x();
        h = parentWidget->height()-offset.y();
        break;
    }
    }
    if(w>(margins.left()+margins.right()) && h>(margins.top()+margins.bottom()))
    {
        parentWidget->move(x,y);
        parentWidget->resize(w,h);
        UpdateRects();
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

最后~完整代码!

#ifndef FRAMELESSWINDOW_H
#define FRAMELESSWINDOW_H

#include <QObject>
#include <QVector>
#include <QRect>

QT_BEGIN_NAMESPACE
class QWidget;
class QMouseEvent;
class QAbstractButton;
QT_END_NAMESPACE

class FramelessWindow : public QObject
{
    enum MoveDirection
    {
        None,Left,Top,Right,Bottom,LeftTop,TopRight,RightBottom,LeftBottom
    };
    enum MoveOperation{
        MoveNode, MoveResize,MoveDrag
    };

    Q_OBJECT
public:
    explicit FramelessWindow(QWidget *parent = nullptr);
    void setMargins(int left, int top, int right, int bottom);
    void addDragWidget(QWidget *widget);
    void setMinButton(QAbstractButton *button);
    void setMaxButton(QAbstractButton *button);
    void setRecoverButton(QAbstractButton *button);
    void setCloseButton(QAbstractButton *button);

signals:

private slots:
    void FrameShowMaximized();
    void FrameShowNormal();
protected:
    bool eventFilter(QObject *watched, QEvent *event);

private:
    void hoverMove(QPoint pos);
    void resize(QPoint pos);
    void UpdateRects();

private:
    QWidget *parentWidget;
    QVector<QWidget*> dragWidgets;
    QAbstractButton *recoverButton=nullptr;
    QAbstractButton *maxButton=nullptr;
    QAbstractButton *minButton=nullptr;
    QAbstractButton *closeButton=nullptr;
    QPoint mousePos;

    bool isResize=false;
    bool isMousePressed=false;
    QVector<QRect> rects;
    QMargins margins;

    MoveOperation operation;
    MoveDirection direction;

    MoveDirection directions[8];
    Qt::CursorShape cursors[8];
};

#endif // FRAMELESSWINDOW_H
#include "framelesswindow.h"
#include <QAbstractButton>
#include <QMouseEvent>
#include <QDebug>
FramelessWindow::FramelessWindow(QWidget *parent) : QObject(parent)
{
    parentWidget=parent;
    parent->setWindowFlags(parent->windowFlags()|Qt::FramelessWindowHint);
    parent->installEventFilter(this);

    int i=0;
    directions[i++] = Left;
    directions[i++] = Right;
    directions[i++] = Top;
    directions[i++] = Bottom;
    directions[i++] = LeftTop;
    directions[i++] = LeftBottom;
    directions[i++] = TopRight;
    directions[i++] = RightBottom;

    i=0;
    cursors[i++] = Qt::SizeHorCursor;
    cursors[i++] = Qt::SizeHorCursor;
    cursors[i++] = Qt::SizeVerCursor;
    cursors[i++] = Qt::SizeVerCursor;
    cursors[i++] = Qt::SizeFDiagCursor;
    cursors[i++] = Qt::SizeBDiagCursor;
    cursors[i++] = Qt::SizeBDiagCursor;
    cursors[i++] = Qt::SizeFDiagCursor;
}

void FramelessWindow::setMargins(int left, int top, int right, int bottom)
{
    isResize=left>0 && top>0 && right>0 && bottom>0?true:false;

    parentWidget->setMouseTracking(isResize);
    margins= QMargins(left,top,right,bottom);
    UpdateRects();
}

void FramelessWindow::addDragWidget(QWidget *widget)
{
    if(!dragWidgets.contains(widget))
    {
        dragWidgets.append( widget);
        widget->installEventFilter(this);
        widget->setWindowFlags(Qt::WindowStaysOnTopHint);
    }
}

void FramelessWindow::setMinButton(QAbstractButton *button)
{
    if(minButton!=nullptr)
    {
        disconnect(minButton,&QAbstractButton::clicked,parentWidget,&QWidget::showMinimized);
    }
    minButton=button;
    if(button)
    {
        connect(button,&QAbstractButton::clicked,parentWidget,&QWidget::showMinimized);
    }
}

void FramelessWindow::setMaxButton(QAbstractButton *button)
{
    if(maxButton!=nullptr)
    {
        disconnect(maxButton,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowMaximized);
    }
    this->maxButton=button;
    if(button)
    {
        connect(button,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowMaximized);
    }
}

void FramelessWindow::setRecoverButton(QAbstractButton *button)
{

    if(recoverButton!=nullptr)
    {
        disconnect(recoverButton,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowNormal);
    }
    this->recoverButton=button;
    if(button)
    {
        button->hide();
        connect(button,&QAbstractButton::clicked,this,&FramelessWindow::FrameShowNormal);
    }
}

void FramelessWindow::setCloseButton(QAbstractButton *button)
{
    if(closeButton!=nullptr)
    {
        disconnect(closeButton,&QAbstractButton::clicked,parentWidget,&QWidget::close);
    }
    this->closeButton = button;
    if(button)
    {
        connect(button,&QAbstractButton::clicked,parentWidget,&QWidget::close);
    }
}

void FramelessWindow::FrameShowMaximized()
{
    parentWidget->showMaximized();
    this->maxButton->hide();
    this->recoverButton->show();
}

void FramelessWindow::FrameShowNormal()
{
    parentWidget->showNormal();
    this->maxButton->show();
    this->recoverButton->hide();
}

bool FramelessWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent* e = static_cast<QMouseEvent*>(event);

        if(isResize)
        {
            for(int i=0,count=rects.size();i<count;i++)
            {
                if(rects[i].contains(e->pos()))
                {
                    isMousePressed=true;
                    operation = MoveResize;
                    mousePos = e->globalPos();
                    break;
                }
            }
        }

        if(dragWidgets.contains(qobject_cast<QWidget *>(watched)))
        {
            isMousePressed=true;
            operation = MoveDrag;
            mousePos = e->globalPos();
        }
    }
    else if(event->type() == QEvent::MouseMove)
    {
        QMouseEvent* e = static_cast<QMouseEvent*>(event);
        if(operation == MoveDrag)
        {
            parentWidget->move(parentWidget->pos() + e->globalPos()-mousePos);
            mousePos = e->globalPos();
        }
        else if(isResize && operation == MoveResize)
        {
            resize(e->globalPos());
            mousePos=e->globalPos();
        }
    }
    else if(event->type() == QEvent::MouseButtonRelease)
    {
        operation = MoveNode;
        isMousePressed=false;
    }
    else if(isResize && event->type() == QEvent::HoverMove)
    {
        hoverMove(static_cast<QMouseEvent*>(event)->pos());
    }
    else if(event->type() == QEvent::Show)
    {
        parentWidget->setAttribute(Qt::WA_Mapped);
    }

    return QObject::eventFilter(watched,event);
}

void FramelessWindow::hoverMove(QPoint pos)
{
    if(isMousePressed)
    {
        return;
    }
    bool directionChanged=false;
    for(int i=0;i<8;i++)
    {
        if(rects[i].contains(pos))
        {
            directionChanged=true;
            direction=directions[i];
            parentWidget->setCursor(cursors[i]);
            break;
        }
    }
    if(!directionChanged)
    {
        direction=None;
        parentWidget->setCursor(Qt::ArrowCursor);
    }
}

void FramelessWindow::resize(QPoint pos)
{
    int x,y,w,h;
    QPoint offset(mousePos-pos);

    x = parentWidget->x();
    y = parentWidget->y();
    w = parentWidget->width();
    h = parentWidget->height();

    switch(direction)
    {
    case Left:
    {
        x = parentWidget->x()-offset.x();
        w = parentWidget->width()+offset.x();
        break;
    }
    case Right:
    {
        w = parentWidget->width()-offset.x();
        break;
    }
    case Top:
    {
        y = parentWidget->y()-offset.y();
        h = parentWidget->height()+offset.y();
        break;
    }
    case Bottom:
    {
        h = parentWidget->height()-offset.y();
        break;
    }
    case LeftTop:
    {
        x = parentWidget->x()-offset.x();
        y = parentWidget->y()-offset.y();
        w = parentWidget->width()+offset.x();
        h = parentWidget->height()+offset.y();
        break;
    }
    case LeftBottom:
    {
        x = parentWidget->x()-offset.x();
        w = parentWidget->width()+offset.x();
        h = parentWidget->height()-offset.y();
        break;
    }
    case TopRight:
    {
        y = parentWidget->y()-offset.y();
        h = parentWidget->height()+offset.y();
        w = parentWidget->width()-offset.x();
        break;
    }
    case RightBottom:
    {
        w = parentWidget->width()-offset.x();
        h = parentWidget->height()-offset.y();
        break;
    }
    }
    if(w>(margins.left()+margins.right()) && h>(margins.top()+margins.bottom()))
    {
        parentWidget->move(x,y);
        parentWidget->resize(w,h);
        UpdateRects();
    }
}

void FramelessWindow::UpdateRects()
{
    if(!isResize)
    {
        return;
    }
    rects.clear();
    rects.append(QRect(0,margins.top(),margins.left(),parentWidget->height()-margins.top()-margins.bottom()));
    rects.append(QRect(parentWidget->width()-margins.right(),margins.top(),margins.right(),parentWidget->height()-margins.top()-margins.bottom()));
    rects.append(QRect(margins.left(),0,parentWidget->width()-margins.left()-margins.right(),margins.top()));
    rects.append(QRect(margins.left(),parentWidget->height()-margins.bottom(),parentWidget->width()-margins.left()-margins.right(),margins.bottom()));

    rects.append(QRect(0,0,margins.left(),margins.top()));
    rects.append(QRect(0,parentWidget->height()-margins.bottom(),margins.left(),margins.bottom()));
    rects.append(QRect(parentWidget->width()-margins.right(),0,margins.right(),margins.top()));
    rects.append(QRect(parentWidget->width()-margins.right(),parentWidget->height()-margins.bottom(),margins.right(),margins.bottom()));
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼游戏开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值