Qt如何实现拉伸控件

这篇文章给大家分享的是有关Qt如何实现拉伸控件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

公司主营业务:网站设计、做网站、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出万安免费做网站回馈大家。

一、前言

插件控件加载了,拖曳控件也实现了,接下来就是一个最难点了,跟QtDesigner或者其他开发环境一样,能够任意自由的拉伸控件大小,移动位置,为了这个功能,还特别编写了一个控件来实现这个功能,名字叫SelectWidget描点跟随窗体控件,大致的原理就是安装事件过滤器,在生成控件的时候将该控件传入描点跟随控件,自动识别鼠标的位置,按下拉动的距离来改变控件的大小,绘制描点指示器以便用户拉伸使用。 描点跟随控件可设置是否绘制描点、边距、描点颜色、描点尺寸、描点样式 正方形+圆形、选中边框宽度,支持上下左右按键移动窗体,支持delete键删除窗体,支持八个描点改变窗体大小尺寸。

二、实现的功能

  1. 自动加载插件文件中的所有控件生成列表,默认自带的控件超过120个。

  2. 拖曳到画布自动生成对应的控件,所见即所得。

  3. 右侧中文属性栏,改变对应的属性立即应用到对应选中控件,直观简洁,非常适合小白使用。

  4. 独创属性栏文字翻译映射机制,效率极高,可以非常方便拓展其他语言的属性栏。

  5. 所有控件的属性自动提取并显示在右侧属性栏,包括枚举值下拉框等。

  6. 支持手动选择插件文件,外部导入插件文件。

  7. 可以将当前画布的所有控件配置信息导出到xml文件。

  8. 可以手动选择xml文件打开控件布局,自动根据xml文件加载控件。

  9. 可拉动滑动条、勾选模拟数据复选框、文本框输入,三种方式来生成数据应用所有控件。

  10. 控件支持八个方位拉动调整大小,自适应任意分辨率,可键盘上下左右微调位置。

  11. 打通了串口采集、网络采集、数据库采集三种方式设置数据。

  12. 代码极其精简,注释非常详细,可以作为组态的雏形,自行拓展更多的功能。

  13. 纯Qt编写,支持任意Qt版本+任意编译器+任意系统。

三、效果图

Qt如何实现拉伸控件

四、核心代码

bool SelectWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == widget) {
        if (event->type() == QEvent::Resize) {
            //设置当前窗体大小为跟随窗体的大小增加部分
            this->resize(this->widget->size() + QSize(padding * 2, padding * 2));
        } else if (event->type() == QEvent::Move) {
            //将当前窗体移到偏移位置
            this->move(this->widget->pos() - QPoint(padding, padding));
        }
    } else {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = dynamic_cast(event);
            if (keyEvent->key() == Qt::Key_Left) {
                this->move(this->pos() - QPoint(1, 0));
            } else if (keyEvent->key() == Qt::Key_Right) {
                this->move(this->pos() + QPoint(1, 0));
            } else if (keyEvent->key() == Qt::Key_Up) {
                this->move(this->pos() - QPoint(0, 1));
            } else if (keyEvent->key() == Qt::Key_Down) {
                this->move(this->pos() + QPoint(0, 1));
            } else if (keyEvent->key() == Qt::Key_Delete) {
                emit widgetDelete(widget);
                widget->deleteLater();
                this->deleteLater();
                widget = 0;
            }

            //重新设置附带窗体的位置和大小
            if (widget != 0) {
                widget->setGeometry(this->x() + padding, this->y() + padding, this->width() - padding * 2, this->height() - padding * 2);
            }

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

        QMouseEvent *mouseEvent = static_cast(event);
        if (mouseEvent->type() == QEvent::MouseButtonPress) {
            //记住当前控件坐标和宽高以及鼠标按下的坐标
            rectX = this->x();
            rectY = this->y();
            rectW = this->width();
            rectH = this->height();
            lastPos = mouseEvent->pos();

            //判断按下的手柄的区域位置
            if (rectLeft.contains(lastPos)) {
                pressedLeft = true;
            } else if (rectRight.contains(lastPos)) {
                pressedRight = true;
            } else if (rectTop.contains(lastPos)) {
                pressedTop = true;
            } else if (rectBottom.contains(lastPos)) {
                pressedBottom = true;
            } else if (rectLeftTop.contains(lastPos)) {
                pressedLeftTop = true;
            } else if (rectRightTop.contains(lastPos)) {
                pressedRightTop = true;
            } else if (rectLeftBottom.contains(lastPos)) {
                pressedLeftBottom = true;
            } else if (rectRightBottom.contains(lastPos)) {
                pressedRightBottom = true;
            } else {
                pressed = true;
            }

            if (widget != 0) {
                emit widgetPressed(widget);
            }
        } else if (mouseEvent->type() == QEvent::MouseMove) {
            //根据当前鼠标位置,计算XY轴移动了多少
            QPoint pos = mouseEvent->pos();
            int dx = pos.x() - lastPos.x();
            int dy = pos.y() - lastPos.y();

            //根据按下处的位置判断是否是移动控件还是拉伸控件
            if (pressed) {
                this->move(this->x() + dx, this->y() + dy);
            } else if (pressedLeft) {
                int resizeW = this->width() - dx;
                if (this->minimumWidth() <= resizeW) {
                    this->setGeometry(this->x() + dx, rectY, resizeW, rectH);
                }
            } else if (pressedRight) {
                this->setGeometry(rectX, rectY, rectW + dx, rectH);
            } else if (pressedTop) {
                int resizeH = this->height() - dy;
                if (this->minimumHeight() <= resizeH) {
                    this->setGeometry(rectX, this->y() + dy, rectW, resizeH);
                }
            } else if (pressedBottom) {
                this->setGeometry(rectX, rectY, rectW, rectH + dy);
            } else if (pressedLeftTop) {
                int resizeW = this->width() - dx;
                int resizeH = this->height() - dy;
                if (this->minimumWidth() <= resizeW) {
                    this->setGeometry(this->x() + dx, this->y(), resizeW, resizeH);
                }
                if (this->minimumHeight() <= resizeH) {
                    this->setGeometry(this->x(), this->y() + dy, resizeW, resizeH);
                }
            } else if (pressedRightTop) {
                int resizeW = rectW + dx;
                int resizeH = this->height() - dy;
                if (this->minimumHeight() <= resizeH) {
                    this->setGeometry(this->x(), this->y() + dy, resizeW, resizeH);
                }
            } else if (pressedLeftBottom) {
                int resizeW = this->width() - dx;
                int resizeH = rectH + dy;
                if (this->minimumWidth() <= resizeW) {
                    this->setGeometry(this->x() + dx, this->y(), resizeW, resizeH);
                }
                if (this->minimumHeight() <= resizeH) {
                    this->setGeometry(this->x(), this->y(), resizeW, resizeH);
                }
            } else if (pressedRightBottom) {
                int resizeW = rectW + dx;
                int resizeH = rectH + dy;
                this->setGeometry(this->x(), this->y(), resizeW, resizeH);
            }

            //重新设置附带窗体的位置和大小
            if (widget != 0) {
                widget->setGeometry(this->x() + padding, this->y() + padding, this->width() - padding * 2, this->height() - padding * 2);
            }
        } else if (mouseEvent->type() == QEvent::MouseButtonRelease) {
            pressed = false;
            pressedLeft = false;
            pressedRight = false;
            pressedTop = false;
            pressedBottom = false;
            pressedLeftTop = false;
            pressedRightTop = false;
            pressedLeftBottom = false;
            pressedRightBottom = false;

            if (widget != 0) {
                emit widgetRelease(widget);
            }
        }
    }

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

