array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 Qt 无边框拖拽实现 - 爱码网

Qt 无边框拖拽实现

头文件定义:

class TDragProxy:public QObject
{
Q_OBJECT

public:
    TDragProxy(QWidget* parent);
    ~TDragProxy();

protected:
    enum WidgetRegion
    {
        Top = 0,
        TopRight,
        Right,
        RightBottom,
        Bottom,
        LeftBottom,
        Left,
        LeftTop,
        Inner,
        Unknown
    };

public:
    void SetBorderWidth(int top, int right, int bottom, int left);//设置四周边框宽度
    void SetDragEnable(bool bEnable); //最大化无拖拽效果

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

    void MakeRegions();
    WidgetRegion HitTest(const QPoint& pos);
    void UpdateGeometry(int x, int y, int w, int h);

    //鼠标从边框快速移到窗体内子控件上,可能会造成鼠标样式未改变,这里使用计时器监控
    void StartCursorTimer();
    void StopCursorTimer();

private:
    QWidget* m_proxyWidget; //代理的窗体
    int m_top,m_right,m_bottom,m_left; //四周宽度
    QRect m_regions[9]; //九宫格,对应9个区域

    QPoint m_originPosGlobal; //拖拽前鼠标位置
    QRect m_originGeo; //拖拽前窗体位置和大小

    bool m_mousePressed; //鼠标是否按下
    WidgetRegion m_regionPressed; //记录鼠标按下时所点击的区域

    int m_cursorTimerId;

    bool m_bDragEnable;
    bool m_bBorderMini; //边框为1时,处理四对角位置
};

CPP文件实现:

TDragProxy::TDragProxy(QWidget *parent)
:QObject((QObject*)parent)
, m_bDragEnable(true)
, m_bBorderMini(false)
{
    m_proxyWidget = parent;
    m_top = m_right = m_bottom = m_left = 0;

    m_proxyWidget->setMouseTracking(true);
    m_proxyWidget->installEventFilter(this);    // 代理窗体事件

    m_mousePressed = false;
    m_regionPressed = Unknown;

    m_cursorTimerId = 0;
}

TDragProxy::~TDragProxy()
{
}

void TDragProxy::SetBorderWidth(int top, int right, int bottom, int left)
{
    m_top = top;
    m_right = right;
    m_bottom = bottom;
    m_left = left;

    if (m_top == 1 && m_right == 1 && m_bottom == 1 && m_left==1)
    {
        m_bBorderMini = true;
    }

    MakeRegions();
}

void TDragProxy::UpdateGeometry(int x, int y, int w, int h)
{
    int minWidth = m_proxyWidget->minimumWidth();
    int minHeight = m_proxyWidget->minimumHeight();
    int maxWidth = m_proxyWidget->maximumWidth();
    int maxHeight = m_proxyWidget->maximumHeight();

    if (w < minWidth || w > maxWidth || h < minHeight || h > maxHeight)
    {
        return;
    }

    m_proxyWidget->setGeometry(x, y, w, h);
}

