Qt實(shí)現(xiàn)對(duì)齊線功能的示例代碼
現(xiàn)有功能
1.添加任意數(shù)量的按鈕。
2.移動(dòng)按鈕,通過對(duì)齊線來設(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_Hbutton.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); // 繪制垂直中心線
void drawHorizontalCenterLine(QPainter &painter); // 繪制水平中心線
void drawBtnLeftLine(QPainter &painter); // 繪制按鈕左側(cè)線
void drawBtnTopLine(QPainter &painter); // 繪制按鈕頂部線
void checkBtnTopLine(Button *movingBtn); // 比對(duì)當(dāng)前移動(dòng)按鈕和其他按鈕頂部的位置
void checkBtnLeftLine(Button *movingBtn); // 比對(duì)當(dāng)前移動(dòng)按鈕和其他按鈕左側(cè)的位置
void checkWindowCenterLines(Button *movingBtn); // 比對(duì)按鈕和中心線的位置
private:
QSpinBox *spinBox;
QList<Button *> btnList;
int lineShowThresholdValue; // 線條顯示閾值
int lineAdsorbThresholdValue; // 線條吸附閾值
bool isVerticalCenterLineShown; // 是否顯示中心豎線
bool isHorizontalCenterLineShown; // 是否顯示中心橫線
bool isBtnLeftLineShown; // 是否顯示按鈕左側(cè)線條
bool isBtnTopLineShown; // 是否顯示按鈕頂部線條
int btnLeftLineX; // 按鈕左側(cè)線x坐標(biāo)
int btnTopLineY; // 按鈕頂部線y坐標(biāo)
QPen pen1; // 用來繪制中心對(duì)齊線
QPen pen2; // 用來繪制按鈕間的對(duì)齊線
};
#endif // WINDOW_Hwindow.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實(shí)現(xiàn)對(duì)齊線功能的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Qt對(duì)齊線的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
dev-c++創(chuàng)建lib(靜態(tài)鏈接庫(kù))文件的實(shí)現(xiàn)步驟
本文主要介紹了dev-c++創(chuàng)建lib(靜態(tài)鏈接庫(kù))文件的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
詳解如何用alpine鏡像做一個(gè)最小的鏡像并運(yùn)行c++程序
這篇文章主要介紹了詳解如何用alpine鏡像做一個(gè)最小的鏡像并運(yùn)行c++程序,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
C語(yǔ)言中自動(dòng)隱式轉(zhuǎn)換與類型強(qiáng)制轉(zhuǎn)換實(shí)例分析
這篇文章主要介紹了C語(yǔ)言中自動(dòng)隱式轉(zhuǎn)換與類型強(qiáng)制轉(zhuǎn)換實(shí)例分析,需要的朋友可以參考下2014-07-07
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易三子棋游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
使用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實(shí)現(xiàn)步驟
這篇文章主要介紹了用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實(shí)現(xiàn)步驟,本文分步驟通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02

