• 基于Qt实现的轻量级CAD画图软件


    1.界面展示 

    2.功能展示

    新建画布:(背景的虚线格子花是录屏转gif的原因,原视频中没有花)

    更新:之前一个画图按钮画下只能画每次只能画一个图形,后面实现了按钮按下一直画:

     

    3.关于Graphics View绘图架构

         由于QPainter画图形,不能实现对图形的选择、编辑、移动等操作,所以我的整个项目是基于Craphics View绘图架构来实现的

    3.1 Craphics View

    (1)Craphics View绘图架构介绍        

    Craphics View架构主要分为三个部分:视图、场景、图形项(图元)

    • QGraphicsScene(场景):可以管理多个图形项
    • QGraphicsItem(图形项):也就是图元,支持鼠标事件响应。
    • QGraphicsView(视图):关联场景可以让场景中的所有图形项可视化

    场景、视图、图元三者的关系图:

    (2)QGrphicsView中一些常用操作接口

    //添加场景

    //设置关联显示的场景

    void QGraphicsView::setScene(QGraphicsScene *scene)

    // 设置场景在视图中可视部分的矩形区域

    void QGraphicsView::setSceneRect(const QRectF &rect)

    //场景外观设置操作

    //设置场景在视图中的对齐方式,缺省是上下都居中

     void QGraphicsView::setAlignment(Qt::Alignment alignment)

    //设置场景场景的背景画刷

    void QGraphicsView::setBackgroundBrush(const QBrush &brush)

    //设置场景的前景画刷

    void QGraphicsView::setForegroundBrush(const QBrush &brush)

    //设置视图的绘图选项

     void QGraphicsView::setRenderHints(QPainter::RenderHints hints)

     //交互

    //是否允许场景可交互,如果禁止交互,则任何键盘或鼠标操作都被忽略

    void QGraphicsView::setInteractive(bool allowed)

    //返回选择矩形框

     QRect QGraphicsView::rubberBandRect() const

    //选择模式 ,参数为枚举类型Qt : : ltemSelectionMode

     Qt::ItemSelectionMode rubberBandSelectionMode() const

    //获取视图坐标系中某个位置处的图形项

    1. QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
    2. QGraphicsItem *QGraphicsView::itemAt(int x, int y) const

    //获取场景中的所有、或者某个选择区域内图形项目的列表

    1. QList QGraphicsView::items() const
    2. QList QGraphicsView::items(const QPoint &pos) const
    3. QList QGraphicsView::items(int x, int y) const
    4. ....

    //坐标

    //将场景中的一个坐标转换为视图的坐标

    QPolygon QGraphicsView::mapFromScene(const QRectF &rect) const

    //将视图中的一个坐标转换为场景的坐标

     QPointF QGraphicsView::mapToScene(const QPoint &point) const

    (3)QGraphicsScene中一些常用操作接口

    //场景

    //设置场景的矩形区

    ​​​​​​​void QGraphicsScene::setSceneRect(const QRectF &rect)

    //分组

    //创建图形项组

    QGraphicsItemGroup *QGraphicsScene::createItemGroup(const QList &items)

    //解除一个图形项组

    void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group)

     //输入焦点

    //返回当前获得焦点的图形项

    QGraphicsItem *QGraphicsScene::focusItem() const

    //去除选择焦点

    void QGraphicsScene::clearFocus()

    //视图是否有焦点

     bool QGraphicsScene::hasFocus() const

    //图形项的操作

    //添加一个已经创建的图形项

    void QGraphicsScene::addItem(QGraphicsItem *item) 

    //删除图形项

     void QGraphicsScene::removeItem(QGraphicsItem *item)

    //清除所有图形项

    [slot] void QGraphicsScene::clear()

    //返回鼠标抓取的图形项

    QGraphicsItem *QGraphicsScene::mouseGrabberItem() const

    //返回选择的图形项列表

    QList QGraphicsScene::selectedItems() const

    //清除所有选择

    [slot] void QGraphicsScene::clearSelection()

    //获取某个位置处的顶层图形项

    1. QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
    2. QGraphicsItem *QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const

    //返回某个矩形区域、多边形等选择区域内的图形项列表

    QList QGraphicsScene::items(Qt::SortOrder order = Qt::DescendingOrder) const

    //添加图形项

    1. //添加一个椭圆
    2. QGraphicsEllipseItem *QGraphicsScene::addEllipse(const QRectF &rect, const QPen &pen = QPen(), const QBrush &brush = QBrush());
    3. //添加一条直线
    4. QGraphicsLineItem *QGraphicsScene::addLine(qreal x1, qreal y1, qreal x2, qreal y2, const QPen &pen = QPen());
    5. //添加一个绘图路径
    6. QGraphicsPathItem *QGraphicsScene::addPath(const QPainterPath &path, const QPen &pen = QPen(), const QBrush &brush = QBrush());
    7. //添加一个图片
    8. QGraphicsPixmapItem *QGraphicsScene::addPixmap(const QPixmap &pixmap);
    9. //添加一个多边形
    10. QGraphicsPolygonItem *QGraphicsScene::addPolygon(const QPolygonF &polygon, const QPen &pen = QPen(), const QBrush &brush = QBrush());
    11. //添加一个矩形
    12. QGraphicsRectItem *QGraphicsScene::addRect(const QRectF &rect, const QPen &pen = QPen(), const QBrush &brush = QBrush());
    13. //添加简单文字
    14. QGraphicsSimpleTextItem *QGraphicsScene::addSimpleText(const QString &text, const QFont &font = QFont());
    15. //添加字符串
    16. QGraphicsTextItem *QGraphicsScene::addText(const QString &text, const QFont &font = QFont());
    17. //添加界面组件
    18. QGraphicsProxyWidget *QGraphicsScene::addWidget(QWidget *widget, Qt::WindowFlags wFlags = Qt::WindowFlags());

     (4)QGraphicsItem中一些常用操作接口

    //属性设置

    //设置图形项的操作属性,例如,可选择,可移动等

    void QGraphicsItem::setFlags(QGraphicsItem::GraphicsItemFlags flags)

    //设置透明度

    void QGraphicsItem::setOpacity(qreal opacity)

    //设置图形效果

    void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)

    //图形项是否被选中

    void QGraphicsItem::setSelected(bool selected)

    //用户自定义数据

    void QGraphicsItem::setData(int key, const QVariant &value)

    //坐标

    //图形项的X坐标

    void QGraphicsItem::setX(qreal x)

    //图形项的Y坐标

    void QGraphicsItem::setY(qreal y)

    //图形项的Z值,Z值控制图形项的叠放次序

    void QGraphicsItem::setZValue(qreal z)

    //图形项在父项中的位置

    void QGraphicsItem::setPos(const QPointF &pos)

    //返回图形项在场景中的坐标,相当于调用mapToScene(0,0)

    QPointF QGraphicsItem::scenePos() const

    //坐标变换 

    //复位坐标系,取消所有坐标变换

    void QGraphicsItem::resetTransform()

    //旋转一定角度,参数为正数时表示顺时针旋转

    void QGraphicsItem::setRotation(qreal angle)

    //按比例缩放,缺省值为1

    void QGraphicsItem::setScale(qreal factor)

    //坐标映射 

    //将另一个图形项的一个点映射到本图形项到坐标系

    QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &point) const

    //将父项的一个点映射到本图形项的坐标系

    QPointF QGraphicsItem::mapFromParent(const QPointF &point) const

    //将场景中的一个点映射到本图项到坐标系

    QPointF QGraphicsItem::mapFromScene(const QPointF &point) const

    //将本图形项内到一个点映射到另一个图形项的坐标系

    1. QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterPath &path) const
    2. QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal x, qreal y) const
    3. QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point) const
    4. QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect) const
    5. QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &polygon) const
    6. ...

    //将本图形项内的一个点映射到父项坐标系

    1. QPointF QGraphicsItem::mapToParent(const QPointF &point) const
    2. QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
    3. QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
    4. QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
    5. QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
    6. QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
    7. QPointF QGraphicsItem::mapToParent(qreal x, qreal y) const

    //将本图形项内到一个点映射到场景坐标系

    1. QPointF QGraphicsItem::mapToScene(const QPointF &point) const
    2. QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const
    3. QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const
    4. QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const
    5. QPointF QGraphicsItem::mapToScene(qreal x, qreal y) const
    6. QPolygonF QGraphicsItem::mapToScene(qreal x, qreal y, qreal w, qreal h) const

    4.项目整体结构

    4.1 项目中使用的类

    项目总结:

    项目上遇到的一些问题:

            1.开始在tabWidget上添加画布时,不能做画,选择要画的图形后,一点击画笔程序就崩溃退出,然后我添加了一些判定条件,如果tabWidget->currentIndex() < 0时,指针赋值失败,后来加了判断条件后,就可以了,再后来我直接改进,打开应用程序窗口时,就在会在tabWidget上创建画布。

            2.在mainwindow.cpp中我重写了mouseDoubleClickEvent方法,双击图形时,更新右边的属性列表,但是在双击空白的视图view时程序就会闪退,后来使用的解决方法就是加了判定条件,如果已经选择了图形,双击图形就更新属性列表,如果没有选择图形,只单纯的双击画布,就忽视事件。具体代码实现如下:

    1. //双击图形更新图形的属性列表
    2. void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
    3. { QGraphicsScene * scene = m_scene;
    4. if (scene && !scene->selectedItems().isEmpty()) {
    5. if (scene->selectedItems().first()->isSelected()) {
    6. updateItemProperty(); //更新属性列表
    7. }
    8. }else{
    9. event->ignore();
    10. }
    11. }

            3.在按下如下按钮时,如果图形没有被选中,程序会崩溃闪退,后来我加了一些判定条件,比如在选中的图形大于1时才能进行组合、对齐和拉伸等操作 ,该问题也完美解决

    1. void MainWindow::aglin() {
    2. graphicsScene * scene = dynamic_cast(m_scene);
    3. int selectedItemCount = scene->selectedItems().count();
    4. if(ui->tabWidget->currentIndex() >= 0 && scene && selectedItemCount > 1){
    5. if (sender() == ui->top_align_button){
    6. scene->align(TOP_ALIGN);
    7. }else if(sender() == ui->bottom_align_button){
    8. scene->align(BOTTOM_ALIGN);
    9. }else if(sender() == ui->left_align_button){
    10. scene->align(LEFT_ALIGN);
    11. }else if(sender() == ui->right_align_button){
    12. scene->align(RIGHT_ALIGN);
    13. }else if(sender() == ui->horizontal_align){
    14. scene->align(HORZEVEN_ALIGN);
    15. }else if(sender() == ui->vertical_align){
    16. scene->align(VERTEVEN_ALIGN);
    17. }else if(sender() == ui->vertical_space_Button){
    18. scene->align(HORZEVEN_SPACE);
    19. }else if(sender() == ui->horizontal_space_Button){
    20. scene->align(VERTEVEN_SPACE);
    21. }else if(sender() == ui->widthButton){
    22. scene->align(WIDTH_ALIGN);
    23. }else if(sender() == ui->heightButton){
    24. scene->align(HEIGHT_ALIGN);
    25. }
    26. }
    27. }

            以上就是我在开发时遇到的一些问题,当然还有一些小问题,就不一一阐述了。

  • 相关阅读:
    git工作常用命令
    腾讯强推的599页Netty进阶神技,完美诠释Netty
    扩容LVM卷导致lvm元数据丢失的恢复过程
    Apollo与TypeScript:强大类型检查在前端开发中的应用
    26、类型别名
    Java每日笔试题错题分析(7)
    安装【银河麒麟V10】linux系统
    【一周安全资讯1021】工业和信息化部等六部门印发《算力基础设施高质量发展行动计划》;思科未修补的零日漏洞正被积极利用
    Canal
    【论文解读】斯坦福小镇Generative Agents
  • 原文地址:https://blog.csdn.net/weixin_44954230/article/details/133922568