bool TDragProxy::eventFilter(QObject* obj, QEvent* event)
{
    if (!m_bDragEnable)
    {
        return QObject::eventFilter(obj, event);
    }

    QEvent::Type eventType = event->type();
    if (eventType == QEvent::MouseMove)
    {
        QMouseEvent* mouseEvent = (QMouseEvent*)event;
        QPoint curPosLocal = mouseEvent->pos();
        TDragProxy::WidgetRegion regionType = HitTest(curPosLocal);
        QPoint curPosGlobal = m_proxyWidget->mapToGlobal(curPosLocal);

        if (!m_mousePressed)    // 鼠标未按下
        {
            switch (regionType)
            {
                case Top:
                case Bottom:
                    m_proxyWidget->setCursor(Qt::SizeVerCursor);
                    break;
                case TopRight:
                case LeftBottom:
                    m_proxyWidget->setCursor(Qt::SizeBDiagCursor);
                    break;
                case Right:
                case Left:
                    m_proxyWidget->setCursor(Qt::SizeHorCursor);
                    break;
                case RightBottom:
                case LeftTop:
                    m_proxyWidget->setCursor(Qt::SizeFDiagCursor);
                    break;
                default:
                    m_proxyWidget->setCursor(Qt::ArrowCursor);
                    break;
            }

            StartCursorTimer();
        }
        else    // 鼠标已按下
        {
            QRect geo = m_proxyWidget->geometry();

            if (m_regionPressed == Inner)
            {
                m_proxyWidget->move(m_originGeo.topLeft() + curPosGlobal - m_originPosGlobal);
            }
            else if (m_regionPressed == Top)
            {
                int dY = curPosGlobal.y() - m_originPosGlobal.y();
                UpdateGeometry(m_originGeo.x(), m_originGeo.y() + dY, m_originGeo.width(), m_originGeo.height() - dY);
            }
            else if (m_regionPressed == TopRight)
            {
                QPoint dXY = curPosGlobal - m_originPosGlobal;
                UpdateGeometry(m_originGeo.x(), m_originGeo.y() + dXY.y(), m_originGeo.width() + dXY.x(), m_originGeo.height() - dXY.y());
            }
            else if (m_regionPressed == Right)
            {
                int dX = curPosGlobal.x() - m_originPosGlobal.x();
                UpdateGeometry(m_originGeo.x(), m_originGeo.y(), m_originGeo.width() + dX, m_originGeo.height());
            }
            else if (m_regionPressed == RightBottom)
            {
                QPoint dXY = curPosGlobal - m_originPosGlobal;
                UpdateGeometry(m_originGeo.x(), m_originGeo.y(), m_originGeo.width() + dXY.x(), m_originGeo.height() + dXY.y());
            }
            else if (m_regionPressed == Bottom)
            {
                int dY = curPosGlobal.y() - m_originPosGlobal.y();
                UpdateGeometry(m_originGeo.x(), m_originGeo.y(), m_originGeo.width(), m_originGeo.height() + dY);
            }
            else if (m_regionPressed == LeftBottom)
            {
                QPoint dXY = curPosGlobal - m_originPosGlobal;
                UpdateGeometry(m_originGeo.x() + dXY.x(), m_originGeo.y(), m_originGeo.width() - dXY.x(), m_originGeo.height() + dXY.y());
            }
            else if (m_regionPressed == Left)
            {
                int dX = curPosGlobal.x() - m_originPosGlobal.x();
                UpdateGeometry(m_originGeo.x() + dX, m_originGeo.y(), m_originGeo.width() - dX, m_originGeo.height());
            }
            else if (m_regionPressed == LeftTop)
            {
                QPoint dXY = curPosGlobal - m_originPosGlobal;
                UpdateGeometry(m_originGeo.x() + dXY.x(), m_originGeo.y() + dXY.y(), m_originGeo.width() - dXY.x(), m_originGeo.height() - dXY.y());
            }
        }
    }
    else if (eventType == QEvent::MouseButtonPress)
    {
        QMouseEvent* mouseEvent = (QMouseEvent*)event;
        if (mouseEvent->button() == Qt::LeftButton)
        {
            m_mousePressed = true;

            QPoint curPos = mouseEvent->pos();
            m_regionPressed = HitTest(curPos);

            m_originPosGlobal = m_proxyWidget->mapToGlobal(curPos);
            m_originGeo = m_proxyWidget->geometry();

            StopCursorTimer();
        }
    }
    else if (eventType == QEvent::MouseButtonRelease)
    {
        m_mousePressed = false;
        m_regionPressed = Unknown;

        m_proxyWidget->setCursor(Qt::ArrowCursor);
    }
    else if (eventType == QEvent::Resize)
    {
        MakeRegions();
    }
    else if (eventType == QEvent::Leave)
    {
        m_proxyWidget->setCursor(Qt::ArrowCursor);
        StopCursorTimer();
    }
    else if (eventType == QEvent::Timer)
    {
        QTimerEvent* timerEvent = (QTimerEvent*)event;
        if (timerEvent->timerId() == m_cursorTimerId)
        {
            if (m_regions[Inner].contains(m_proxyWidget->mapFromGlobal(QCursor::pos())))
            {
                m_proxyWidget->setCursor(Qt::ArrowCursor);
                StopCursorTimer();
            }
        }
    }
    return QObject::eventFilter(obj, event);
}

void TDragProxy::StartCursorTimer()
{
    StopCursorTimer();
    m_cursorTimerId = m_proxyWidget->startTimer(50);
}

void TDragProxy::StopCursorTimer()
{
    if (m_cursorTimerId != 0)
    {
        m_proxyWidget->killTimer(m_cursorTimerId);
        m_cursorTimerId = 0;
    }
}

void TDragProxy::MakeRegions()
{
    int width = m_proxyWidget->width();
    int height = m_proxyWidget->height();

    if (m_bBorderMini)
    {
        m_regions[Top] = QRect(2, 0, width - 4, 1);
        m_regions[TopRight] = QRect(width - 2, 0, 2, 2);
        m_regions[Right] = QRect(width - 1, 2, 1, height - 4);
        m_regions[RightBottom] = QRect(width - 2, height - 2, 2, 2);
        m_regions[Bottom] = QRect(2, height - 1, width - 4, 1);
        m_regions[LeftBottom] = QRect(0, height - 2, 2, 2);
        m_regions[Left] = QRect(0, 2, 1, height - 4);
        m_regions[LeftTop] = QRect(0, 0, 2, 2); 
        m_regions[Inner] = QRect(2, 2, width - 4, height - 4);
    }
    else
    {
        m_regions[Top] = QRect(m_left, 0, width - m_left - m_right, m_top);
        m_regions[TopRight] = QRect(width - m_right, 0, m_right, m_top);
        m_regions[Right] = QRect(width - m_right, m_top, m_right, height - m_top - m_bottom);
        m_regions[RightBottom] = QRect(width - m_right, height - m_bottom, m_right, m_bottom);
        m_regions[Bottom] = QRect(m_left, height - m_bottom, width - m_left - m_right, m_bottom);
        m_regions[LeftBottom] = QRect(0, height - m_bottom, m_left, m_bottom);
        m_regions[Left] = QRect(0, m_top, m_left, height - m_top - m_bottom);
        m_regions[LeftTop] = QRect(0, 0, m_left, m_top);
        m_regions[Inner] = QRect(m_left, m_top, width - m_left - m_right, height - m_top - m_bottom);
    }
}

TDragProxy::WidgetRegion TDragProxy::HitTest(const QPoint& pos)
{
    for (int i = 0; i < 9; i++)
    {
        const QRect rect = m_regions[i];
        if (rect.contains(pos))
        {
            return TDragProxy::WidgetRegion(i);
        }
    }
    return Unknown;
}

void TDragProxy::SetDragEnable(bool bEnable)
{
    m_bDragEnable = bEnable;
}

接口调用例子:

setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
setMinimumSize(MWS_MIN_WIDTH, MWS_MIN_HEIGHT);

mpDragProxy = new TDragProxy(this);
mpDragProxy->SetBorderWidth(MWS_BORD_WIDTH, MWS_BORD_WIDTH, MWS_BORD_WIDTH, MWS_BORD_WIDTH);

相关文章: