QGraphics View layout - qt

Can somebody help me understand how the QGraphicsView works within a QVBoxlayout?
I inherit a class from QWidget and the following code works as expected when it gets displayed:
m_mainVBoxLayout=new QVBoxLayout;
this->setLayout(m_mainVBoxLayout);
QWidget *testWidget=new QWidget();
testWidget->setAutoFillBackground(true);
m_mainVBoxLayout->addWidget(testWidget);
QWidget *testWidget2=new QWidget();
testWidget2->setAutoFillBackground(true);
m_mainVBoxLayout->addWidget(testWidget2);
When I run it the screen is divided vertically and there are two shaded boxes for the test Widgets as expected.
But if I remove testWidget2 code and replace it by:
QGraphicsView *view=new QGraphicsView();
m_mainVBoxLayout->addWidget(view);
The layout is messed up in that I don't see the shaded box for testWidget.
I even tried creating a scene and adding it to the view to no avail.
Any ideas why this happens?

I need to learn how to read better (Qt Documentation)
You have to use the viewport() method of QGraphicsView to get the default QWidget associated with it.
m_mainVBoxLayout->addWidget(view->viewport());
fixes the problem.

Related

fit QGraphicsScene to QGraphicsView

I'm trying to draw a stacked bar graph on Qt, i followed the tutorial on the documentation but when i try to put the graph inside a QGraphicsView i get a lo of unused space and can't manage to make the scene fit the view.
My code is the same as the documentation one plus the following to make the scene show up in the view:
QGraphicsScene *scene = new QGraphicsScene(this);
scene->addWidget(chartView);
ui->view->setScene(scene);
And what i get is this
As you can see there is a lot of unused space and it makes the text disappear, i wanted to make the graph fit the view but i can't seem to find a way to do so.
I tried in many different ways using
ui->view->ensureVisible ( scene->sceneRect() );
ui->view->fitInView( scene->sceneRect(),Qt::KeepAspectRatio);
and
ui->view->setSceneRect(0,0,ui->view->frameSize().width(),ui->view->frameSize().height());
but nothing seems to work (the second solution just moves the graph to the top left)
As per the comment... the real issue is the basic sizing of chartView rather than anything to do with QGraphicsView or QGraphicsScene.
When a QWidget is added to a QGraphicsScene the resulting QGraphicsProxyWidget will generally honour the size hint and policy of that widget.
In addition, though, the QGraphicsScene will set the scene rect to the bounding rectangle of all scene items and the QGraphicsView will then position the scene according to whatever viewport anchor is in force. The end result can be visually misleading if the scene has a complex set of items or has a bounding rectangle smaller than that displayed within the GraphicsView.
So if a widget does look odd when added to a QGraphicsScene it's normally a good idea to test by just showing it as a top level window on the desktop and make sure it behaves as expected before going any further.

Attach a QLabel in front of QGLWidget

I have a QGLWidget and I like to attach on top of it a QLabel for some measurement visualization (fps, number of object, etc).
I'd like to keep QGLWidget as clean as possible for further re-using and not use QGLWidget::renderText inside of it but use an external debug interface with those measurement.
For now I have:
QVBoxLayout *l = new QVBoxLayout;
this->gl = new MyGLWidget;
l->addWidget(gl);
QLabel *fps = new QLabel;
fps->setText(QString("FPS"));
fps->setStyleSheet("QLabel { background-color : red; color : blue; }");
fps->setParent(gl);
this->setLayout(l);
But nothing appears.. of course if I add the QLabel to the layout with QLayout::addWidget I see it.. but is not what I want..
Some ideas?
Without being assigned to a layout the widget doesn't know, where it should draw, if you don't tell it explicitly. You must call QWidget::setGeometry explicitly to position it.
However placing regular Qt widgets on top of a QGLWidget has some merits. The QGLWidget actually creates a subwindow parented by the top level window. Regular widgets however don't have their own, deidicated subwindows, which means, that from the point of view of the graphics system they're on the same Z stacking level than the top level window itself. And the QGLWidget's actual subwindow has a higher Z stacking level. Parenting a QLabel to the QGLWidget should place it at the right Z stacking level. But then OpenGL drawing operations are different than Qt drawing operations, so your drawing on the QGLWidget may mess up the QLabel.
Simply spoken, there's a reason why QGLWidget has a function "drawText".

