Results 1 to 3 of 3

Thread: QGraphicsGridLayout & QGraphicsLayoutItem boundingRect struggles.

  1. #1
    Join Date
    Apr 2007
    Location
    United States
    Posts
    17
    Thanks
    2
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QGraphicsGridLayout & QGraphicsLayoutItem boundingRect struggles.

    I have a traditional QWidget based UI with a QGraphicsView (well inside a QVBoxLayout of a QWidget) set as the QMainWindows central widget.

    I subclassed QGraphicsVideoItem and QGraphicsLayoutItem so that I could build a NxN grid of videos. When I start the application it looks like this:

    Screenshot of app before Resizing

    For the most part it works, and once the first resize event triggers the videos correctly fill the available space.

    Screenshot of app after Resizing

    At this point when I dynamically resize the application, they grow and shrink (keeping aspect ratio) as they should.

    I realize that until the show event, geometry sizes will be 0. That would explain why my boundingRect() of each custom GraphicsLayoutItem returns the equivalent of QRectF(0, 0, QSize(0, 0)). However, this fact is causing multiple problems for me and I feel like i'm spinning my wheels trying to fix it. If you look at the first screenshot, you will see that the video sizes are set to a 400x300 size because i was forced to set the minimum row/col sizes in the QGraphicsGridLayout. Without those values being set the video items will be drawn as if they have zero size (because my boundingRect is zero) appearing as a point with my borders painted around them). In addition to that, all mouse events are not being propagated to the individual GraphicsItems since you cant click on something registered as having a size of zero.

    I have tried multiple approaches. I have tried setting the boundingRect of the custom GraphicsItems to return a default size of 400x300. This sort of fixes the mouse event propagation issue, but the videos no longer resize larger than that, and when I resize the mouse area no longer sits over the top and is offset. I've tried manually calling setGeometry() on all custom Graphics Items within a resizeEvent() function in the QGraphicsView's parent QWidget. That caused other problems as I was trying to use the parents new size to calculate what an individual grid cell would be, which resulted in odd behavior as the setPos() call in setGeometry(x, y, w, h) would move the custom QGraphicsItem out of the grid and paint it at the (X,Y) point passed in.

    The one area I'm not exactly sure of is the behavior of QGraphicView's fitInView() function. I'm using that to keep the scene centered and taking up all available space in the view. However I'm not sure if thats just artificially zooming in and out (without changing the actual sizes of the QGraphicsItems) or vice versa.

    Code in comments.

    viewwidget.h
    Qt Code:
    1. #ifndef VIDEOWIDGET_H
    2. #define VIDEOWIDGET_H
    3.  
    4. #include <QHash>
    5. #include <QWidget>
    6.  
    7. class QGraphicsGridLayout;
    8. class VideoPlayer;
    9. class ImagePlayer;
    10.  
    11. class VideoWidget : public QWidget
    12. {
    13. Q_OBJECT
    14. public:
    15. explicit VideoWidget(QWidget *parent = 0);
    16. ~VideoWidget();
    17.  
    18. QSize sizeHint() const { return QSize(800, 600); }
    19.  
    20. QGraphicsView* GetGraphicsView() { return _view; }
    21. QGraphicsScene* GetGraphicsScene() { return _scene; }
    22. VideoPlayer* GetActiveVideoPlayer() { return _activeVideoPlayer; }
    23. ImagePlayer* GetActiveImagePlayer() { return _activeImagePlayer; }
    24.  
    25. signals:
    26. void Signal_VideoActive(QString name, bool active);
    27.  
    28. protected:
    29. void resizeEvent(QResizeEvent* event);
    30.  
    31. private:
    32. void SetupUI();
    33. void Test();
    34.  
    35. int _rows, _cols;
    36.  
    37. QGraphicsView* _view;
    38. QGraphicsScene* _scene;
    39. QGraphicsGridLayout *_grid;
    40.  
    41. VideoPlayer* _activeVideoPlayer;
    42. ImagePlayer* _activeImagePlayer;
    43.  
    44. QHash<QString, VideoPlayer*> _videos;
    45. QHash<QString, ImagePlayer*> _images;
    46.  
    47. };
    48.  
    49. #endif // VIDEOWIDGET_H
    To copy to clipboard, switch view to plain text mode 

    videowidget.cpp
    Qt Code:
    1. #include <QtWidgets>
    2. #include <QHash>
    3. #include <QHashIterator>
    4. #include <QGraphicsVideoItem>
    5. #include <QGLWidget>
    6. #include <QGraphicsView>
    7. #include <QGraphicsWidget>
    8.  
    9. #include "videowidget.h"
    10. #include "videoplayer.h"
    11. #include "imageplayer.h"
    12.  
    13. VideoWidget::VideoWidget(QWidget *parent) :
    14. QWidget(parent)
    15. {
    16. _rows = 2;
    17. _cols = 2;
    18.  
    19. _activeVideoPlayer = NULL;
    20. _activeImagePlayer = NULL;
    21.  
    22. SetupUI();
    23. Test();
    24.  
    25. _view->fitInView(_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
    26. }
    27.  
    28. VideoWidget::~VideoWidget()
    29. {
    30. _videos.clear();
    31. _images.clear();
    32.  
    33. _activeVideoPlayer = NULL;
    34. _activeImagePlayer = NULL;
    35. }
    36.  
    37. void VideoWidget::SetupUI()
    38. {
    39. _view = new QGraphicsView(this);
    40. _view->setAcceptDrops(true);
    41. _view->viewport()->setMouseTracking(true);
    42. _view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    43. _view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    44. _view->setResizeAnchor(QGraphicsView::AnchorViewCenter);
    45.  
    46. _scene = new QGraphicsScene(this);
    47. _scene->setBackgroundBrush(QColor(39,39,39));
    48.  
    49. _view->setScene(_scene);
    50.  
    51. _grid = new QGraphicsGridLayout;
    52. _grid->setContentsMargins(5, 5, 5, 5);
    53.  
    54. QGraphicsWidget *container = new QGraphicsWidget;
    55. container->setAcceptHoverEvents(true);
    56. container->setAcceptTouchEvents(true);
    57. container->setLayout(_grid);
    58. container->setContentsMargins(0, 0, 0, 0);
    59. _scene->addItem(container);
    60.  
    61. QBoxLayout *layout = new QVBoxLayout;
    62. layout->setContentsMargins(0, 0, 0, 0);
    63. layout->addWidget(_view);
    64. this->setLayout(layout);
    65. }
    66.  
    67. void VideoWidget::Test()
    68. {
    69. VideoPlayer* videoPlayer;
    70. QString video("/Users/chucks/test.mp4");
    71. int count = 0;
    72. for(int i=0; i<_rows; i++)
    73. {
    74. for(int j=0; j<_cols; j++)
    75. {
    76. QString name = "Video" + QString::number(++count);
    77. videoPlayer = new VideoPlayer(name, video);
    78. _scene->addItem(videoPlayer);
    79. _videos.insert(name, videoPlayer);
    80. _grid->addItem(videoPlayer, i, j);
    81.  
    82. _grid->setColumnAlignment(j, Qt::AlignHCenter);
    83. _grid->setColumnMinimumWidth(j, 400);
    84. _grid->setColumnSpacing(j, 10);
    85. }
    86. _grid->setRowAlignment(i, Qt::AlignCenter);
    87. _grid->setRowMinimumHeight(i, 300);
    88. _grid->setRowSpacing(i, 10);
    89. }
    90. }
    91.  
    92. void VideoWidget::resizeEvent(QResizeEvent* event)
    93. {
    94. _view->fitInView(_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
    95. QWidget::resizeEvent(event);
    96. }
    To copy to clipboard, switch view to plain text mode 

    videoplayer.h
    Qt Code:
    1. #ifndef VIDEOPLAYER_H
    2. #define VIDEOPLAYER_H
    3.  
    4. #include <QMediaPlayer>
    5. #include <QMovie>
    6. #include <QGraphicsLayoutItem>
    7. #include <QGraphicsVideoItem>
    8. #include <QPainter>
    9. #include <QPixmap>
    10. #include <QGraphicsSceneMouseEvent>
    11.  
    12. class VideoPlayer : public QGraphicsVideoItem, public QGraphicsLayoutItem
    13. {
    14. public:
    15. VideoPlayer(QString name, QString fileName);
    16.  
    17. QRectF boundingRect() const;
    18. void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    19.  
    20. QString name() { return _name; }
    21. QString file() { return _fileName; }
    22. bool isPlaying() { return _isPlaying; }
    23.  
    24. void setGeometry(const QRectF & rect);
    25. void updateGeometry();
    26.  
    27. signals:
    28.  
    29. public slots:
    30. void Slot_OpenFile();
    31. void Slot_Play();
    32. void Slot_Stop();
    33. void Slot_Rewind();
    34. void Slot_FastForward();
    35.  
    36. protected:
    37. QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF()) const;
    38. void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
    39. void mousePressEvent(QGraphicsSceneMouseEvent * event);
    40. void mouseReleaseEvent(QGraphicsSceneMouseEvent * event);
    41. void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event);
    42.  
    43. private slots:
    44. void mediaStateChanged(QMediaPlayer::State state);
    45. void positionChanged(qint64 position);
    46. void durationChanged(qint64 duration);
    47. void setPosition(int position);
    48.  
    49. private:
    50. QMediaPlayer* _mediaPlayer;
    51. QPixmap *_pm;
    52. QString _name;
    53. QString _fileName;
    54.  
    55. bool _isPlaying;
    56.  
    57. };
    58.  
    59. #endif // VIDEOPLAYER_H
    To copy to clipboard, switch view to plain text mode 

    videoplayer.cpp
    Qt Code:
    1. #include "videoplayer.h"
    2.  
    3. #include <QtWidgets>
    4. #include <QVideoSurfaceFormat>
    5. #include <QGraphicsItem>
    6. #include <QGraphicsScene>
    7. #include <QPainter>
    8. #include <QStyleOption>
    9.  
    10. VideoPlayer::VideoPlayer(QString name, QString fileName) :
    11. QGraphicsVideoItem(),
    12. QGraphicsLayoutItem()
    13. {
    14. setFlag(QGraphicsItem::ItemIsSelectable, true);
    15. setFlag(QGraphicsItem::ItemIsFocusable, true);
    16. setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    17.  
    18. setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
    19. setAcceptHoverEvents(true);
    20. setAcceptDrops(true);
    21.  
    22. setAspectRatioMode(Qt::KeepAspectRatio);
    23.  
    24. _name = name;
    25. _fileName = fileName;
    26. _isPlaying = false;
    27.  
    28. _mediaPlayer = new QMediaPlayer(0, QMediaPlayer::VideoSurface);
    29. _mediaPlayer->setVideoOutput(this);
    30. connect(_mediaPlayer, &QMediaPlayer::stateChanged, this, &VideoPlayer::mediaStateChanged);
    31. connect(_mediaPlayer, &QMediaPlayer::positionChanged, this, &VideoPlayer::positionChanged);
    32. connect(_mediaPlayer, &QMediaPlayer::durationChanged, this, &VideoPlayer::durationChanged);
    33.  
    34. _pm = new QPixmap(QLatin1String(":/images/Resources/noise.png"));
    35. setGraphicsItem(this);
    36. }
    37.  
    38. QRectF VideoPlayer::boundingRect() const
    39. {
    40. return QRectF(QPointF(0, 0), geometry().size());
    41. }
    42.  
    43. void VideoPlayer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    44. {
    45. Q_UNUSED(widget);
    46. Q_UNUSED(option);
    47.  
    48. QRectF frame(QPointF(0,0), geometry().size());
    49.  
    50. qreal w = (parentItem()->boundingRect().width()/2) - 10;
    51. qreal h = (parentItem()->boundingRect().height()/2) - 10;
    52.  
    53. // paint a rect around the pixmap
    54. QPointF pixpos = frame.center() - (QPointF(w, h) / 2);
    55. QRectF innerFrame(pixpos, QSizeF(w, h));
    56. innerFrame.adjust(-4, -4, 4, 4);
    57. painter->setBrush(QBrush(Qt::darkGreen));
    58.  
    59. if(isSelected())
    60. {
    61. painter->setBrush(QBrush(Qt::green));
    62. painter->drawRoundedRect(innerFrame, 10.0, 10.0);
    63. }
    64. else
    65. {
    66. painter->setBrush(QBrush(Qt::darkGreen));
    67. painter->drawRect(innerFrame);
    68. }
    69.  
    70. // paint a title bar rect
    71. QRect rectangle(-w/2, -h/2, w, 20);
    72. painter->setPen(QPen(Qt::darkGreen));
    73. painter->setBrush(QBrush(QColor(39,39,39)));
    74. painter->drawRect(rectangle);
    75.  
    76. // paint video name in title bar
    77. painter->drawText(rectangle, Qt::AlignCenter, _name);
    78.  
    79. // paint the default background pixmap
    80. painter->drawPixmap(pixpos.x(), pixpos.y()+rectangle.height(), w, h-rectangle.height(), *_pm);
    81. painter->setPen(QPen(QBrush(Qt::black), 10));
    82. painter->drawText(innerFrame, Qt::AlignCenter, "No Video");
    83.  
    84. QGraphicsVideoItem::paint(painter, option, widget);
    85. }
    86.  
    87. void VideoPlayer::Slot_OpenFile()
    88. {
    89. }
    90.  
    91. void VideoPlayer::Slot_Play()
    92. {
    93. }
    94.  
    95. void VideoPlayer::Slot_Stop()
    96. {
    97. _mediaPlayer->stop();
    98. }
    99.  
    100. void VideoPlayer::Slot_Rewind()
    101. {
    102. }
    103.  
    104. void VideoPlayer::Slot_FastForward()
    105. {
    106. }
    107.  
    108. void VideoPlayer::mediaStateChanged(QMediaPlayer::State state)
    109. {
    110. }
    111.  
    112. void VideoPlayer::positionChanged(qint64 position)
    113. {
    114. }
    115.  
    116. void VideoPlayer::durationChanged(qint64 duration)
    117. {
    118. }
    119.  
    120. void VideoPlayer::setPosition(int position)
    121. {
    122. }
    123.  
    124. void VideoPlayer::setGeometry(const QRectF & rect)
    125. {
    126. prepareGeometryChange();
    127. QGraphicsLayoutItem::setGeometry(rect);
    128. setPos(rect.topLeft());
    129. }
    130.  
    131. void VideoPlayer::updateGeometry()
    132. {
    133. QGraphicsLayoutItem::updateGeometry();
    134. }
    135.  
    136. QSizeF VideoPlayer::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
    137. {
    138. switch ( which )
    139. {
    140. case Qt::MinimumSize:
    141. case Qt::PreferredSize:
    142. return this->boundingRect().size();
    143. case Qt::MaximumSize:
    144. return QSizeF(parentItem()->boundingRect().width(), parentItem()->boundingRect().height());
    145. default:
    146. return this->boundingRect().size();
    147. }
    148.  
    149. return constraint;
    150. }
    151.  
    152. void VideoPlayer::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
    153. {
    154. QGraphicsVideoItem::mouseMoveEvent(event);
    155. }
    156.  
    157. void VideoPlayer::mousePressEvent(QGraphicsSceneMouseEvent * event)
    158. {
    159. QGraphicsVideoItem::mousePressEvent(event);
    160. }
    161.  
    162. void VideoPlayer::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
    163. {
    164. QGraphicsVideoItem::mouseReleaseEvent(event);
    165. }
    166.  
    167. void VideoPlayer::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)
    168. {
    169. QGraphicsVideoItem::mouseDoubleClickEvent(event);
    170. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsGridLayout & QGraphicsLayoutItem boundingRect struggles.

    The one area I'm not exactly sure of is the behavior of QGraphicView's fitInView() function. I'm using that to keep the scene centered and taking up all available space in the view. However I'm not sure if thats just artificially zooming in and out (without changing the actual sizes of the QGraphicsItems) or vice versa.
    fitInView() simply applies a scale factor (or factors, if ignoring aspect ratio) to the scene so that all elements in the scene are visible in the view. As far as I know, it is simply a transformation applied during rendering with no effect on the underlying items in the scene.

    I'm not clear why your VideoWidget class inherits from QWidget. Why not simply make VideoWidget a QGraphicsView instead of pushing your actual graphics view down two layers by embedding it in an otherwise empty QVBoxLayout which is then set as the layout for VideoWidget? QGraphicsView *is* a QWidget, and it will happily live as the central widget for a QMainWindow.

    You might also try playing around with the row and column stretch factors for your grid layout.

    If what you want is that the "before resize" screen shot should instead look like the "after resize" screenshot, implement a showEvent() and call fitInView() there.

  3. #3
    Join Date
    Apr 2007
    Location
    United States
    Posts
    17
    Thanks
    2
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QGraphicsGridLayout & QGraphicsLayoutItem boundingRect struggles.

    Hey, thanks for the reply.
    I had forgotten I posted this question here too, should have posted. My issue was related to the boundingRect() of my individual video items. And I did end up using showEvent to accomplish the correct scaling at app startup. As for the VideoWidget, i originally had a single video window as a GraphicsView, and video controls as a QWidget. Thats why VideoWidget inherits from QWidget and it is inside the VBoxLayout. I just have not ripped that out yet... though i'm glad you pointed that out to remind me.

    So far fitInView() works but I'm going to just go though the motions and manually resize everything. I don't want everything to grow and shrink such as the video controls, just the video itself.

Similar Threads

  1. QGraphicsGridLayout Broken
    By oberlus in forum Qt Programming
    Replies: 1
    Last Post: 27th August 2010, 10:32
  2. Sublassing QGraphicsLayoutItem
    By onurozcelik in forum Qt Programming
    Replies: 7
    Last Post: 24th May 2010, 07:37
  3. AlignAbsolute - QGraphicsLayoutItem
    By onurozcelik in forum Qt Programming
    Replies: 3
    Last Post: 22nd April 2010, 08:17
  4. QGraphicsWidgets on QGraphicsGridLayout
    By onurozcelik in forum Qt Programming
    Replies: 4
    Last Post: 4th April 2010, 12:38
  5. heightForWidth QGraphicsLayoutItem
    By bunjee in forum Qt Programming
    Replies: 0
    Last Post: 20th October 2009, 09:14

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.