Qt 无边框窗口之 最大化/最小化/可伸缩/可移动

1.实现的功能

窗口的 最大化和最大化前大小切换、最小化、关闭窗口、移动、拉伸、缩小。

很多时候,为了界面的美观,需要将界面设置为无边框窗口,这就需要重写上述功能来完善窗口。

2.具体步骤

最大化、最小化、关闭 为三个按钮,按钮设置好布局位置,设置QIcon,将按钮添加入槽,具体步骤不在此叙述。

以下三个槽函数即为最大化、最小化、关闭三个按钮的槽函数;
私有变量中的变量和函数看注释和具体代码。

private slots:
    void on_minBtn_clicked();
    void on_closeBtn_clicked();
    void on_maxBtn_clicked();
    
private:
    Ui::RailwayPowerInterface  *ui;
    bool _isleftpressed = false; //判断是否是左键点击
    int _curpos = 0;    //鼠标左键按下时光标所在区域
    QPoint _plast;      //获取鼠标左键按下时光标在全局(屏幕而非窗口)的位置
    void mousePressEvent(QMouseEvent* event);//鼠标按下事件
    void mouseReleaseEvent(QMouseEvent* event);//鼠标释放事件
    void mouseMoveEvent(QMouseEvent* event);//鼠标移动事件  
    int countRow(QPoint p);            //获取光标在窗口所在区域的 行   返回行数
    int countFlag(QPoint p,int row);    //获取光标在窗口所在区域的 列  返回行列坐标
    void setCursorType(int flag);          //根据传入的坐标,设置光标样式

窗口最大化、最小化、关闭的具体实现代码,比较简单

//最小化界面
void RailwayPowerInterface::on_minBtn_clicked()
{
    this->showMinimized();
}

//关闭界面
void RailwayPowerInterface::on_closeBtn_clicked()
{
    this->close();
}

//放大,缩小界面
void RailwayPowerInterface::on_maxBtn_clicked()
{
    static bool max = false;
    static QRect location = this->geometry();
    if (max) {
        this->setGeometry(location);//回复窗口原大小和位置
        ui->maxBtn->setIcon(QIcon(":/MAX_.png"));
    }else {
        ui->maxBtn->setIcon(QIcon(":/minMAX.png"));
        location = this->geometry();	//最大化前记录窗口大小和位置
        //this->setGeometry(qApp->desktop()->availableGeometry());
        this->showFullScreen();	//设置窗口铺满全屏
    }
    max = !max;
}

在设置窗口 可伸缩、可移动前,需要线分析以下窗口;
如图,可将窗口分为如下9部分,光标在不同区域将呈现不同样式,而根据光标样式又可以将以下9个区域分为五类:

(1,1) (3,3) :

(1,2) (3,2) :

(1,3) (3,3) :

(2,1) (2,3) :

(2,2) :以上区域用来伸缩窗口,此区域用来移动窗口

注: 在代码中,将坐标(1,1) 以数字 11代替,(1,2)以数字12代替,其他坐标依次类推。

通过宏定义来设定边框区域的大小(即绿色区域)

#define MARGIN 2 
//鼠标按下事件
/*
 *作用:
 *1.判断是否时左键点击 _isleftpressed
 *2.获取光标在屏幕中的位置 _plast
 *3.左键按下时光标所在区域 _curpos
 */
void RailwayPowerInterface::mousePressEvent(QMouseEvent *event)
{
	Q_UNUSED(event);
    if (event->button() == Qt::LeftButton)
    {
        this->_isleftpressed = true;
        QPoint temp = event->globalPos();
        _plast = temp;
        _curpos = countFlag(event->pos(), countRow(event->pos()));
    }
}

//鼠标释放事件
/*
 *作用:
 *1.将_isleftpressed 设为false
 *2.将光标样式恢复原样式  setCursor(Qt::ArrowCursor);
 */
void RailwayPowerInterface::mouseReleaseEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    if (_isleftpressed)
        _isleftpressed = false;
    setCursor(Qt::ArrowCursor);
}

//鼠标移动事件 
void RailwayPowerInterface::mouseMoveEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    if(this->isFullScreen()) return;	//窗口铺满全屏,直接返回,不做任何操作
    int poss = countFlag(event->pos(), countRow(event->pos()));
    setCursorType(poss);
    if (_isleftpressed)//是否左击
    {
        QPoint ptemp = event->globalPos();
        ptemp = ptemp - _plast;
        if (_curpos == 22)//移动窗口
        {
            ptemp = ptemp + pos();
            move(ptemp);
        }
        else
        {
            QRect wid = geometry();
            switch (_curpos)//改变窗口的大小
            {
            case 11:wid.setTopLeft(wid.topLeft() + ptemp); break;//左上角
            case 13:wid.setTopRight(wid.topRight() + ptemp); break;//右上角
            case 31:wid.setBottomLeft(wid.bottomLeft() + ptemp); break;//左下角
            case 33:wid.setBottomRight(wid.bottomRight() + ptemp); break;//右下角
            case 12:wid.setTop(wid.top() + ptemp.y()); break;//中上角
            case 21:wid.setLeft(wid.left() + ptemp.x()); break;//中左角
            case 23:wid.setRight(wid.right() + ptemp.x()); break;//中右角
            case 32:wid.setBottom(wid.bottom() + ptemp.y()); break;//中下角
            }
            setGeometry(wid);
        }
        _plast = event->globalPos();//更新位置
    }
}

//获取光标在窗口所在区域的 列  返回行列坐标
int RailwayPowerInterface::countFlag(QPoint p,int row)//计算鼠标在哪一列和哪一行
{
    if(p.y()<MARGIN)
        return 10+row;
    else if(p.y()>this->height()-MARGIN)
        return 30+row;
    else
        return 20+row;
}

//获取光标在窗口所在区域的 行   返回行数
int RailwayPowerInterface::countRow(QPoint p)
{
    return (p.x()<MARGIN) ? 1 : (p.x()>(this->width() - MARGIN) ? 3 : 2);
}

//根据鼠标所在位置改变鼠标指针形状
void RailwayPowerInterface::setCursorType(int flag)
{
    switch(flag)
    {
    case 11:
    case 33:
        setCursor(Qt::SizeFDiagCursor);
        break;
    case 13:
    case 31:
        setCursor(Qt::SizeBDiagCursor);break;
    case 21:
    case 23:
        setCursor(Qt::SizeHorCursor);break;
    case 12:
    case 32:
        setCursor(Qt::SizeVerCursor);break;
    case 22:
        setCursor(Qt::ArrowCursor);
        QApplication::restoreOverrideCursor();//恢复鼠标指针性状
        break;
    }
}
  • 13
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值