设为首页 加入收藏

TOP

Qt无边框窗体-最大化时支持拖拽还原(一)
2019-09-03 03:43:09 】 浏览:72
Tags:边框 窗体 最大化 支持 还原

原文链接:Markdown模板

一、概述

用Qt进行开发界面时,既想要实现友好的用户交互又想界面漂亮,那么自定义界面就必不可少。其中有一个操作就是是我们每一个Qter开发者都要会的,而且是经常进行的。

Qt::FramelessWindowHint这个属性想必大家都使用过,有些同学可能对这个属性很了解,也用的是炉火纯青,今天我们也来说说这个属性。

关于这个无边框属性网上也有一些文章,有些谈论的是bug,当然了这是针对不同os而言,也有些是跟其他第三方库混合使用时的问题。可是问题归问题,想要实现自定义的优秀界面这个属性也是必不可少的。

今天我们就来实现一个无边框窗体最大化时,支持拖拽标题栏进行还原的功能。

无边框窗体支持缩放、移动这些不属于本篇文章的内容,本篇文章主要讲解怎么实现最大化时拖拽标题栏进行还原窗体,本篇文章的代码依赖于博主之前封装的一个拖拽代理类。

二、效果展示

如效果图所示,做了一个简单的事例,双击标题栏窗体最大化,这个时候如果进行标题栏拖拽,当鼠标按下并移动一段距离时窗体恢复normal状态。

恢复normal状态下的窗体仍然支持放大和缩小,有接口可以设置。

三、demo制作

demo的制作过程还是比较简单的,分为如下几步

1、设计窗体

通过desinger设计器我们拖拽了一个大致窗体内容,为了更好的展示效果,标题栏加上了icon和背景色

2、双击放大

鼠标双击标题栏放大这个功能实现起来方法也比较多,这里博主选择了代码量最少并且实现起来最简单的方式,直接把标题栏的事件循环安装到了主窗体上。

ui.widget->installEventFilter(this);

接下来我们就需要重写主窗口的eventFilter函数即可

bool DragWidget::eventFilter(QObject * watched, QEvent * event)
{
    if (watched == ui.widget)
    {
        if (event->type() == QEvent::MouseButtonDblClick)
        {
            if (isMaximized())
            {
                showNormal();
                m_handler.setWidgetResizable(true);
                m_handler.setWidgetMovable(true);
            }
            else
            {
                showMaximized();
                m_handler.setWidgetResizable(false);
                m_handler.setWidgetMovable(false);
            }
        }
    }

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

细心的同学就会发现代码里有一个m_handler变量,这个类就是博主之前自己封装的一个拖拽代理,通过接口可以设置被代理的窗体,并设置需要代理哪些行为。

本篇文章中所演示的事例代码,我们代理了主窗口上标题栏部分的移动事件和整个窗体的缩放事件,设置代码如下所示

m_handler.activateOn(this);
m_handler.useLocalMoveabled(true);
m_handler.addLocalWidget(ui.widget);
m_handler.setMaximumMove(true, true);

拖拽代理类内容比较多,本篇文章暂不讲解。

四、拖拽

为了更好的理解本篇文章,这里需要把拖拽代理类的头文件放出来,这样更有利于大家理解。

接口都比较简单,代码中也有注释,大家自行阅读。

class WidgetResizeHandler : public QObject
{

public:
    explicit WidgetResizeHandler(QObject* parent = 0);
    ~WidgetResizeHandler();

public:
    void activateOn(QWidget * topLevelWidget);//添加topLevelWidget事件代理
    void removeFrom(QWidget * topLevelWidget);//移除topLevelWidget事件代理

    Qt::CursorShape CursorShape(QWidget * widget);

    //窗口移动 default:true
    void setWidgetMovable(bool movable);
    bool isWidgetMovable();

    //大小可变 default:true
    void setWidgetResizable(bool resizable);
    bool isWidgetResizable();

    // 橡胶式窗口移动 default:false
    void useRubberBandOnMove(bool use);
    bool isUsingRubberBandOnMove();

    //橡胶式修改大小 default:false
    void useRubberBandOnResize(bool use);
    bool isUsingRubberBandOnResisze();

    void setBorderWidth(int newBorderWidth);
    int borderWidth();

    //局部可移动
    void useLocalMoveabled(bool use);
    void addLocalWidget(QWidget *);

    //最大化时支持拖拽 参数2表示是否可放大缩小
    void setMaximumMove(bool move, bool resize = false);

protected:
    virtual bool eventFilter(QObject * obj, QEvent * event) Q_DECL_OVERRIDE;

private:
    WidgetResizeHandlerImpl * d_ptr;
};

值得注意的是最后一个setMaximumMove接口,他就是我们今天的猪脚-是否支持最大化时拖拽。当我们设置了这个接口后,窗体最大化时也就能进行拖拽,并还原到之前的normal状态。

文章第三小节讲解demo时,说过主窗体已经被代理拖拽类进行了事件代理,那么主窗体的所有事件首先都会传递给这个代理类,这里我们需要重点关注下鼠标按下时移动事件。

void WidgetData::handleMouseMoveEvent(QMouseEvent* event)
{
    if (mLeftButtonPressed)
    {
        if (d_ptr->mWidgetResizable && mPressedMousePos.onEdges)
        {
            resizeWidget(event->globalPos());
        }
        else if (d_ptr->mWidgetMovable)
        {
            moveWidget(event->globalPos());
        }
        else if (d_ptr->mMaxMovable)
        {
            if (mWidget->i
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇剑指offer22:从上往下打印出二叉.. 下一篇剑指offer11:输入一个整数,输出..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目