Нужна помощь, чтобы понять, как работает sceneRect в Qt - PullRequest
1 голос
/ 19 апреля 2019

Я новичок в Qt.Я читаю учебные пособия, но до сих пор не понимаю, как работает sceneRect.

Когда я запускаю этот код, изображение (зеленое) отображается посередине (вероятно, по умолчанию, верно?)

MyApplication.cpp

ui.setupUi(this);    

ui.graphicsView->setBackgroundBrush(Qt::red);
_graphicsScene = make_unique<QGraphicsScene>(this);
ui.graphicsView->setScene(_graphicsScene.get());

_graphicsScene->setBackgroundBrush(Qt::blue);

QImage img("C:\\Users\\user\\Downloads\\img.png");
auto pixImg = QPixmap::fromImage(img);
pixImg = pixImg.scaled(QSize(50, 50), Qt::KeepAspectRatio);

QGraphicsPixmapItem* item = new QGraphicsPixmapItem(pixImg);
_graphicsScene->addPixmap(pixImg);

enter image description here

ui_MyApplication.h

void setupUi(QMainWindow *MyApplicationToolClass)
{
    if (MyApplicationToolClass->objectName().isEmpty())
        MyApplicationToolClass->setObjectName(QString::fromUtf8("MyApplicationToolClass"));
    MyApplicationToolClass->resize(465, 372);
    centralWidget = new QWidget(MyApplicationToolClass);
    centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
    entitiesView = new QGraphicsView(centralWidget);
    entitiesView->setObjectName(QString::fromUtf8("entitiesView"));
    entitiesView->setGeometry(QRect(30, 20, 401, 281));
    MyApplicationToolClass->setCentralWidget(centralWidget);
    menuBar = new QMenuBar(MyApplicationToolClass);
    menuBar->setObjectName(QString::fromUtf8("menuBar"));
    menuBar->setGeometry(QRect(0, 0, 465, 21));
    MyApplicationToolClass->setMenuBar(menuBar);
    mainToolBar = new QToolBar(MyApplicationToolClass);
    mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
    MyApplicationToolClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
    statusBar = new QStatusBar(MyApplicationToolClass);
    statusBar->setObjectName(QString::fromUtf8("statusBar"));
    MyApplicationToolClass->setStatusBar(statusBar);

    retranslateUi(MyApplicationToolClass);

    QMetaObject::connectSlotsByName(MyApplicationToolClass);
} // setupUi

Я подумал, что если установить sceneRect на (0,0,100,100) на _entitiesScene->setSceneRect(0, 0, 100, 100);, изображение будет отображаться в верхнем левом углу, но оно немного сдвинется вверх.

enter image description here

Я установил sceneRect на (50,50,100,100), он сдвигается вверх и влево

enter image description here

1 Ответ

0 голосов
/ 20 апреля 2019

Краткий обзор sceneRect сцены, boundingRect элементов:

QGraphicsItem::boundingRect:

Эта чисто виртуальная функция определяетвнешние границы элемента в виде прямоугольника;вся живопись должна быть ограничена внутри ограничительного прямоугольника элемента.QGraphicsView использует это для определения необходимости перерисовки элемента.

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

QGraphicsScene::sceneRect

Это свойство содержит прямоугольник сцены;ограничивающий прямоугольник сцены

Прямоугольник сцены определяет экстент сцены.Он в основном используется QGraphicsView для определения области прокрутки по умолчанию для представления и QGraphicsScene для управления индексированием элементов.

Если не установлено или если установлено нулевое значение QRectF, sceneRect () вернет самый большой ограничивающий прямоугольник из всехэлементы на сцене с момента создания сцены (т. е. прямоугольник, который увеличивается при добавлении или перемещении элементов в сцене, но никогда не сжимается).

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

Отсутствующий фрагмент OP - это ИМХО, что при рендеринге учитывается что-то еще:

QGraphicsView::alignment

Это свойство содержит выравнивание сцены в представлении, когда видна вся сцена.

Если вся сцена видна в виде (т. Е. Нет видимых полос прокрутки), выравнивание вида будет определять, где сцена будет отображаться в виде.Например, если выравнивание Qt :: AlignCenter, которое является значением по умолчанию, сцена будет центрирована в представлении, а если выравнивание (Qt :: AlignLeft | Qt :: AlignTop), сцена будет отображаться в верхней части.-левый угол обзора.)

Для этого QGraphicsView учитывает собственный размер представления и прямоугольник сцены и вычисляет соответствующий перевод для достижения требуемого выравнивания.Перевод используется для обновления QGraphicsView::transform, который отображает координаты сцены в координаты области просмотра.

Небольшой пример, чтобы проиллюстрировать это (testQGraphicsSceneSceneRect.cc):

#include <QtWidgets>

// returns a random floating point number in [min, max).
qreal randF(qreal min, qreal max)
{
  return qrand() / (RAND_MAX + 1.0) * (max - min) + min;
}

