千家信息网

Qt如何实现拉伸控件

发表于:2024-09-21 作者:千家信息网编辑
千家信息网最后更新 2024年09月21日,这篇文章给大家分享的是有关Qt如何实现拉伸控件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、前言插件控件加载了,拖曳控件也实现了,接下来就是一个最难点了,跟QtDesi
千家信息网最后更新 2024年09月21日Qt如何实现拉伸控件

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

一、前言

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

二、实现的功能

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

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

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

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

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

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

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

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

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

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

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

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

  13. 纯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如何实现拉伸控件"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

0