Why does Qt3DWindow on rare instances not render a scene and instead projects other parts of the GUI onto the window? - qt

This is a rare bug, but sometimes when I start my Qt app the qt3d window which hosts my scene is blank (without any of my models), except the window itself seems to be bugged because it will mirror other parts of the GUI if I shift between tabs. So instead of my scene appearing in the window it'll contain information and widgets from another tab that's located in the same area as the window on a different tab.
This doesn't occur very often, which makes the bug hard to replicate. Has anyone else seen this behavior before or maybe it's the way I'm setting up the Qt3DExtras::Qt3DWindow?
Qt3DExtras::Qt3DWindow* view = new Qt3DExtras::Qt3DWindow();
view->defaultFrameGraph()->setClearColor(QColor(0,0,0));
view->setRootEntity(CreateScene());
// embed 3D Window in Widget
QWidget* container = QWidget::createWindowContainer(view);
ui->verticalLayout_visualizer->addWidget(container);

Related

Main Window Goes Blank

In my QMainWindow based application, I'm using two QQuickWidgets. One loads the map (using QML Map Type) and other one loads a custom scene. MainWindow also runs a QTimer at 10 Hz.
When I continuously zoom in/out on the map, at some point, the main window goes blank. This behavior is quite consistent. After resizing the main window, it gets refreshed but sometimes the qml scene is not rendered properly. Kindly have a look at the attached screenshots.
Why the main window goes blank and how to overcome it.
You can find working demo application on GitHub: github link
I'm using Desktop Qt 5.12.3 MinGW 64-bit.
Working App
Blank Main Window
Corrupted QML Scene

How to "embed" one window inside another

I have inherited a Qt-based app that handles the master/detail relationship by presenting the detail screens as separate windows. The main window includes a list, and when you tap on a row a separate detail window is opened up.
In the code base, the detail windows are handled by a QML file and a matching .cpp file (the main window also has its own .cpp file). The problem I am facing is that a new client wants me to modify this application for them, except that they want everything to occur within a single window. They want the list to be shown on the left side, and then when a user taps a row, the detail screen is to be shown on the right side of the window in its own panel (but not in a separate window).
For various reasons I can't easily refactor this application. A quicker solution for me would be to continue to present the detail screen in its own window, but to make it a borderless window and position this borderless window over top of the main window (on the right) so that it appears to be a panel within the main window.
Is something like this possible with Qt? I have written Windows apps in the past that hooked into the Windows API to do something like, but I don't know whether this is even possible in a native Mac OS app, so I don't know whether Qt can handle it in some way automaticaly.
One thing you could try is to create a widget based "main" window and then use QWidget::createWindowContainer() to wrap the QtQuick windows for positioning them with QtWidget means, e.g. layouts.

Make the objects' size of a GUI adapt to window

I created a GUI with Qt5 but I will like the objects to be always contained in the window. When I change the size of the window (with the mouse), the objects dont resize themselves and therefore are hidden by the window.
Basically, I will like my GUI to act like a Web Page for example.
I think I have to use the Layout properties to do that but I dont seem to find it in Qt (in the QBBoxLayout or QWidget ?). I will like to change this in Qt and not in my PyQt script if possible.
Have you set the layout of the window ?
Normally you should have a code similar to this one
dialog = QDialog()
verticalLayout = QVBoxLayout()
label1 = QLabel("first")
label2 = QLabel("second")
verticalLayout.addWidget(label1)
verticalLayout.addWidget(label2)
dialog.setLayout(verticalLayout)
if you are creating the gui writing the necessary the code yourself.
If you are creating the gui with the designer, probably you have not applied a layout to your window.

Slow repaint underneath dragged object on X... Can Qt force drag and drop operations to be internal only?

I'm implementing Qt's drag and drop API across Windows and X. When I pick up an object in the app running on X and drag it, it leaves a white ghost trail of itself on the window underneath, as if the window underneath is being slow to repaint where the dragged object was previously obscuring part of itself.
I believe that this is symptomatic of the same problem that Qt has just solved with resizing windows causing flicker in child widgets on X windows - i.e. the dragged object is treated as a separate native window and therefore X handles the clipping from the dragged object to the window underneath. Since X does this in a different way to Qt, we get the ghosting effect.
Has anyone experienced the same problems? One solution that comes to mind is to use the same technique as detailed in the blog article linked above and stop the dragged object being treated as a native window, presumably at the cost of drag and drop being limited to my application only (I have no problem with this). Would anyone know how to force drag and drop operations to be internal only?
EDIT: I'm using QDrag::setPixmap to set the graphical representation of the dragged object - it is important that I retain this in favour of a standard drag cursor as this interface is being used on a touchscreen device and will hence have no visible cursor.
I'm now of the opinion that short of editing and then compiling my own build of Qt (not an option for me), I can't force drag and drop operations to be internal only.
Equally, I can't find any way of getting rid of the ghost trail by tweaking my window manager settings or using a compositing window manager (thanks anyway though #atomice). Using OpenGL as the renderer increases the screen repaint speed slightly, but is not perfect and introduces its own problems (see Starting a Qt drag operation on X11 w/ OpenGL causes screen flicker). I would still be very interested to hear any ideas though.
I have, however, got a workaround for my problem which works on both Windows and X. Here's a simplified version:
void DoDrag()
{
//Prepare the graphical representation of the drag
mDragRepresenter = new QWidget(QApplication::activeWindow());
mDragRepresenter->setAttribute(Qt::WA_TransparentForMouseEvents);
mDragRepresenter->SetPixmap(GenerateDragPixmap());
RepositionDragRepresenter();
mDragRepresenter->show();
QTimer UpdateTimer;
connect(&UpdateTimer, SIGNAL(timeout()), this, SLOT(RepositionDragRepresenter()));
UpdateTimer.start(40);
//Start the drag (modal operation)
Qt::DropAction ResultingAction = Drag->exec(Qt::CopyAction);
UpdateTimer.stop();
delete mDragRepresenter;
}
void RepositionDragRepresenter()
{
mDragRepresenter->move(QApplication::activeWindow()->mapFromGlobal(QCursor::pos()) - mDragRepresenterHotSpot);
}
An X11 window is only created for a drag operation if a QDrag::mimeData()->hasImage() is true. If you modify your code so it doesn't use an image then you will just get a drag cursor instead which won't trigger a repaint of the windows underneath.
You don't specify what kind of object you are dragging or how you are setting up the drag operation. Can you add some code to show that?

Attach Qt windows?

Is there any way to attach two Qt windows together? For example, if window A is the main window and window B is another widget I want to be able to show window B to the side of A and have both windows move together if the windows are dragged.
Not that I am aware of, but you can try following the trail of QMoveEvent. When a given widget is moved void QWidget::moveEvent ( QMoveEvent * event ) is called, and the QMoveEvent contains both old and new pos. Using this information, you can inject a move event in the other widget as well, and make it follow.
Of course, I am speaking of two independent widgets, each one in its own window. If they are contained, you don't need anything but a Layout management (see QLayout and related classes).
I don't work with Qt since a long time, so there could be a better method, but if I had to do it right now, this is the strategy I would use.
Also, I have the feeling that the QMoveEvent will be invoked only at start and end, unless you enable mouse tracking. If the former is the case, you will obtain that the other widget will "teleport" at the end of the move, instead of following smoothly.
You might be after something like this:
http://doc.qt.io/archives/4.6/qt4-mainwindow.html
Window A would be a QMainWindow and window B would be a QDockWidget.

Resources