Qt實(shí)現(xiàn)對(duì)齊線(xiàn)功能的示例代碼
現(xiàn)有功能
1.添加任意數(shù)量的按鈕。
2.移動(dòng)按鈕,通過(guò)對(duì)齊線(xiàn)來(lái)設(shè)置按鈕位置。
3.自動(dòng)吸附。
運(yùn)行結(jié)果
源碼
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); // 改變按鈕數(shù)量 private: void drawVerticalCenterLine(QPainter &painter); // 繪制垂直中心線(xiàn) void drawHorizontalCenterLine(QPainter &painter); // 繪制水平中心線(xiàn) void drawBtnLeftLine(QPainter &painter); // 繪制按鈕左側(cè)線(xiàn) void drawBtnTopLine(QPainter &painter); // 繪制按鈕頂部線(xiàn) void checkBtnTopLine(Button *movingBtn); // 比對(duì)當(dāng)前移動(dòng)按鈕和其他按鈕頂部的位置 void checkBtnLeftLine(Button *movingBtn); // 比對(duì)當(dāng)前移動(dòng)按鈕和其他按鈕左側(cè)的位置 void checkWindowCenterLines(Button *movingBtn); // 比對(duì)按鈕和中心線(xiàn)的位置 private: QSpinBox *spinBox; QList<Button *> btnList; int lineShowThresholdValue; // 線(xiàn)條顯示閾值 int lineAdsorbThresholdValue; // 線(xiàn)條吸附閾值 bool isVerticalCenterLineShown; // 是否顯示中心豎線(xiàn) bool isHorizontalCenterLineShown; // 是否顯示中心橫線(xiàn) bool isBtnLeftLineShown; // 是否顯示按鈕左側(cè)線(xiàn)條 bool isBtnTopLineShown; // 是否顯示按鈕頂部線(xiàn)條 int btnLeftLineX; // 按鈕左側(cè)線(xiàn)x坐標(biāo) int btnTopLineY; // 按鈕頂部線(xiàn)y坐標(biāo) QPen pen1; // 用來(lái)繪制中心對(duì)齊線(xiàn) QPen pen2; // 用來(lái)繪制按鈕間的對(duì)齊線(xiàn) }; #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); // 判斷是否顯示中心豎線(xiàn) 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; } // 判斷是否顯示中心橫線(xiàn) 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實(shí)現(xiàn)對(duì)齊線(xiàn)功能的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Qt對(duì)齊線(xiàn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(97.交織相錯(cuò)的字符串)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(97.交織相錯(cuò)的字符串),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言實(shí)現(xiàn)手寫(xiě)Map(數(shù)組+鏈表+紅黑樹(shù))的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言實(shí)現(xiàn)手寫(xiě)Map(數(shù)組+鏈表+紅黑樹(shù)),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定借鑒價(jià)值,需要的可以參考一下2022-09-09OpenCV實(shí)現(xiàn)直線(xiàn)檢測(cè)并消除
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)直線(xiàn)檢測(cè)并消除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06詳解C語(yǔ)言中g(shù)etgid()函數(shù)和getegid()函數(shù)的區(qū)別
這篇文章主要介紹了詳解C語(yǔ)言中g(shù)etgid()函數(shù)和getegid()函數(shù)的區(qū)別,注意getegid只返回有效的組識(shí)別碼,需要的朋友可以參考下2015-08-08