Qt写的一个基于纯代码的Windows风格窗体实现

QT随记

记录随手写的QT代码

一个基于纯代码的Windows风格窗体实现


前言

一直觉得Qt自带的窗体留给我们自定义的空间太小了,所以参考了网上大神代码的基础上改了现在这个用纯代码写的窗体。基本实现了该有的基础功能吧,接下来剩下的就可以根据需求自由发挥了。直接贴代码了,很简单,也就没写啥注释。

.h文件

#ifndef CUSTOMW_H
#define CUSTOMW_H

#include <QWidget>
#include <QMouseEvent>
#include <QApplication>
#include <QPainter>
#include <QTime>
#include <QPushButton>


enum {
    Minimized = 1 ,
    Maximized = 2 ,
    closed = 3
};
enum {
    TOPLEFT = 11,
    TOP = 12,
    TOPRIGHT = 13,
    LEFT = 21,
    CENTER = 22,
    RIGHT = 23,
    BUTTOMLEFT = 31,
    BUTTOM = 32,
    BUTTOMRIGHT = 33,
    ToMinimize = 1,
    ToMaximize = 2,
    Closed = 3
};

#define FRAMESHAPE 10

class customW : public QWidget
{
    Q_OBJECT
public:
    explicit customW(QWidget *parent = nullptr);

protected:
    // 双击标题栏进行界面的最大化/还原
    virtual void mouseDoubleClickEvent(QMouseEvent *event);
    // 进行鼠界面的拖动
    virtual void mousePressEvent(QMouseEvent *event);
    // 设置界面标题与图标
    virtual void mouseMoveEvent(QMouseEvent *event);

    virtual void mouseReleaseEvent(QMouseEvent *event);

private:
    void paintEvent(QPaintEvent *e);
    int CalCursorCol(QPoint pt);    //计算鼠标X的位置
    int CalCursorPos(QPoint pt, int colPos);    //计算鼠标的位置
    void setCursorShape(int CalPos);    //设置鼠标对应位置的形状

public:
    void OnClicked( int index);
    void setDoubleclickflag(bool value);
    void setMoveflag(bool value);
    void setResizeflag(bool value);
    void setStatusbarflag(bool value);
    void setTitletext(const QString &value);


private:
    int     m_iCalCursorPos;
    bool    m_bLeftPress;
    bool    m_rightPress;
    QRect   m_rtPreGeometry;
    QPoint  m_currentPosition;
    QPoint  m_ptViewMousePos;

    bool statusbarflag;   //是否显示状态栏
    bool doubleclickflag; //是否允许双击标题栏最大化最小化
    bool moveflag ;       //是否允许移动
    bool resizeflag;      //是否允许修改尺寸
    QString titletext;    //标题

    int MinBtnState;
    int MaxBtnState;
    int CloseBtnState;

    QRect MinRect;
    QRect MaxRect;
    QRect CloseRect;


signals:
    void mousePress(QMouseEvent *event);
    void widgetResizeChange();

};


#endif // CUSTOMW_H

.cpp文件

#include "customw.h"
#include <QDebug>

customW::customW(QWidget *parent) : QWidget(parent),
    statusbarflag(true),
    doubleclickflag(true),
    resizeflag(true),
    moveflag(true),
    CloseBtnState(0)
{
    setWindowFlags(windowFlags()|Qt::FramelessWindowHint);
    setWindowState(Qt::WindowNoState );
    setFocusPolicy(Qt::NoFocus);
    this->setMouseTracking(true);

    m_rightPress = false;
    m_bLeftPress = false;
}

void customW::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    if(event->y() < 30 &&  doubleclickflag)
    {
        OnClicked(Maximized);
    }
}

void customW::mousePressEvent(QMouseEvent *event)
{
    判断鼠标所在Rect
    if(MinRect.contains(event->pos()))
    {
        MinBtnState = 2 ;
        update();
        return;
    }
    if(MaxRect.contains(event->pos()))
    {
        MaxBtnState = 2 ;
        update();
        return;
    }
    if(CloseRect.contains(event->pos()))
    {
        CloseBtnState = 2 ;
        update();
        return;
    }

    m_iCalCursorPos = CalCursorPos(event->pos(),CalCursorCol(event->pos()));//鼠标在窗口的相近位置整数型
    if (event->button() == Qt::LeftButton &&!this->isMaximized() )
    {
        if(m_iCalCursorPos != CENTER && resizeflag)//CENTER=22
        {
            m_bLeftPress = true;
        }
        else if(moveflag)
        {
            m_rightPress = true;
            setCursor(Qt::SizeAllCursor);
        }
    }
    m_rtPreGeometry = geometry();//窗口几何矩形
    m_currentPosition = this->pos();
    m_ptViewMousePos = event->globalPos();//鼠标按下时的全局点

    emit mousePress(event);
}