// returns a random color.
QColor randColor()
{
  return QColor(
    (int)256 * randF(0.0, 1.0),
    (int)256 * randF(0.0, 1.0),
    (int)256 * randF(0.0, 1.0));
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QMainWindow qWin;
  qWin.setWindowTitle("QSceneGraph::sceneRect Demo");
  QToolBar qToolbar;
  QAction qCmdAdd("Add Rect");
  qToolbar.addAction(&qCmdAdd);
  QAction qCmdClear("Clear Scene");
  qToolbar.addAction(&qCmdClear);
  qToolbar.addSeparator();
  QWidget qEditAlign;
  QGridLayout qGridAlign; QButtonGroup qBtnGrp;
  QRadioButton qBtnTL, qBtnTC, qBtnTR;
  qGridAlign.addWidget(&qBtnTL, 0, 0);
  qBtnGrp.addButton(&qBtnTL, Qt::AlignLeft | Qt::AlignTop);
  qGridAlign.addWidget(&qBtnTC, 0, 1);
  qBtnGrp.addButton(&qBtnTC, Qt::AlignHCenter | Qt::AlignTop);
  qGridAlign.addWidget(&qBtnTR, 0, 2);
  qBtnGrp.addButton(&qBtnTR, Qt::AlignRight | Qt::AlignTop);
  QRadioButton qBtnCL, qBtnCC, qBtnCR;
  qGridAlign.addWidget(&qBtnCL, 1, 0);
  qBtnGrp.addButton(&qBtnCL, Qt::AlignLeft | Qt::AlignVCenter);
  qGridAlign.addWidget(&qBtnCC, 1, 1);
  qBtnGrp.addButton(&qBtnCC, Qt::AlignHCenter | Qt::AlignVCenter);
  qGridAlign.addWidget(&qBtnCR, 1, 2);
  qBtnGrp.addButton(&qBtnCR, Qt::AlignRight | Qt::AlignVCenter);
  QRadioButton qBtnBL, qBtnBC, qBtnBR;
  qGridAlign.addWidget(&qBtnBL, 2, 0);
  qBtnGrp.addButton(&qBtnBL, Qt::AlignLeft | Qt::AlignBottom);
  qGridAlign.addWidget(&qBtnBC, 2, 1);
  qBtnGrp.addButton(&qBtnBC, Qt::AlignHCenter | Qt::AlignBottom);
  qGridAlign.addWidget(&qBtnBR, 2, 2);
  qBtnGrp.addButton(&qBtnBR, Qt::AlignRight | Qt::AlignBottom);
  qEditAlign.setLayout(&qGridAlign);
  qToolbar.addWidget(&qEditAlign);
  qWin.addToolBar(&qToolbar);
  QGraphicsView qGView;
  QGraphicsScene qGScene;
  qGView.setScene(&qGScene);
  qWin.setCentralWidget(&qGView);
  qWin.show();
  // activate button for default align of qGView
  qBtnGrp.button(qGView.alignment())->setChecked(true);
  // install signal handlers
  QObject::connect(&qCmdAdd, &QAction::triggered,
    [&]() {
      // add rect
      QRectF qRect(
        randF(-50.0, 50.0), randF(-50.0, 50.0),
        randF(10.0, 100.0), randF(10.0, 100.0));
      qGScene.addRect(qRect, QPen(randColor(), 2), randColor());
      // report
      qDebug() << "new rect:" << qRect;
      qDebug() << "scene rect:" << qGScene.sceneRect();
      qDebug() << "scene (0, 0) in view at:"
        << qGView.mapFromScene(QPointF(0.0, 0.0));
      qDebug() << "top left view corner in scene at:"
        << qGView.mapToScene(QPoint(0, 0));
    });
  QObject::connect(&qCmdClear, &QAction::triggered,
    [&]() {
      // clear scene
      qGScene.clear();
      // reset sceneRect
      qGScene.setSceneRect(QRect());
    });
  QObject::connect(&qBtnGrp,
    (void(QButtonGroup::*)(int, bool))&QButtonGroup::buttonToggled,
    [&](int id, bool checked) {
      if (checked) qGView.setAlignment((Qt::Alignment)id);
    });
  // run time loop
  return app.exec();
}

Соответствующий проект Qt (testQGraphicsSceneSceneRect.pro):

SOURCES = testQGraphicsSceneSceneRect.cc

QT += widgets

Скомпилировано и протестировано в cygwin64 :

$ qmake-qt5 testQGraphicsSceneSceneRect.pro

$ make && ./testQGraphicsSceneSceneRect
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQGraphicsSceneSceneRect.o testQGraphicsSceneSceneRect.cc
g++  -o testQGraphicsSceneSceneRect.exe testQGraphicsSceneSceneRect.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
Qt Version: 5.9.4
new rect: QRectF(-4.13499,25.5605 21.8384x10.0007)
scene rect: QRectF(-5.13499,24.5605 23.8384x12.0007)
scene (0, 0) in view at: QPoint(120,3)
top left view corner in scene at: QPointF(-120,-3)
new rect: QRectF(-46.5428,33.0965 56.7475x44.5152)
scene rect: QRectF(-47.5428,24.5605 66.2462x54.0512)
scene (0, 0) in view at: QPoint(141,-17)
top left view corner in scene at: QPointF(-141,17)

Snapshot of testQGraphicsSceneSceneRect (two rects added)

После этого я изменил выравнивание щелчком мыши:

scene (0, 0) in view at: QPoint(47,-24)
top left view corner in scene at: QPointF(-47,24)

Snapshot of testQGraphicsSceneSceneRect (alignment changed to top left)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...