Qt : event invisible widget?

For some reasons, I need to draw a widget onto one another.
The structure is the following (see the image) :
I have an original QTableWigetItem
On the QTableWigetItem, I create a QWidget at the foreground with the same geometry
This QWidget contains a QBoxLayout
This QBoxLayout contains a QPixmap and a QComboBox
I want to do the following things :
The QWidget is just a "container" for my QBoxLayout and I would like to set him completely "invisible" for the user. If the user click or move at the position of the widget, I want the event of the QTableWigetItem in the background to be trigerred. But the problem is that I want the QPixmap and the QComboBox to be at the foreground, visible and "normal". For me it's just a trick to be able to put children widgets in a QTableWidget of a HeaderView.
How to make the QWidget "completely invisible" (from the event/signals point of view) ?
Thank you very much.
Try QWidget::setWindowOpacity(0)

How to anchor QGraphicsWidget/Item (make them static) on QGraphicsView

I want to make something like a hud. I have a QGraphicsScene with a huge QPixmap, that I added to a much smaller QGraphicsView. Now I need to add some control elements, like QLabel, QPushButton and QGraphicsEllipseItem. That's, I think, is not a problem. I found this helpful page Graphics View Classes. But how do I anchor this control elements to the View or maybe better said how do I not anchor them? When I drag the QPixmap, then I don't want that the hud is moving with the QPixmap out of the QGraphicsView.
What do I need to do, to solve this problem. Hope someone can help me.
You should just have to create your widgets and specify the QGraphicsView in the constructor like this:
QPushButton *button1 = new QPushButton(view);

How does QWidget size when used as a window?

Several examples on trolltech use QWidget rather than a QMainWindow as the main window for simple Qt applications.
Now I need just a simple window with a single content widget (QGlWidget) that covers the entire client area.
However, when I show a QWidget window with a single content window it automatically resizes itself to be tiny.
If I create the QWidget parent window without a child It is a nice large default size.
I don't want to resort to using Layouts for a single child window :/
What I understand is that you use a QWidget to display your QGIWidget. Try calling the show method of your QGIWidget directly (if your QGIWidget class inherits QWidget), Qt will create the window decoration for you.
Otherwise if you really need your widget to be inside one another, and fit its size, you'll have to use a layout.
Either follow gregseth's advice or you can simply resize the widget yourself.
(though this way you'll loose nice auto-resizing which is provided by Qt when you use layouts)
In your case you can basically do something like:
QGlWidget* myWidget = new QGlWidget;
myWidget->resize(QApplication::desktopWidget()->availableGeometry().size());
// or maybe instead of resizing show it in fullscreen:
myWidget->showFullScreen();
(actually I don't remember if showFullScreen() will do resizing for you, maybe you'll need both resize+showFullScreen :))
Cheers :)
P.S. Using layout is actually an option. It's not expensive and it's flexible. All it gets: "layout = new QVBoxLayout(myWidget); layout->addWidget(myWidget);" and you're done :)
Not always.
I've found that a QMainWindow will not work as the parent widget when using the QVBoxLayout and QHBoxLayout to arrange child widgets.
If you create a QWidget and use that in place of the QMainWindow then the layouts will work correctly.
QWidget* centralWidget = new QWidget( MainWindow );
MainWindow->setCentralWidget( centralWidget );
If you use QtCreator and look at the code it creates you can see it creating a 'hidden' widget if you try to use the layouts directly at the top level.
It's not obvious, intuitive, or documented anywhere that I've found.

Resources