У меня есть подкласс QGraphicsView, содержащий подкласс QGraphicsScene внутри QWidget.

QGraphicsScene имеет реальный прямоугольник для рисования с верхним пустым углом в точке (0,0) (так что сцена действительно имеет QRectF(-x,-y,w,h) значений, не имеющих отношения к проблеме).

При запуске, фактически в showEvent виджета, я устанавливаю размер сцены, чтобы она соответствовала прямоугольнику нестандартного размера. Это тоже его центрирует.

Я бы хотел, чтобы точка (0,0) сцены совпадала с верхним левым углом обзора при запуске.

В отличие от других вопросов с таким же названием, мне действительно нужно перемещать вид, а не элементы внутри сцены.

Изображение 1: фактическое начало, изображение 2: желаемое

actual desired

Я пытаюсь:

void MyWidget::showEvent(QShowEvent *event)
{
    static bool startUp = true;
    if(startUp)
    {
        QSizeF sz = m_scene->getActualSize();
        ui->graphicsView->fitInView(QRectF(0, 0, sz.width(), sz.height()), Qt::KeepAspectRatio);

        QPointF zero = ui->graphicsView->mapFromScene(QPointF(0,0));
        ui->graphicsView->translate(-zero.x(), -zero.y()); // or positive

        startUp = false;
    }
    QWidget::showEvent(event);
}

Примечание: я использую fitInView, чтобы получить желаемый масштаб - и он также фокусирует желаемый прямоугольник - но по центру обзора.

Я тоже пробовал

void GraphicsView::alignToZero()
{
    QPointF zero = this->mapFromScene(QPointF(0,0));
    this->scrollContentsBy(-zero.x(), -zero.y());
}

void MyWidget::showEvent(QShowEvent *event)
{
    static bool startUp = true;
    if(startUp)
    {
        QSizeF sz = m_scene->getActualSize();
        ui->graphicsView->fitInView(QRectF(0, 0, sz.width(), sz.height()), Qt::KeepAspectRatio);

        ui->graphicsView->alignToZero();

        startUp = false;
    }
    QWidget::showEvent(event);
}

По-прежнему безрезультатно.

Также пробовал

void MyWidget::showEvent(QShowEvent *event)
{
    static bool startUp = true;
    if(startUp)
    {
        QSizeF sz = m_scene->getActualSize();
        ui->graphicsView->fitInView(QRectF(0, 0, sz.width(), sz.height()), Qt::KeepAspectRatio);

        QPointF zero = ui->graphicsView->mapFromScene(QPointF(0,0));
        //ui->graphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
        ui->graphicsView->horizontalScrollBar()->setValue(zero.x());
        ui->graphicsView->verticalScrollBar()->setValue(zero.y());

        startUp = false;
    }
    QWidget::showEvent(event);
}

Это, с настройкой выравнивания или без нее (которая, я думаю, может иметь нежелательные эффекты в другом месте), сдвигает представление ... слишком далеко.

1
Thalia 24 Фев 2016 в 00:25

2 ответа

Лучший ответ

Хотя должен быть способ получше ... Я придумал способ выровнять мои 0, выполнив fitInView дважды:

void MyWidget::showEvent(QShowEvent *event)
{
    static bool startUp = true;
    if(startUp)
    {
        QSizeF sz = m_scene->getActualSize();
        // First I do a normal `fitInView` that centers the rectangle
        ui->graphicsView->fitInView(QRectF(0, 0, sz.width(), sz.height()), Qt::KeepAspectRatio);

        // Then, knowing the shift, I fit it again adding twice the shift to the size.
        QPointF zero = ui->graphicsView->mapToScene(QPoint(0,0));
        ui->graphicsView->fitInView(QRectF(0, 0, sz.width() - 2 * zero.x(), sz.height() - 2 * zero.y()), Qt::KeepAspectRatio);

        startUp = false;
    }
    QWidget::showEvent(event);
}
1
Thalia 23 Фев 2016 в 23:15

Если я правильно понял ваш вопрос, для достижения желаемого эффекта вы можете использовать метод

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

ui->graphicsView->setAlignment( Qt::AlignTop | Qt::AlignLeft );

Что прокомментировано в вашем коде. Этот метод с этими аргументами выравнивает вид по левому верхнему краю, вам не нужно ничего перемещать или подгонять.

6
Tomasz T 5 Июн 2016 в 09:42