Qt实现对齐线功能的示例代码
作者:la_vie_est_belle
这篇文章主要介绍了Qt如何实现对齐线功能,并且可以添加任意数量和自动吸附,文中示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
现有功能
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对齐线的资料请关注脚本之家其它相关文章!