现有功能
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对齐线的资料请关注编程网其它相关文章!