【问题标题】:Resizing/Scaling a png image of rectangular shape on mouse move event in Qt在Qt中的鼠标移动事件上调整/缩放矩形形状的png图像
【发布时间】:2014-05-01 08:16:24
【问题描述】:

我有一个 QGraphicPixmapItem,其中包含一个 png 图像,出现在场景中。

图像本身是一个矩形图像。我的要求是,当我在鼠标移动事件上调整矩形图像的大小时,我应该能够调整图像的大小/缩放。 我可以通过拖动矩形图像的任意一侧来调整矩形的大小。

问题是,我可以通过拖动矩形图像的任何边来调整其大小,但原始图像严重扭曲,无法辨认。图片基本 在连续调整大小(扩大/缩小宽度或高度)时变成一块固体。 如何在 Qt 中实现图像的缩放/缩放而不会对原始图像造成太大的破坏?我所经历的不是像素化,而是更糟。

下面的代码是 QGraphicsPixmapItem 的 mouseMoveEvent() 的快照,实现了通过拖动矩形图像的右侧/左侧来调整矩形的大小。

 void PersonSizeGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        const QPointF event_pos = event->pos();
        const QPointF event_scene_pos = event->scenePos();

        QPixmap current_pixmap = this->pixmap();
        QImage current_image = current_pixmap.toImage();
        QRect current_image_rect = current_image.rect();

        QPoint current_top_left = current_image_rect.topLeft();
        QPoint current_bottom_right = current_image_rect.bottomRight();

        if((event->scenePos().x() > this->scene()->width()) || (event->scenePos().y() > this->scene()->height())
            || (event->scenePos().x() < 0) || (event->scenePos().y() < 0) )
        {
            return;
        }

        if( this->cursor().shape() == Qt::SizeHorCursor )
        {
            if(rect_right_condition)
            {
                        new_rect = QRect( current_top_left, QPoint( event->pos().x(), current_bottom_right.y()) );


                scaled_pixmap = QPixmap::fromImage(current_image.scaled(QSize(new_rect.width(),new_rect.height()),Qt::IgnoreAspectRatio,Qt::FastTransformation));

                setPixmap(scaled_pixmap);

     }

            if(rect_left_condition)
            {
                            new_rect = QRect( QPoint(event_pos.x(), 0), current_bottom_right );

    scaled_pixmap = QPixmap::fromImage(current_image.scaled(QSize(new_rect.width(),new_rect.height()),Qt::IgnoreAspectRatio,Qt::FastTransformation));
                setPixmap(scaled_pixmap);
                QPoint new_top_left = new_rect.topLeft();
                QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
                this->setPos(mapped_topLeft);
                rect_resize_occurred = true;


            }

        }
    }

【问题讨论】:

  • 黄金法则:在用户事件上更新state,请求绘制事件,并在绘制方法中完成繁重的工作。在您的情况下,这意味着将第一个 if 之后的所有代码推送到油漆区。
  • @UmNyobe - 感谢您的建议。记下来了。

标签: qt png qgraphicsitem


【解决方案1】:

在不断调整大小(扩大/缩小宽度或高度)时,图像基本上会变成一块固体。

这是正常的。你需要做的是改变你想要的效果的方法。与其不断更改相同的图像,不如从您期望用户需要的最大尺寸的源图像开始。此图像不会被更改。

在 mouseMove 函数中,更新成员变量以存储您显示的图像的大小。

然后,在 PersonSizeGraphicsItem 的绘制函数中,使用 drawImage 指定源图像和目标 rect 以在 mouseMoveEvent 中更新的大小绘制图像:-

void QPainter::drawImage(const QRectF & rectangle, const QImage & image);

因此,通过将源图像保持在其原始大小,您不会在每次连续调整大小时越来越扭曲它。

class PersonSizeGraphicsItem : public QGraphicsItem
{
    public:
        PersonSizeGraphicsItem(QGraphicsItem* parent);

    protected:
        void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
        void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0)

    private:
        QRectF m_imageRect;
        QImage m_image;
};

