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

目录
  • 现有功能
  • 运行结果
  • 源码
    • button.h
    • button.cpp
    • window.h
    • window.cpp
    • main.cpp

现有功能

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对齐线的资料请关注我们其它相关文章!

(0)

相关推荐

  • Qt实现矩形大小任意缩放的示例代码

    目录 现有功能 运行结果 源码 point_button.h point_button.cpp window.h window.cp main.cpp 现有功能 1.在窗口上绘制任意大小的矩形. 2.通过边角的拖曳按钮改变矩形大小. 运行结果 源码 point_button.h #ifndef POINTBUTTON_H #define POINTBUTTON_H #include <QPushButton> #include <QWidget> #include <QMou

  • Qt实现实时鼠标绘制图形

    目录 功能实现 1:记录图形第一个绘制点 2:实时获取鼠标最新位置并绘图 3:释放绘制点,绘制最终图形 总结 上一章节介绍了关于QGraphicsView的基础讲解,以及简单的类图创建,由上一章节中最后展示的动画效果来看,今年主要讲述如何在QGraphicsView架构下,实时拖动鼠标绘制图形! 今天主要以矩形为例,再来看一下展示效果吧! 功能实现 想要实现鼠标拖拽绘图的效果,离不开鼠标的三大事件:按下.移动.释放 那么具体实现实时绘制矩形框的核心流程是什么呢? 第一步:鼠标左键点击,记录初始点

  • QT中QChart绘制折线图

    目录 一.简单绘图 二.绘制折线图 实例 一.简单绘图 Qt Charts基于Qt的Graphics View架构,其核心组件是QChartView 和 QChart QChartView是显示图标的视图,基类为QGraphicsView QChart的基类是QGraphicsltem 类的继承关系: 创建项目:.pro文件中添加:QT += charts代码如下:其他文件未修改,修改代码只在mainwindow.cpp文件中进行.mainwindow.cpp #include "mainwin

  • Qt实现绘制网格背景的示例代码

    目录 现有功能 运行结果 源码 window.h window.cpp main.cpp 现有功能 使用滚轮缩放. 缩放到达一定阈值后恢复网格大小. 窗口大小调整时网格背景也自动调整重绘. 运行结果 源码 window.h #ifndef WINDOW_H #define WINDOW_H #include <QWidget> #include <QPen> #include <QPainter> #include <QPaintEvent> class W

  • Qt实现简易毛玻璃效果的示例代码

    目录 现有功能 运行结果 源码 frosted_glass_label.h frosted_glass_label.cpp main.cpp 现有功能 1.用模糊功能实现简易的毛玻璃效果. 2.鼠标移动无边框窗口. 运行结果 源码 frosted_glass_label.h #ifndef FROSTEDGLASSLABEL_H #define FROSTEDGLASSLABEL_H #include <QWidget> #include <QLabel> #include <

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

    目录 现有功能 运行结果 源码 button.h button.cpp window.h window.cpp main.cpp 现有功能 1.添加任意数量的按钮. 2.移动按钮,通过对齐线来设置按钮位置. 3.自动吸附. 运行结果 源码 button.h #ifndef BUTTON_H #define BUTTON_H #include <QPushButton> #include <QWidget> #include <QMouseEvent> class But

  • Qt实现保存、浏览、预览、打印功能的示例代码

    Qt提供了以文本.图片.HTML等方式来实现对文档的操作,主要用到了QPrinter类和QPainter类,用到了QFileDialog文件窗口.QPrintPreviewDialog预览窗口类和QPrintDialog打印窗口类,Qt5也提供了QPdfWriter类来实现对pdf的操作,这里并不包括打开pdf文件,Qt没有提供任何方法来直接像文件浏览器一样打开pdf文件,可以用第三方库来实现. 这里采用了图片的方式来实现保存.预览和打印,其实 三个功能基本上一样. 1.保存PDF (1)保存某

  • Qt实现简易计时器的示例代码

    目录 一.项目介绍 二.项目基本配置 三.UI界面设计 四.主程序实现 4.1 mainwindow.h头文件 4.2 mainwindow.cpp源文件 五.效果演示 一.项目介绍 计时器实现四个功能:开始计时.停止计时.暂停计时以及打点.当点击暂停时,开始按钮和停止按钮无法点击,此时暂停按钮变为继续.当点击停止时,开始按钮和暂停按钮无法点击,此时停止按钮变为清零. 二.项目基本配置 新建一个Mainwindow界面.基本配置与其他Qt项目类似,这里不过多介绍. 三.UI界面设计 UI界面如下

  • Qt实现电子时钟的示例代码

    目录 一.项目介绍 二.项目基本配置 三.UI界面设计 四.主程序实现 4.1 添加新文件 4.2 digiclock.h头文件 4.3 digiclock.cpp源文件 4.4 main.cpp源文件 五.效果演示 一.项目介绍 利用Qt实现显示与桌面上并可以随意拖拽至桌面任意位置的电子时钟案例. 二.项目基本配置 新建一个Qt案例,项目名称为“Clock”,基类选择“QDialog”,取消创建UI界面复选框的选中状态. 三.UI界面设计 无UI界面 四.主程序实现 4.1 添加新文件 添加新

  • VUE饿了么树形控件添加增删改功能的示例代码

    本文介绍了VUE饿了么树形控件添加增删改功能的示例代码,分享给大家,具体如下: element-ui树形控件:地址 在原文档中有个案例是有新增和删除功能,但是后来发现其修改的数据并不能直接影响到树形数据,所以采用了 render-content 的API重新写了个组件. 写个开发的步骤,所以文章比较长emmm 大致效果如图: 1.省市API 在网上复制了个省市的list,有两个属性是新增的 isEdit :控制编辑状态 maxexpandId :为现下id的最大值 export default{

  • Android仿微信发送语音消息的功能及示例代码

    微信的发送语音是有一个向上取消的,我们使用onTouchListener来监听手势,然后做出相应的操作就行了. 直接上代码: //语音操作对象 private MediaPlayer mPlayer = null; private MediaRecorder mRecorder = null; //语音文件保存路径 private String FileName = null; FileName = Environment.getExternalStorageDirectory().getAbs

  • php 实现收藏功能的示例代码

    整理文档,搜刮出一个php 实现收藏功能的示例代码,稍微整理精简一下做下分享. HTML: <a class = "x" id="{$photo.id}" uid="{$Think.session.uid}" status = "{$collect_pic}" href = "javascript:void(0);"> <if condition = "$collect_num

  • React 实现拖拽功能的示例代码

    本文介绍了React 实现拖拽功能的示例代码,分享给大家,具体如下: 实现效果: 因为工作中会用到 JIRA 所以想实现一下相似的功能,顺便学习一下 H5 的拖拽.不支持拖拽改变顺序,感觉有点麻烦,而且没必要.感觉相关的博文好少的,大部分都是直接上代码,没有解释. 图片默认可以拖动,其他元素的拖动效果同图片.正常的 div 是不能被拖动的,鼠标点击选择后移动没有效果,需要加  draggable="true" 使得元素可以被拖动. 拖拽相关的几个事件,有被拖动元素的事件,也有拖动进入的

  • MyBatis XML方式的基本用法之多表查询功能的示例代码

    1. 多表查询 在之前,我们示例的2个查询都是单表查询,但实际的业务场景肯定是需要多表查询的,比如现在有个需求: 查询某个用户拥有的所有角色.这个需求要涉及到sys_user,sys_user_role,sys_role三张表,如何实现呢? 首先,在SysUserMapper接口中定义如下方法. /** * 根据用户id获取角色信息 * * @param userId * @return */ List<SysRole> selectRolesByUserId(Long userId); 然后

  • swift4 使用DrawerController实现侧滑菜单功能的示例代码

    本文介绍了swift4 使用DrawerController实现侧滑功能的示例代码,分享给大家,具体如下: 直接上图 安装 类库开源地址:https://github.com/sascha/DrawerController 可惜的是,它已经不维护了,很好用的一个侧滑实现 pod 'DrawerController' 新建侧滑视图 import UIKit // 这个类就是一个 UIViewController 可以在里面写任何你想写的东西 class LeftViewController: UI

随机推荐