Floating QDockWidget appears not on the same screen as the main window when dragged - qt

I'm completely stuck with the following problem. When I drag a dock widget out of the main window, which is placed on the second screen, the floating dock appears on the first screen. When I click on the float button, it appears undocked correctly, i.e. near the main window, but only if I didn't drag it out before. If I did, docked it after and then clicked the float button, it appears detached on the first screen as well.
When I do all this on the first screen, it works fine.
First I thought I could force the dock widget to appear where I want it to by using something like this:
connect(dock, &QDockWidget::topLevelChanged, [this, dock](bool) {
dock->setGeometry(this->x(), this->y(), 200, 500);
});
It solved buggy floating button behavior, but didn't help with dragging, so my dock widget appears 200x500 px on the first screen again.
I also don't see any possibility to subclass and override anything here.
Is there a way to make the dock widget appear on the screen where the main window is, when it's detached by dragging?

Related

How to prevent QMenu from going out of the main window

I have a QMenubar inside QMainWindow. I have set it to be displayed on the right corner using setCornerWidget. But the menu items are going out of the main window. How can I prevent the menu to be displayed within the window?
I have already tried menu->setLayoutDirection(Qt::RightToLeft) which is giving me a mirror image of the current menu display as seen below, but that does not look good to me. Is there a way to keep the direction from Qt::LeftToRight and still be able to contain the menu inside the window?

How to dock a QDockWidgets inside a QSplitter?

I am trying to have a QSplitter accept QDockWidgets in my application. So far, I have done everything through the Qt Designer and what I have done is create three individual QWidgets. I then select all three of the QWidgets and I right click on them and select Layout->Lay out Vertically in a Splitter.
This lays all three of the widgets in a splitter quite nicely. I then drag a Dock Widget to the Object/Class Window in the top right and set them in the Splitters Widget. This places the QDockWidget happily inside the widget. However, when I fire up the program I cannot click and drag the dock widgets. If I double click the dock widget, the dock widget will pop out, however I cannot place it back since it was never technically docked. Which then creates the problem of the widget not being allowed to dock anywhere else. It cannot be docked on the QMainWindow class or in the QSplitter class.
Is there anyway to have a QDockWidget docked inside of a QSplitter and have the functionality of a QDockWidget?
After you add the dock widget to the QSplitter, the widget has become part of the splitter.
You can try checking like this
//If sure of Dockwidget at zeroth position
QDockWidget *widget1 = (QDockWidget*)ui->splitter->children().at(0);
A Dockwidget has a feature of floating as a top level window.
But you can make a dockwidget look like other widgets by setting QDockWidget::NoDockWidgetFeatures
Either:
Go to the object window in Qtdesigner (top -> right)
And select the dock widget added to splitter.
In proeprties window, down below scroll down and look for "features".
Then uncheck the features like movalble, closable etc....
I made it NoDockWidgetFeatures.
or
You can set programmatically using setFeatures(QDockWidget::NoDockWidgetFeatures)

How to increase the clickable area of a QPushButton in Qt?

The Back button in the top left corner of my touch user interface is a little hard to press on a resistive touchscreen, because the touch events are not so precise at the borders of the screen.
The visual size of the button can't really be increased because the screen space is needed for other things. Thus I would like to increase only the clickable area of the button. So when the user touches somewhere in the top left corner of the screen (as marked in red), the back button should be pressed. Note that the red area also overlaps another button. Ideally, the visual button state would also change to the "pressed" state.
Can anyone give me some pointers in the right direction? I have considered the following things, but I'm unsure which would work.
Overlaying the actual button with a larger, invisible button, painted with a transparent brush. But I have no idea how I could paint the smaller button as "pressed" when the user is pressing the invisible button.
Creating a new class based on QWidget, which has the size of the red area (with invisible background) and contains the actual button. Then relay touch events to the button so that it is pressed when the user touches the empty area.
Subclassing QPushButton and reimplementing QAbstractButton::hitButton to accept points outside of the button's area. But I guess that function would probably isn't even called when I touch outside the widget area.
To occupy more vertical space inside a layout, set buttons vertical policy to expanding.
To increase the clickable area without increasing the visual size, increase the margin.
To have the back button overlapping other buttons, don't put it to a layout. Instead set its parent directly and move it to the corner.
backButton = new QPushButton("< Back", mainWindow);
backButton->setStyleSheet("margin: 30;");
backButton->show();
backButton->resize(150, 90);
backButton->move(-30, -30);

QScrollArea - how to do precise programmatic scrolling

I am using Qt to build a view for multipage documents. I'm drawing each page to a separate QLabel widget, like in the ImageViewer example app.
The QLabels are organized vertically using QVBoxLayout. This all works nicely, with a little grey margin between the pages.
What I want now is, when the user does page down, to move the scroll so that the top of a particular QLabel appears right at the top of the window. the "ensure" functions might do that, but I'm not immediately seeing how.
Has anyone done something like this?
If a child widget is taller that the viewport height ensureWidgetVisible scrolls to the middle of the widget.
If you need to scroll to the top of the widget you can do it easily with a little calculation:
//childWidget - QLabel you want to move to
//area - QScrollArea
// calculate childWidget position in coordinates of the viewport
const QPoint p = childWidget->mapTo(area, QPoint(0,0));
// move scroll bar
area->verticalScrollBar()->setValue(p.y() + area->verticalScrollBar()->value());

QScollArea doesn't autoscroll when dragging inside it

I have some widgets inside a QScrollArea and I'm dragging between these widgets, the problem is that the QScrollArea doesn't scroll when I'm dragging inside it, so if I want to drag between a widget A to the widget B and the widget B is not visible on the viewport, the QScrollArea doesn't automatically scroll when the mouse moves to the edge of the viewport.
Subclass your scroll area, and add in one of the functions below.
http://qt-project.org/doc/qt-4.8/qwidget.html#mousePressEvent
http://qt-project.org/doc/qt-4.8/qwidget.html#dragMoveEvent
http://qt-project.org/doc/qt-4.8/qwidget.html#dragLeaveEvent // Probably just need this one
When the dragMoveEvent reaches the edge of your widget, or when the dragLeaveEvent happens, detect which edge it is, or left at, and then scroll your area in that direction.
Hope that helps.

Resources