void SelectWidget::resizeEvent(QResizeEvent *)
{
    //重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
    int width = this->width();
    int height = this->height();

    //左侧描点区域
    rectLeft = QRectF(0, height / 2 - pointSize / 2, pointSize, pointSize);
    //上侧描点区域
    rectTop = QRectF(width / 2 - pointSize / 2, 0, pointSize, pointSize);
    //右侧描点区域
    rectRight = QRectF(width - pointSize, height / 2 - pointSize / 2, pointSize, pointSize);
    //下侧描点区域
    rectBottom = QRectF(width / 2 - pointSize / 2, height - pointSize, pointSize, pointSize);

    //左上角描点区域
    rectLeftTop = QRectF(0, 0, pointSize, pointSize);
    //右上角描点区域
    rectRightTop = QRectF(width - pointSize, 0, pointSize, pointSize);
    //左下角描点区域
    rectLeftBottom = QRectF(0, height - pointSize, pointSize, pointSize);
    //右下角描点区域
    rectRightBottom = QRectF(width - pointSize, height - pointSize, pointSize, pointSize);
}

void SelectWidget::mouseMoveEvent(QMouseEvent *e)
{
    //计算当前鼠标位置是否在某个区域内,自动更新鼠标形状
    QPoint p = e->pos();
    if (rectLeft.contains(p)) {
        this->setCursor(Qt::SizeHorCursor);
    } else if (rectTop.contains(p)) {
        this->setCursor(Qt::SizeVerCursor);
    } else if (rectRight.contains(p)) {
        this->setCursor(Qt::SizeHorCursor);
    } else if (rectBottom.contains(p)) {
        this->setCursor(Qt::SizeVerCursor);
    } else if (rectLeftTop.contains(p)) {
        this->setCursor(Qt::SizeFDiagCursor);
    } else if (rectRightTop.contains(p)) {
        this->setCursor(Qt::SizeBDiagCursor);
    } else if (rectLeftBottom.contains(p)) {
        this->setCursor(Qt::SizeBDiagCursor);
    } else if (rectRightBottom.contains(p)) {
        this->setCursor(Qt::SizeFDiagCursor);
    } else {
        this->setCursor(Qt::ArrowCursor);
    }
}

感谢各位的阅读!关于“Qt如何实现拉伸控件”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!


网页标题:Qt如何实现拉伸控件
链接地址:http://myzitong.com/article/geopcd.html