Qt add Widget to GraphicsView? - c++

Is there a way to draw Widgets on QGraphicsView instead of QGraphicsScene so that the widget stays in position when the scene is moved?
I want to create some dialogs that are dockable inside the workspace like this:
http://www.thebandfrom.com/wp-content/uploads/photoshop-ui.png

You can use the addWidget function of QGraphicsScene, and then set the QGraphicsItem::ItemIgnoresTransformations flag to the added QGraphicsProxyWidget.
QGraphicsProxyWidget* proxyWidget = scene->addWidget(myWidget);
proxyWidget->setFlag(QGraphicsItem::ItemIgnoresTransformations);

You can add widgets onto the QGraphicsView directly by setting the QGraphicsView as their parent. You could also add a layout so that when the QGraphicsView is resized, your widgets arrange themselves appropriately.

Related

Prevent QDockWidget autosizing behaviour

Qt 5.5.0
In my application, I have a QGraphicsView as the main widget and a QDockWidget for properties.
The goal is for the user to select an item in the graphics view and, depending on the item, present the appropriate properties for that item.
I achieve this by having a properties manager widget with a layout containing each of the properties widgets. I have signals and slots hooked up for getting the currently selected item, and then show() the widget I need and hide() the rest.
This works great! However, when selecting different items, the dock shrinks or grows based on the shown widget. It is very jarring, and rather annoying. The thing is though, that when the user manually resizes the dock, it maintains that size. I want the maintained size to be default rather than this autosizing behaviour.
Things I've tried:
I've tried changing the sizePolicy() of the dock and the mainwindow: No effect.
I've set a minimum size for my properties manager which does indeed prevent the dock from shrinking when a smaller set of properties is shown. However, I still want the user to be able to shrink the dock to a smaller size if they wish, and this method prevents that...
Conclusion:
Is there a flag or something that is set when the user resizes the dock that tells it to maintain that size? If so, is there a way to manually set it?
I haven't tried subclassing QDockWidget or QMainWindow yet. Is there a method(s) that I can override to achieve the correct behaviour?
Thanks for any help!
All that was necessary was to call
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
in the constructor of my properties manager widget (the central widget of the QDockWidget)
I also overloaded the sizeHint() function to return a respectable default size.
First, create your dock widget:
QDockWidget *dock = new QDockWidget;
Now set size policy to dock's widget.
If dock is vertical:
dock->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
If dock is horizontal:
dock->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
Set your widget to dock:
QWidget *myWidget = new QWidget;
dock->setWidget(myWidget);
Now set size policy to dock's widget.
If dock is vertical:
dock->widget()->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
If dock is horizontal:
dock->widget()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
Finally, add dock to main window:
If dock is vertical:
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock);
mainWindow->resizeDocks({dock}, {0}, Qt::Horizontal);
If dock is horizontal:
mainWindow->addDockWidget(Qt::TopDockWidgetArea, dock);
mainWindow->resizeDocks({dock}, {0}, Qt::Vertical);

QMainWindow centralWidget border

I have a QMainWindow whose central widget has been set to a QGraphicsView viewing a black scene (for test purposes). Note that in the code below, I use my class derived from QGraphicsView, called CQtGlView, which reimplements only the resizeEvent function.
Regardless of whether I add the view directly,
CQtMainWindow::CQtMainWindow() {
m_glView = new CQtGlView();
setCentralWidget(m_glView);
}
or stick it in a layout with margins of 0 in a dummy widget,
CQtMainWindow::CQtMainWindow() {
m_glView = new CQtGlView();
QWidget* dummy = new QWidget();
QHBoxLayout* l = new QHBoxLayout();
l->setContentsMargins(0,0,0,0);
l->addWidget(m_glView);
dummy->setLayout(l);
setCentralWidget(dummy);
}
I get an unwanted grey border around the widget.
The screenshot below illustrates the problem, visible between my scene and the windows aero border.
This would not be a problem if my application did not allow switching to full screen. The border is very obvious once the rest of the screen is black.
It's possible this area represents the DockWidgetAreas around the outside of the central widget.
Is there anything I can do to solve this other than not use QMainWindow? (Undesirable due to my use of menuBar, tool bars, and statusBar.)
It turns out that QGraphicsView derives from QFrame, where I assumed it was only a QWidget.
The solution to this problem was to call setFrameStyle(QFrame::NoFrame); in the constructor of my QGraphicsView subclass. Or if it was not a subclass,
m_glView->setFrameStyle(QFrame::NoFrame);
Have you tried setFrameShape(QFrame::NoFrame) on the QGraphicsView?

Qt: making QHBoxLayout scrollable

I have a QHBoxLayout horizontal layout with a lot of list widgets added to it.
And although I call setMaximumWidth(300) and setMinimumWidth(300) for the list widgets, once they don't fit on the window, they start to shrink.
I would like to have a scroll bar instead. Is this possible?
Yes, if you put the Layout inside a parent widget, and that parent widget inside a QScrollArea.
QScrollArea Documentation

how to dynamically add a QWidget based to QGraphicsScene?

I want to add a QWidget based class(composed by buttons and labels an so on...) to my QGraphicScene scene in a special position and respecting the graphic style of my scene.?
I am using QT 4.7.
You may use QGraphicsScene::addWidget() to add your widget to the scene and use the returned QGraphicsProxyWidget * to reposition your widget with QGraphicsItem::setPos().
Alternatively, you may look into QGraphicsWidget class.

How should I use a QGraphicsScene with layouts and widgets

I'm creating some graphic data displaying widget in Qt4 and I was tempted to use the QGraphicsScene for it, create QGraphicsItems for the data items etc.
However, I wanted to add some layer of controls (eg. scrollbars, zoom+other buttons - I want to make it in a similar style as eg. Google Maps, that is, the data would be displayed all over the widget, and the buttons would be shown atop of them) to the widget. So I thought it might be feasible to add them to the scene (perhaps as a child of a QGraphicsGroupItem that would be shown over the data). But I want them to move & resize when I resize the whole widget, so I should use a QGraphicsLayout for managing them. But at this point, I discovered things are pretty complicated.
The problem is that when using QGraphicsLayout, the following constraints hold:
Only a QGraphicsWidget can be managed by a layout
QGraphicsLayout can only be used to manage children of a QGraphicsWidget
Which means that I would have to create my controls as QGraphicsWidgets, add a top level QGraphicsWidget to the data widget, and manage the size of this top level widget myself.
So I want to ask:
Wouldn't a classic approach (ie. use plain old widgets for all controls, and use QGraphicsScene only for displaying the data) be more reasonable?
Is there any advantage in using QGraphicsScene in this case (performance or simplicity...)?
How should I use QGraphicsScene to exploit its strengths?
Since Qt 4.4 you can embed classic widgets in a QGraphicsScene by using QGraphicsProxyWidget :
QWidget *widget = new QWidget;
QGraphicsScene scene;
QGraphicsProxyWidget *proxy = scene.addWidget(widget);
If you think that QGraphicsScene (or whatever other widget you have) is appropriate for most of your display, use that. What we have done in the past for somewhat similar things is to make a custom widget that inherits (one way or another) from QWidget, and put the control widgets in a layout on top of that widget. This means that the whole widget is drawing whatever it is you want drawn, and the control widgets are on top of that, resizing as the whole widget is resized.
Alternatively, a couple of times we've had layouts that were just a bit too complicated for the layout widgets to easily handle. Rather than create a custom layout, we just positioned them with no layout, and moved them in code on the resize event. It works just as well.