void customW::mouseMoveEvent(QMouseEvent *event)
{
    计算Rect位置
    MinRect.setRect(width()-210,0,70,30);
    MaxRect.setRect(width()-140,0,70,30);
    CloseRect.setRect(width()-70,0,70,30);

    判断鼠标所在Rect
    if(CloseBtnState == 2 || MinBtnState == 2 || MaxBtnState == 2)
        return;
    if(MinRect.contains(event->pos()) )
        MinBtnState = 1 ;
    else
        MinBtnState = 0 ;
    if(MaxRect.contains(event->pos()))
        MaxBtnState = 1 ;
    else
        MaxBtnState = 0 ;
    if(CloseRect.contains(event->pos()))
        CloseBtnState = 1 ;
    else
        CloseBtnState = 0 ;

    update();
    if(CloseBtnState == 1 || MinBtnState == 1 || MaxBtnState == 1)
        return;

    //窗体不是最大的话就改变鼠标的形状
    if(Qt::WindowMaximized != windowState())
    {
        setCursorShape(CalCursorPos(event->pos(),CalCursorCol(event->pos())));
    }
    //获取当前的点,这个点是全局的
    QPoint ptCurrentPos = QCursor::pos();
    //计算出移动的位置,当前点 - 鼠标左键按下的点
    QPoint ptMoveSize = ptCurrentPos - m_ptViewMousePos;
    QRect rtTempGeometry = m_rtPreGeometry;//窗口矩形
    if(m_bLeftPress)
    {
        switch(m_iCalCursorPos)
        {
        case TOPLEFT:
            rtTempGeometry.setTopLeft(m_rtPreGeometry.topLeft()+ptMoveSize);
            break;
        case TOP:
            rtTempGeometry.setTop(m_rtPreGeometry.top()+ptMoveSize.y());
            break;
        case TOPRIGHT:
            rtTempGeometry.setTopRight(m_rtPreGeometry.topRight()+ptMoveSize);
            break;
        case LEFT:
            rtTempGeometry.setLeft(m_rtPreGeometry.left()+ptMoveSize.x());
            break;
        case RIGHT:
            rtTempGeometry.setRight(m_rtPreGeometry.right()+ptMoveSize.x());
            break;
        case BUTTOMLEFT:
            rtTempGeometry.setBottomLeft(m_rtPreGeometry.bottomLeft()+ptMoveSize);
            break;
        case BUTTOM:
            rtTempGeometry.setBottom(m_rtPreGeometry.bottom()+ptMoveSize.y());
            break;
        case BUTTOMRIGHT:
            rtTempGeometry.setBottomRight(m_rtPreGeometry.bottomRight()+ptMoveSize);
            break;
        default:
            break;
        }
        //移动窗体,如果比最小窗体大,就移动
        if(rtTempGeometry.width() >= 200 && rtTempGeometry.height() >= 300)
            setGeometry(rtTempGeometry);
    }
    else if(m_rightPress)
    {
        setCursor(Qt::SizeAllCursor);
        this->move(m_currentPosition + ptMoveSize);
    }
}

void customW::mouseReleaseEvent(QMouseEvent *event)
{
    if(MinRect.contains(event->pos()) )
        MinBtnState = 1 ;
    else
        MinBtnState = 0 ;
    if(MaxRect.contains(event->pos()))
        MaxBtnState = 1 ;
    else
        MaxBtnState = 0 ;
    if(CloseRect.contains(event->pos()))
        CloseBtnState = 1 ;
    else
        CloseBtnState = 0 ;

    if(MinBtnState == 1)
        OnClicked(Minimized);
    if(MaxBtnState == 1)
        OnClicked(Maximized);
    if(CloseBtnState == 1)
        OnClicked(closed);

    update();

    Q_UNUSED(event)
    m_bLeftPress = false;
    m_rightPress = false;
    setCursor(Qt::ArrowCursor);
    QApplication::restoreOverrideCursor();
}