void PersonSizeGraphicsItem::mouseMoveEvent()
{
   // Update the image rect here
}

void PersonSizeGraphicsItem::paint(QPainter * painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    painter->drawImage(m_imageRect, m_image);
}

【讨论】:

  • Wrt ur cmets "在 mouseMove 函数中,更新成员变量以存储您显示的图像的大小"
  • Wrt ur cmets "在 mouseMove 函数中,更新成员变量以存储您显示的图像的大小"。目前,我正在从缩放图像更新新的矩形尺寸?这种方法可以吗,否则我将如何获得我显示的图像的大小,除非我使用 setPixmap() 设置缩放的像素图? QPainter::drawImage() 是否也会将图像设置为像素图?
  • 我已经实现了代码,当前调整大小只有在我们拖动矩形的右侧和底部时才有效。从左侧和顶部调整大小不会发生。矩形只会移动而不是调整大小当被拖到那些边时。请你帮我处理一下 mouseMoveEvent() 并告诉我出了什么问题?
  • 如何将代码发送给您?此处无法粘贴 mouseMoveEvent() 代码。它不适合本节。
  • Merlin069 - 在我的原始实现中,矩形的宽度和高度取自缩放的图像,mouseMoveEvent() 中的逻辑用于调整矩形的大小。我能够从任何方面调整矩形的大小。
【解决方案2】:

根据 Merlin069 的回答重新实现代码:

PersonSizeGraphicsItem::PersonSizeGraphicsItem(const QPixmap &pixmap, QGraphicsScene *scene)
    :QGraphicsPixmapItem(pixmap, 0, scene)
{
    this->setFlag(QGraphicsItem::ItemIsMovable, true);
    this->setFlag(QGraphicsItem::ItemIsSelectable, true);
    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    this->setFlag(QGraphicsItem::ItemIsFocusable, true);
    this->setFocus(Qt::MouseFocusReason);
    this->setAcceptHoverEvents(true);
    //this->setScale(0.5);

    rect_left_condition = false;
    rect_right_condition = false;
    rect_top_condition = false;
    rect_bottom_condition = false;
    rect_resize_occurred = false;
    image_rect = QRect();
    image_rect =  this->pixmap().toImage().rect();
}

void PersonSizeGraphicsItem::setSourceImage(const QImage& source_image)
{
    this->source_image =  source_image;
}


void PersonSizeGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    const QPointF event_pos = event->pos();
    const QPointF event_scene_pos = event->scenePos();

    QPoint current_top_left = image_rect.topLeft();
    QPoint current_bottom_right = image_rect.bottomRight();

    if((event->scenePos().x() > this->scene()->width()) || (event->scenePos().y() > this->scene()->height())
        || (event->scenePos().x() < 0) || (event->scenePos().y() < 0) )
    {
        return;
    }

    if( this->cursor().shape() == Qt::SizeHorCursor )
    {
        if(rect_right_condition)
        {

        image_rect = QRect( current_top_left, QPoint( event->pos().x(), current_bottom_right.y()) );

        }

        if(rect_left_condition)
        {

            image_rect = QRect( QPoint(event_pos.x(), 0), current_bottom_right);

            QPoint new_top_left = image_rect.topLeft();
            QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
            this->setPos(mapped_topLeft);
            rect_resize_occurred = true;

            //qDebug() << "new rectangle top left**:" << this->pixmap().rect().topLeft();
        }

    }

    if( this->cursor().shape() == Qt::SizeVerCursor )
    {
        if(rect_bottom_condition)
        {

            image_rect = QRect(current_top_left, QPoint(current_bottom_right.x(), event->pos().y()));


    }

        if(rect_top_condition)
        {
            image_rect = QRect(QPoint(0, event_pos.y()), current_bottom_right);

                        QPoint new_top_left = image_rect.topLeft();
            QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
            this->setPos(mapped_topLeft);


        }
    }

    this->update();

}

void PersonSizeGraphicsItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawImage(image_rect, source_image);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多