溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Qt如何實現(xiàn)拉伸控件

發(fā)布時間:2021-12-15 10:18:18 來源:億速云 閱讀:398 作者:小新 欄目:互聯(lián)網(wǎng)科技

這篇文章給大家分享的是有關(guān)Qt如何實現(xiàn)拉伸控件的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

一、前言

插件控件加載了,拖曳控件也實現(xiàn)了,接下來就是一個最難點了,跟QtDesigner或者其他開發(fā)環(huán)境一樣,能夠任意自由的拉伸控件大小,移動位置,為了這個功能,還特別編寫了一個控件來實現(xiàn)這個功能,名字叫SelectWidget描點跟隨窗體控件,大致的原理就是安裝事件過濾器,在生成控件的時候?qū)⒃摽丶魅朊椟c跟隨控件,自動識別鼠標的位置,按下拉動的距離來改變控件的大小,繪制描點指示器以便用戶拉伸使用。 描點跟隨控件可設置是否繪制描點、邊距、描點顏色、描點尺寸、描點樣式 正方形+圓形、選中邊框?qū)挾?,支持上下左右按鍵移動窗體,支持delete鍵刪除窗體,支持八個描點改變窗體大小尺寸。

二、實現(xiàn)的功能

  1. 自動加載插件文件中的所有控件生成列表,默認自帶的控件超過120個。

  2. 拖曳到畫布自動生成對應的控件,所見即所得。

  3. 右側(cè)中文屬性欄,改變對應的屬性立即應用到對應選中控件,直觀簡潔,非常適合小白使用。

  4. 獨創(chuàng)屬性欄文字翻譯映射機制,效率極高,可以非常方便拓展其他語言的屬性欄。

  5. 所有控件的屬性自動提取并顯示在右側(cè)屬性欄,包括枚舉值下拉框等。

  6. 支持手動選擇插件文件,外部導入插件文件。

  7. 可以將當前畫布的所有控件配置信息導出到xml文件。

  8. 可以手動選擇xml文件打開控件布局,自動根據(jù)xml文件加載控件。

  9. 可拉動滑動條、勾選模擬數(shù)據(jù)復選框、文本框輸入,三種方式來生成數(shù)據(jù)應用所有控件。

  10. 控件支持八個方位拉動調(diào)整大小,自適應任意分辨率,可鍵盤上下左右微調(diào)位置。

  11. 打通了串口采集、網(wǎng)絡采集、數(shù)據(jù)庫采集三種方式設置數(shù)據(jù)。

  12. 代碼極其精簡,注釋非常詳細,可以作為組態(tài)的雛形,自行拓展更多的功能。

  13. 純Qt編寫,支持任意Qt版本+任意編譯器+任意系統(tǒng)。

三、效果圖

Qt如何實現(xiàn)拉伸控件

四、核心代碼

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<QKeyEvent *>(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<QMouseEvent *>(event);
        if (mouseEvent->type() == QEvent::MouseButtonPress) {
            //記住當前控件坐標和寬高以及鼠標按下的坐標
            rectX = this->x();
            rectY = this->y();
            rectW = this->width();
            rectH = this->height();
            lastPos = mouseEvent->pos();

            //判斷按下的手柄的區(qū)域位置
            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) {
            //根據(jù)當前鼠標位置,計算XY軸移動了多少
            QPoint pos = mouseEvent->pos();
            int dx = pos.x() - lastPos.x();
            int dy = pos.y() - lastPos.y();

            //根據(jù)按下處的位置判斷是否是移動控件還是拉伸控件
            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 *)
{
    //重新計算八個描點的區(qū)域,描點區(qū)域的作用還有就是計算鼠標坐標是否在某一個區(qū)域內(nèi)
    int width = this->width();
    int height = this->height();

    //左側(cè)描點區(qū)域
    rectLeft = QRectF(0, height / 2 - pointSize / 2, pointSize, pointSize);
    //上側(cè)描點區(qū)域
    rectTop = QRectF(width / 2 - pointSize / 2, 0, pointSize, pointSize);
    //右側(cè)描點區(qū)域
    rectRight = QRectF(width - pointSize, height / 2 - pointSize / 2, pointSize, pointSize);
    //下側(cè)描點區(qū)域
    rectBottom = QRectF(width / 2 - pointSize / 2, height - pointSize, pointSize, pointSize);

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

void SelectWidget::mouseMoveEvent(QMouseEvent *e)
{
    //計算當前鼠標位置是否在某個區(qū)域內(nèi),自動更新鼠標形狀
    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);
    }
}

感謝各位的閱讀!關(guān)于“Qt如何實現(xiàn)拉伸控件”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

qt
AI