void customW::paintEvent(QPaintEvent *e)
{
    Q_UNUSED(e)

    QPainter painter(this);
    painter.save();
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(231, 234, 237));
    painter.drawRect(0,0, width(),30);
    painter.restore();

    painter.save();
    painter.setPen(Qt::NoPen);
    ///画背景
    if(MinBtnState == 0) //最小化按键初始状态
    {
        painter.setBrush(QColor(231, 234, 237));
    }
    else if(MinBtnState == 1) //最小化悬浮状态
    {
        painter.setBrush(QColor(209, 209, 209));
    }
    else if(MinBtnState == 2) //最小化按键按下状态
    {
        painter.setBrush(QColor(150, 150, 150));
    }
    painter.drawRect(MinRect);

    if(MaxBtnState == 0) //最大化按键初始状态
    {
        painter.setBrush(QColor(231, 234, 237));
    }
    else if(MaxBtnState == 1) //最大化悬浮状态
    {
        painter.setBrush(QColor(209, 209, 209));
    }
    else if(MaxBtnState == 2) //最大化按键按下状态
    {
        painter.setBrush(QColor(150, 150, 150));
    }
    painter.drawRect(MaxRect);


    if(CloseBtnState == 0) //关闭按键初始状态
    {
        painter.setBrush(QColor(231, 234, 237));
    }
    else if(CloseBtnState == 1) //关闭悬浮状态
    {
        painter.setBrush(QColor(255, 0, 0));
    }
    else if(CloseBtnState == 2) //关闭按键按下状态
    {
        painter.setBrush(QColor(255, 137, 137));
    }
    painter.drawRect(CloseRect);

    painter.restore();
    //

    ///画符号
    painter.save();
    painter.setPen(QPen{QColor(20,20,20),4});
    painter.drawLine(width()-181,15,width()-168,15); ///最下化
    painter.setPen(QPen{QColor(20,20,20),2});
    if(this->window()->isFullScreen())
    {
        QPointF pointB[5] =
        {
            QPointF(width()-108,12),
            QPointF(width()-108,9),
            QPointF(width()-93,9),
            QPointF(width()-93,20),
            QPointF(width()-99,20),
        };
        painter.drawLine(pointB[0],pointB[1]);
        painter.drawLine(pointB[1],pointB[2]);
        painter.drawLine(pointB[2],pointB[3]);
        painter.drawLine(pointB[3],pointB[4]);

        QPointF pointF[4] =
        {
            QPointF(width()-114,13),
            QPointF(width()-99,13),
            QPointF(width()-99,24),
            QPointF(width()-114,24),
        };
        painter.drawConvexPolygon(pointF,4);
    }
    else
    {
        QPointF pointG[4] =
        {
            QPointF(width()-116,7),
            QPointF(width()-95,7),
            QPointF(width()-95,23),
            QPointF(width()-116,23),
        };
        painter.drawConvexPolygon(pointG,4);
    }
    if(CloseBtnState == 0) ///关闭
    {
        painter.setPen(QPen{QColor(20,20,20),4});
    }
    else
    {
        painter.setPen(QPen{QColor(255,255,255),4});
    }
    painter.drawLine(width()-41,9,width()-28,22);
    painter.drawLine(width()-41,22,width()-28,9);

    painter.restore();
    写标题
    painter.save();
    QFont font{this->font().family()};
    font.setBold(true);
    font.setPixelSize(20);
    painter.setFont(font);
    painter.drawText(QRect{30,0,500,30},Qt::AlignLeft|Qt::AlignVCenter,titletext);
    painter.restore();

}
int customW::CalCursorCol(QPoint pt)
{
    return (pt.x() < FRAMESHAPE ?
                1 : ((pt.x() > this->width() - FRAMESHAPE) ? 3 : 2));//返回整数型位置个位
}

int customW::CalCursorPos(QPoint pt, int colPos)
{
    return ((pt.y() < FRAMESHAPE ?
                 10 : ((pt.y() > this->height() - FRAMESHAPE) ? 30 : 20)) + colPos);//返回整数型位置十位和个位
}

void customW::setCursorShape(int CalPos)
{
    Qt::CursorShape cursor;
    switch(CalPos)
    {
    case TOPLEFT:
    case BUTTOMRIGHT:
        cursor = Qt::SizeFDiagCursor;
        break;
    case TOPRIGHT:
    case BUTTOMLEFT:
        cursor = Qt::SizeBDiagCursor;
        break;
    case TOP:
    case BUTTOM:
        cursor = Qt::SizeVerCursor;
        break;
    case LEFT:
    case RIGHT:
        cursor = Qt::SizeHorCursor;
        break;
    default:
        cursor = Qt::ArrowCursor;
        break;
    }
    setCursor(cursor);
}

void customW::OnClicked( int index)
{
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        if (index == Minimized)
        {
            pWindow->showMinimized();
        }
        else if (index == Maximized)
        {
            pWindow->isFullScreen() ? pWindow->showNormal() : pWindow->showFullScreen();
        }
        else if (index == closed)
        {
            pWindow->close();
        }
    }
    MinBtnState = 0;
    MaxBtnState = 0;
    CloseBtnState = 0;
}


void customW::setDoubleclickflag(bool value)
{
    doubleclickflag = value;
}

void customW::setMoveflag(bool value)
{
    moveflag = value;
}

void customW::setResizeflag(bool value)
{
    resizeflag = value;
}

void customW::setTitletext(const QString &value)
{
    titletext = value;
    update();
}

void customW::setStatusbarflag(bool value)
{
    statusbarflag = value;
    update();
}

使用

添加头文件,直接继承这个类就可以了
就像这样

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "customw.h"
namespace Ui {
class Widget;
}
class Widget : public customW
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

或者在UI文件里提升!!!!


总结

写的第一篇博客,总结就是没有总结!哈哈
哦对了,网上参考的代码好久之前看到的了,实在是没找到出处,原作看到请见谅呀!!!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值