Почему QGraphicsView не отображается - PullRequest
0 голосов
/ 02 апреля 2019

У меня есть следующие коды в моем проекте Qt со следующим main:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Widget w;
    w.show();

   return a.exec();
}

Класс Widget является объектом QWidget со следующим конструктором:

Widget::Widget(QWidget *parent)
: QWidget(parent)
{
   m_Scene = new QGraphicsScene(this);
   QGraphicsLinearLayout* layout = new 
   QGraphicsLinearLayout(Qt::Orientation::Vertical);
   for(int i = 0; i < 10; i++)
   {
      std::string name = "m_" + std::to_string(i);
      GraphicsTextItem* item = new GraphicsTextItem(nullptr, QString(name.c_str()));
      layout->addItem(item);
   }
   QGraphicsWidget* list = new QGraphicsWidget;
   list->setPos(0,0);
   list->setLayout(layout);
   m_Scene->addItem(list);

   QGraphicsView* view = new QGraphicsView(this);
   view->setScene(m_Scene);

   // Why one of these lines must be uncommented?
   //m_Scene->setSceneRect(0, 0, 1920, 768);
   //QVBoxLayout *ttopLayout = new QVBoxLayout;
   //ttopLayout->addWidget(view);
   //setLayout(ttopLayout);
  }

GraphicsTextItem простоQGraphicsWidget для отображения текста:

class GraphicsTextItem : public QGraphicsWidget
{
public:
    QString m_Name;
    QColor m_Color;
public:
    GraphicsTextItem(QGraphicsItem * parent = nullptr, const QString& name = QString());
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
{
    Q_UNUSED(option)
    Q_UNUSED(widget)

    QFont font("Times", 10);
    painter->setFont(font);
    painter->setPen(m_Color);
    painter->drawText(0, 0, m_Name);
}

};

Мой вопрос заключается в том, почему моя сцена не отображается.Я должен либо определить SceneRect, либо определить макет моего виджета?

1 Ответ

1 голос
/ 03 апреля 2019

Я сделал еще более короткий MCVE для демонстрации:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  QWidget qWinMain;
  qWinMain.resize(320, 240);
  QFrame qFrm(&qWinMain);
  qFrm.setFrameStyle(QFrame::Box | QFrame::Raised);
  qFrm.setLineWidth(0);
  qFrm.setMidLineWidth(1);
  qWinMain.show();
  return app.exec();
}

скомпилировано и запущено в cygwin64 . Вот как это выглядит:

Snapshot of MCVE (layout missing)

  1. Есть главное окно (с оформлением оконного менеджера).
  2. Есть ребенок QFrame.
  3. Дитя QFrame «вдавливается» в верхний левый угол.

Как получается?

Что обеспечивает QWidget: дочерние виджеты отображаются (спереди) при отображении QWidget.

Что QWidget не несет (непосредственной) ответственности за: Размещение дочерних виджетов.

Для этого необходимо подключить менеджер раскладки:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  QWidget qWinMain;
  qWinMain.resize(320, 240);
  QVBoxLayout qVBox(&qWinMain);
  QFrame qFrm(&qWinMain);
  qFrm.setFrameStyle(QFrame::Box | QFrame::Raised);
  qFrm.setLineWidth(0);
  qFrm.setMidLineWidth(1);
  qVBox.addWidget(&qFrm);
  qWinMain.show();
  return app.exec();
}

скомпилировано и запущено снова в cygwin64 . Вот как это выглядит:

Snapshot of MCVE (with layout)

Теперь QFrame qFrm хорошо заполняет QWidget qWinMain. События изменения размера, полученные в qWinMain, будут перенаправлены в менеджер раскладки qVBox, который снова изменит макет дочерних элементов qWinMain (т.е. qFrm).


Я твердо верю, что OP GraphicsView просто не виден, потому что у него нет минимальных требований к размеру. (Это просто маленький, чтобы быть видимым.)

Следовательно, добавление менеджера макета гарантирует, что GraphicsView заполняет клиентскую область родительского виджета. Изменение размера GraphicsView (на m_Scene->setSceneRect(0, 0, 1920, 768);) - это еще один способ исправить это, хотя и худший.


Наконец, ссылка на Qt Doc .: Управление раскладкой .

Управление макетом

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

Введение

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

Все подклассы QWidget могут использовать макеты для управления своими дочерними элементами. Функция QWidget :: setLayout () применяет макет к виджету. Когда макет устанавливается на виджет таким образом, он отвечает за следующие задачи:

  • Позиционирование дочерних виджетов
  • Разумные размеры по умолчанию для окон
  • разумные минимальные размеры для окон
  • Изменение размера
  • Автоматические обновления при изменении содержимого:
    • Размер шрифта, текста или другого содержимого дочерних виджетов
    • Скрытие или показ дочернего виджета
    • Удаление дочерних виджетов
...