Qt实现对齐线功能的示例代码

2022-11-13 09:11:28 代码 示例 对齐

现有功能

1.添加任意数量的按钮。

2.移动按钮,通过对齐线来设置按钮位置。

3.自动吸附。

运行结果

源码

button.h

#ifndef BUTTON_H
#define BUTTON_H

#include <QPushButton>
#include <QWidget>
#include <QMouseEvent>


class Button: public QPushButton
{
    Q_OBJECT

public:
    Button(QString text, QWidget *parent=nullptr);
    ~Button();

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

private:
    int startX;
    int startY;
};

#endif // BUTTON_H

button.cpp

#include "button.h"
#include "window.h"

Button::Button(QString text, QWidget *parent):QPushButton(text, parent)
{

}

Button::~Button() {

}

void Button::mousePressEvent(QMouseEvent *event) {
    QPushButton::mousePressEvent(event);
    this->startX = event->x();
    this->startY = event->y();
}

void Button::mouseMoveEvent(QMouseEvent *event) {
    QPushButton::mouseMoveEvent(event);
    int disX = event->x() - this->startX;
    int disY = event->y() - this->startY;
    this->move(this->x()+disX, this->y()+disY);

    Window *win = (Window*) this->parent();
    win->checkPos(this);
}

void Button::mouseReleaseEvent(QMouseEvent *event) {
    QPushButton::mouseReleaseEvent(event);
}

window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>
#include <QSpinBox>
#include <QPainter>
#include <QPaintEvent>
#include <QPushButton>
#include <QList>
#include <QPen>

#include "button.h"

class Window : public QWidget
{
    Q_OBJECT

public:
    Window(QWidget *parent = nullptr);
    ~Window();
    void checkPos(Button *movingBtn);                   // 检查按钮位置

protected:
    void paintEvent(QPaintEvent *event);

private slots:
    void changeBtnNum(int newNum);                      // 改变按钮数量

private:
    void drawVerticalCenterLine(QPainter &painter);     // 绘制垂直中心线
    void drawHorizontalCenterLine(QPainter &painter);   // 绘制水平中心线
    void drawBtnLeftLine(QPainter &painter);            // 绘制按钮左侧线
    void drawBtnTopLine(QPainter &painter);             // 绘制按钮顶部线
    void checkBtnTopLine(Button *movingBtn);            // 比对当前移动按钮和其他按钮顶部的位置
    void checkBtnLeftLine(Button *movingBtn);           // 比对当前移动按钮和其他按钮左侧的位置
    void checkWindowCenterLines(Button *movingBtn);     // 比对按钮和中心线的位置

private:
    QSpinBox *spinBox;
    QList<Button *> btnList;

    int lineShowThresholdValue;                         // 线条显示阈值
    int lineAdsorbThresholdValue;                       // 线条吸附阈值
    bool isVerticalCenterLineShown;                     // 是否显示中心竖线
    bool isHorizontalCenterLineShown;                   // 是否显示中心横线
    bool isBtnLeftLineShown;                            // 是否显示按钮左侧线条
    bool isBtnTopLineShown;                             // 是否显示按钮顶部线条

    int btnLeftLineX;                                   // 按钮左侧线x坐标
    int btnTopLineY;                                    // 按钮顶部线y坐标

    QPen pen1;                                          // 用来绘制中心对齐线
    QPen pen2;                                          // 用来绘制按钮间的对齐线
};
#endif // WINDOW_H

window.cpp

#include "window.h"
#include <Qt>
#include <QString>
#include <cstdlib>

Window::Window(QWidget *parent): QWidget(parent)
{
    this->resize(500, 500);
    this->spinBox = new QSpinBox(this);
    this->spinBox->setValue(0);
    this->spinBox->move(10, 10);
    connect(this->spinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Window::changeBtnNum);

    this->lineShowThresholdValue = 5;
    this->lineAdsorbThresholdValue = 3;

    this->isVerticalCenterLineShown = false;
    this->isHorizontalCenterLineShown = false;
    this->isBtnLeftLineShown = false;
    this->isBtnTopLineShown = false;

    this->btnLeftLineX = 0;
    this->btnTopLineY = 0;

    this->pen1 = QPen(Qt::darkBlue);
    this->pen2 = QPen(Qt::gray);
}

Window::~Window()
{
}

void Window::paintEvent(QPaintEvent *event) {
    QWidget::paintEvent(event);

    QPainter painter(this);
    painter.setPen(this->pen1);

    if (this->isVerticalCenterLineShown) {
        this->drawVerticalCenterLine(painter);
    }

    if (this->isHorizontalCenterLineShown) {
        this->drawHorizontalCenterLine(painter);
    }

    painter.setPen(this->pen2);
    if (this->isBtnLeftLineShown) {
        this->drawBtnLeftLine(painter);
    }

    if (this->isBtnTopLineShown) {
        this->drawBtnTopLine(painter);
    }
}

