如何根据第一个选定的项目对齐图形场景中的图形项目?

Posted

技术标签:

【中文标题】如何根据第一个选定的项目对齐图形场景中的图形项目?【英文标题】:How to align Graphics items in Graphic scene based on first selected item? 【发布时间】:2018-07-30 11:57:40 【问题描述】:

我有图形场景,我必须根据第一个选定的项目(参考项目)向右、向左、顶部或底部下车。我搜索了一些代码,但在这个代码中它与场景正确的位置对齐。我必须根据第一个选定的项目对齐项目。我怎样才能做到这一点?

    void GraphicScene::ItemsRightAlign()
    
      if (selectedItems().isEmpty())
          return;
      QRectF refRect = selectedItems().first()->boundingRect();
      QList<QGraphicsItem*> sel =selectedItems();  //   for example
      foreach(QGraphicsItem* selItem, sel)
      
         qreal dx = 0, dy = 0;
         QRectF itemRect = selItem->mapToScene(selItem->boundingRect()).boundingRect();

         //if(align_right)
         dx = refRect.right() - itemRect.right();
         qDebug() << "item pos "<< dx << dy << selItem->mapToScene(selItem->boundingRect()).boundingRect() ;
         selItem->moveBy(dx, dy);
      

    

更多详情

输出应该是这样的输出

【问题讨论】:

据我了解,如果您选择例如 5 个项目,您希望最后 4 个项目位于例如第一个选定项目的下方,我是否正确? @eyllanesc 是的...根据第一次选择正确...请检查图片 图片说明了很多,:) 我有一个疑问,你在图像中显示一条垂直线,将移动到左边,右边还是中间的项目?它可以显示您想要获得的图片。 @eyllanesc 就行了 【参考方案1】:

替换 topLeft.x -- 右对齐用 topRight.x ,上对齐用 dy 替换 topLeft.y 和 dx ,下对齐用 dy 替换 bottomLeft.y 和 dx

    void GraphicScene::ItemsLeftAlign
    
       if (selectedItems().isEmpty())
           return;
       QGraphicsItem *FirstSelItem = selectedItems().first();
       QList<QGraphicsItem*> sel =selectedItems();  //   for example
       foreach(QGraphicsItem* selItem, sel)
       
           qreal dx = 0, dy = 0;
           dx = (FirstSelItem->mapToScene(FirstSelItem->boundingRect().topLeft()).x()) -
                (selItem->mapToScene(selItem->boundingRect().topLeft()).x());
           selItem->moveBy(dx, dy);
       
    

【讨论】:

【参考方案2】:

分辨率的方法是将确定右、左、上、下的点映射到第一个项目的场景中,其他项目获得必须补偿的差异。

graphicsscene.h

#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H

#include <QGraphicsScene>
#include <QGraphicsItem>

class GraphicsScene: public QGraphicsScene
    Q_OBJECT
public:
    GraphicsScene(QObject *parent=nullptr);
    void moveSelecteds(Qt::Alignment aligment);
private slots:
    void onSelectionChanged();
private:
    void move(QGraphicsItem *ref, QList<QGraphicsItem *> others, Qt::Alignment aligment);
    QGraphicsItem *mRef;
;
#endif // GRAPHICSSCENE_H

graphicsscene.cpp

#include "graphicsscene.h"

GraphicsScene::GraphicsScene(QObject *parent):
    QGraphicsScene(parent),
    mRef(nullptr)

    connect(this, &GraphicsScene::selectionChanged, this, &GraphicsScene::onSelectionChanged);


void GraphicsScene::moveSelecteds(Qt::Alignment aligment)
    QList<QGraphicsItem *> its= selectedItems();
    if(its.size() < 2)
        return;
    if(!its.removeOne(mRef))
        return;
    move(mRef, its, aligment);


void GraphicsScene::onSelectionChanged()
    if(selectedItems().isEmpty())
        mRef = nullptr;
    
    else if(selectedItems().size() == 1)
        mRef = selectedItems().first();
    


void GraphicsScene::move(QGraphicsItem *ref, QList<QGraphicsItem *> others, Qt::Alignment aligment)
    QPointF p;
    switch (aligment) 
    case Qt::AlignLeft:
        p = QPointF(ref->mapToScene(ref->boundingRect().topLeft()).x(), 0);
        break;
    case Qt::AlignRight:
        p = QPointF(ref->mapToScene(ref->boundingRect().topRight()).x(), 0);
        break;
    case Qt::AlignTop:
        p = QPointF(0, ref->mapToScene(ref->boundingRect().topLeft()).y());
        break;
    case Qt::AlignBottom:
        p = QPointF(0, ref->mapToScene(ref->boundingRect().bottomLeft()).y());
        break;
    

    for(QGraphicsItem *o: others)
        QPointF delta;
        switch (aligment) 
        case Qt::AlignLeft:
            delta = p - QPointF(o->mapToScene(o->boundingRect().topLeft()).x(), 0);
            break;
        
        case Qt::AlignRight:
            delta = p - QPointF(o->mapToScene(o->boundingRect().topRight()).x(), 0);
            break;
        
        case Qt::AlignTop:
            delta = p - QPointF(0, o->mapToScene(o->boundingRect().topLeft()).y());
            break;
        
        case Qt::AlignBottom:
            delta = p - QPointF(0, o->mapToScene(o->boundingRect().bottomLeft()).y());
            break;
        
        
        o->moveBy(delta.x(), delta.y());
    

在本例中,您可以使用上、下、左、右键来移动项目。

ma​​in.cpp

#include "graphicsscene.h"

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QShortcut>
#include <random>

static void create_items(QGraphicsScene  & scene)

    std::default_random_engine generator;
    std::uniform_int_distribution<int> dist_size(30, 40);
    std::uniform_int_distribution<int> dist_pos(-50, 50);

    for(const QString & colorname : "red", "green", "blue", "gray", "orange")
        QRectF r(QPointF(dist_pos(generator), dist_pos(generator)),
                 QSizeF(dist_size(generator), dist_size(generator)));
        auto item = new QGraphicsRectItem(r);
        item->setPos(QPointF(dist_pos(generator), dist_pos(generator)));
        item->setBrush(QColor(colorname));
        item->setFlag(QGraphicsItem::ItemIsSelectable);
        scene.addItem(item);
    


int main(int argc, char *argv[])

    QApplication a(argc, argv);
    GraphicsScene scene;
    create_items(scene);
    QGraphicsView view(&scene);

    const QList<QPair<Qt::Key, Qt::Alignment>> k_a 
        Qt::Key_Up, Qt::AlignTop,
        Qt::Key_Down, Qt::AlignBottom,
        Qt::Key_Left, Qt::AlignLeft,
        Qt::Key_Right, Qt::AlignRight
    ;

    for(const QPair<Qt::Key, Qt::Alignment> & p : k_a)
        QShortcut *shorcut = new QShortcut(p.first, &view);
        QObject::connect(shorcut, &QShortcut::activated, std::bind(&GraphicsScene::moveSelecteds, &scene, p.second));
    

    view.resize(640, 480);
    view.show();

    return a.exec();

完整的例子可以在下面的link找到。

【讨论】:

以上是关于如何根据第一个选定的项目对齐图形场景中的图形项目?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 DataGridView 中的选定行将组合框中的特定项目设置为选定项?

当图形项目靠在其边框上时,使 QGraphicsScene 更大

如何根据另一个的选定项目过滤一个组合框集合?

如何使用场景文件中的几何图形与多个对象(几何图形)?

unity虚拟仿真怎么样

旋转几何图形以对齐方向向量