void Window::drawVerticalCenterLine(QPainter &painter) {
    int verticalCenterValue = int(this->width() / 2);
    painter.drawLine(verticalCenterValue, 0, verticalCenterValue, this->height());
}

void Window::drawHorizontalCenterLine(QPainter &painter) {
    int horizontalCenterValue = int(this->height() / 2);
    painter.drawLine(0, horizontalCenterValue, this->width(), horizontalCenterValue);
}

void Window::drawBtnLeftLine(QPainter &painter) {
    int x = this->btnLeftLineX;
    painter.drawLine(x, 0, x, this->height());
}

void Window::drawBtnTopLine(QPainter &painter) {
    int y = this->btnTopLineY;
    painter.drawLine(0, y, this->width(), y);
}

void Window::checkPos(Button *movingBtn) {
    this->checkBtnTopLine(movingBtn);
    this->checkBtnLeftLine(movingBtn);
    this->checkWindowCenterLines(movingBtn);
    this->update();
}

void Window::checkBtnTopLine(Button *movingBtn) {
    int x = movingBtn->x();
    int y = movingBtn->y();

    for (int i=0; i<this->btnList.size(); i++) {
        Button *btn = this->btnList.at(i);
        if (btn == movingBtn) {
            continue;
        }

        if (y>btn->y()-this->lineShowThresholdValue && y<btn->y()+this->lineShowThresholdValue) {
            this->isBtnTopLineShown = true;
            this->btnTopLineY = btn->y();

            if (y>btn->y()-this->lineAdsorbThresholdValue && y<btn->y()+this->lineAdsorbThresholdValue) {
                movingBtn->move(x, btn->y());
            }
            return;
        }
        else {
            this->isBtnTopLineShown = false;
            this->btnTopLineY = 0;
        }
    }
}

void Window::checkBtnLeftLine(Button *movingBtn) {
    int x = movingBtn->x();
    int y = movingBtn->y();

    for (int i=0; i<this->btnList.size(); i++) {
        Button *btn = this->btnList.at(i);
        if (btn == movingBtn) {
            continue;
        }

        if (x>btn->x()-this->lineShowThresholdValue && x<btn->x()+this->lineShowThresholdValue) {
            this->isBtnLeftLineShown = true;
            this->btnLeftLineX = btn->x();

            if (x>btn->x()-this->lineAdsorbThresholdValue && x<btn->x()+this->lineAdsorbThresholdValue) {
                movingBtn->move(btn->x(), y);
            }
            return;
        }
        else {
            this->isBtnLeftLineShown = false;
            this->btnLeftLineX = 0;
        }
    }
}

void Window::checkWindowCenterLines(Button *movingBtn) {
    int x = movingBtn->x();
    int y = movingBtn->y();

    int verticalCenterValue = int(this->width()/2) - int(movingBtn->width()/2);
    int horizontalCenterValue = int(this->width()/2) - int(movingBtn->height()/2);

    // 判断是否显示中心竖线
    if (x>verticalCenterValue-this->lineShowThresholdValue && x<verticalCenterValue+this->lineShowThresholdValue) {
        this->isVerticalCenterLineShown = true;

        // 判断是否吸附
        if (x>verticalCenterValue-this->lineAdsorbThresholdValue && x<verticalCenterValue+this->lineAdsorbThresholdValue) {
            movingBtn->move(verticalCenterValue, y);
        }
    }
    else {
        this->isVerticalCenterLineShown = false;
    }

    // 判断是否显示中心横线
    if (y>horizontalCenterValue-this->lineShowThresholdValue && y<horizontalCenterValue+this->lineShowThresholdValue) {
        this->isHorizontalCenterLineShown = true;

        // 判断是否吸附
        if (y>horizontalCenterValue-this->lineAdsorbThresholdValue && y<horizontalCenterValue+this->lineAdsorbThresholdValue) {
            movingBtn->move(x, horizontalCenterValue);
        }
    }
    else {
        this->isHorizontalCenterLineShown = false;
    }
}

void Window::changeBtnNum(int newNum) {
    int currentNum = this->btnList.size();

    if (currentNum < newNum) {
        int diff = newNum - currentNum;
        for (int i=0; i<diff; i++) {
            QString text = QString("button%1").arg(currentNum);
            Button *btn = new Button(text, this);
            int x = rand() % (this->width()-btn->width()+1);
            int y = rand() % (this->height()-btn->width()+1);
            btn->move(x, y);
            btn->show();
            this->btnList.append(btn);
        }
    }
    else if (currentNum > newNum) {
        int diff = currentNum - newNum;
        for (int i=0; i<diff; i++) {
            Button *btn = this->btnList.takeLast();
            btn->deleteLater();
        }
    }
}

main.cpp

#include "window.h"

#include <QApplication>

int main(int arGC, char *argv[])
{
    QApplication a(argc, argv);
    Window w;
    w.show();
    return a.exec();
}

以上就是Qt实现对齐线功能的示例代码的详细内容,更多关于Qt对齐线的资料请关注其它相关文章!

相关文章