How to set Focus on a specific widget - c++

I'm trying to implement GUI with various widgets for OpenGL project. I have a main widget for drawing the scene. The OpenGL widget is associated with Key and Mouse events, therefore the focus should always be on it. I've noticed if I click on say a push button, then the focus is moved to this button which means the focus is no longer associated with OpenGL widget. Clicking the widget by the mouse is not changing the focus. One of the solution is to turn off the focus for all widgets except the OpenGL widget in the GUI as follows
ui->processButton->setFocusPolicy(Qt::NoFocus);
ui->quitButton->setFocusPolicy(Qt::NoFocus);
ui->clearButton->setFocusPolicy(Qt::NoFocus);
ui->textEdit->setFocusPolicy(Qt::NoFocus);
ui->groupBox->setFocusPolicy(Qt::NoFocus);
if I have many widgets, then this solution is annoying especially if I add widgets later on. My question is is there a solution to set the focus on a specific widget?

Your solution is fine, you just shouldn't be enumerating widgets manually:
// C++11
for (auto widget : findChildren<QWidget*>())
if (! qobject_cast<QOpenGlWidget*>(widget)) widget->setFocusPolicy(Qt::NoFocus);
// C++98
foreach (QWidget * widget, findChildren<QWidget*>())
if (! qobject_cast<QOpenGlWidget*>(widget)) widget->setFocusPolicy(Qt::NoFocus);

Related

Qt::Popup window flag and parent widget mouse event

I want to create QCombobox with tree models support where each child list displayed in new window just like it happens in QMenu (without using QTreeView) but with QListView display features. All is going fine except one small thing: i lose all mouse events for parent widget when child popup is opened. So my question is how to keep taking mouse events during child popup is opened?
In qt basic example Window flags widget with Qt::Popup lose mouse event too. But in QMenu submenu been closed when mouse leave from parent action field. I mean this behaviour is supported by Qt and may be reached from the mox but it's hidden and I can't find a way to give it.
Qt::Tool or Qt::ToolTip modes give me necessary behaviour for parent widget but child widgets do not track mouse events for it's self

Is there a way to attach or anchor two QWidgets together?

I'm getting started with Qt and decided to build a full-screen text editor. I want to have a button (button with arrow in screenshot) attached to a QDockWidget which opens and closes it so the button is always visible to the right side of the screen and stay anchored to it when dock is visible or resized.
My current app is a simple fullscreen textEdit set to centeralwidget in Mainwindow.
I haven't found a way to do this yet with layouts or existing addAnchor() functions so any help or direction is appreciated.
You can achieve what you want by using a container for your text edit and the button. A QWidget instance can be used as an "invisible"*** container for other widgets.
So in Qt Designer you add a widget as a central widget of the main-window, inside this widget you add the text edit and the button, then you set a vertical layout for this container widget.
Don't forget to restrict the docking widget to only dock to the right side, you can do that with: dock->setAllowedAreas(Qt::DockWidgetArea::RightDockWidgetArea); //assuming dock is the pointer to your QDockWidget.
In case you want the dockWidget to be able to dock to any side and the button to follow, you can do that too, but it get a little bit more complicated. Basically you need to connect a slot to dockLocationChanged of your dockWidget and based on where it's docked you need to set-up a new layout for the container widget to be vertical or horizontal and the order of the textEdit and the button based on the side the dock happened.
LE:*** you will most likely need to set the margins you want, since both the widget and it's layout can have them and the actual content might have higher spacing than you want.

Modifying the QDockWidget default snap locations?

I am trying to model a UI from a wxWidgets application to QT. However, in the original application they have Dock Widgets that can snap in place and move around except for occupying the main window.
Every box appears to be a dock widget except for the main window. And if I want to move the Datasets window (top left) to the right of the Output Adjustment window I can:
So now my goal was to try and get the UI in QT to at least accomplish the dock widgets on the left side of the main widget. Which in my case, I was able to at least get the width and the height with some trouble to show up the same. However, I cannot create a QDockWidget like the Output Adjustment and have it snap next to the others. And the other problem comes when I try to move a dock widget it will not snap to the right or the left of the other widgets.
This is where I have my problems. I cannot snap it to either side of the dock widgets. Is this something that will need to be hard coded? I know I have seen other examples online that look awfully similar to this layout. However they are all hard coded. And it would be a lot more simple if I could just use the creator to add the sliders and toolbars as time goes on. And if it is not something I have to hard code, how do I modify the locations on where my widgets can snap? I tried to make a grid layout, however the widgets do not go into the grid.
By enabling dock nesting in your main window you can achieve a more flexible placement of the dock widgets, including positioning the dock widgets side-by-side. In Qt Designer, select the main window and in the Property Editor panel mark the dockNestingEnabled check box (present in the QMainWindow section). Alternatively, you can achieve the same result by calling the method QMainWindow::setDockNestingEnabled in your code.
If you want your application to start with dock widgets arranged side-by-side as in your reference application, you have to resort on the method QMainWindow::splitDockWidget. For example, you can create an initial arrangement in Qt Designer such as the one depicted below.
Next, you can rearrange the dock widgets in the main window constructor code,
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// Changes the dock widgets arrangement.
splitDockWidget(ui->dock1, ui->dock3, Qt::Orientation::Horizontal);
splitDockWidget(ui->dock1, ui->dock2, Qt::Orientation::Vertical);
}
which would produce the result below.

Qt dock neighbour widget behaviour

I have two Qt widgets in the window. One of them is QDockWidget, and another one is just QWidget.
When I drag the QDockWidget, the default behaviour of the another widget is moving without changing its size. And I want it to fill the whole window except dock widget, and to change its size programmatically when I drag QDockWidget. Hwo to do it better?
The solution was to set container horizontal policy as "fixed"

How does a Qt custom widget notify ScrollArea parent about change of view

I'm writing an image viewer as a custom Qt widget (see: https://github.com/dov/Qviv) and I now got stuck on the question of how to make my widget notify a parent QScrollArea of changes in the view port, and thus to tell it to move the scrollbars. E.g. if the image viewer changes the zoom factor as the result of a keypress then the scrollbars need to change their page size.
One way of doing it would be to have the widget explicitly check if the parent is a QScrollArea and then make an explicit call to its methods to notify it on any changes.
Of course I also need to connect the changes of the ScrollArea to the internal view of the image, but that is a different question. And I need to cut the infinite recursion where the widget reports changes to the scrollbar that report changes to the widget etc.
Edit 20:15 Wednesday (GMT/UTC) trying to clarify to Vjo and myself what I need.
What I am trying to achieve is the equivalent of a Gtk widget that has been assigned a pair of GtkAdjustment's that are connected to a horizontal and vertical scrollbar. In my widget GtkImageViewer, that QvivImageViewer is based on, whenever I change the view due to some internal event (e.g. a keypress) I update the GtkAdjustment's. The scrollbars are connected to such changes and are update accordingly. GtkImageViewer also listens to the GtkAdjustment changes, and thus if the user scrolls the scrollbars, the GtkImageViewer is updated with this information and can change its view. My question is whether there is anything similar to GtkAdjustment in Qt that you can connect to for changes, and update in which case the update will be propagated to all the listeners?
Thus I don't expect the ScrollArea to be part of QvivImageViewer, but if the user has placed QvivImageViewer within a ScrollArea, I want bidirectional communication with it so that the scrollbars reflect the internal state of the widget.
The simplest is to send the QResizeEvent event from your widget object to the QScrollArea object.
I finally downloaded the Qt sources and investigated how QTextEdit does it. What I found is that QTextEdit inherits the QAbstractScrollArea on its own, and thus the scroll area and the scrollbars are part of the widget. This is different from Gtk, which uses a higher level of abstraction, through its GtkAdjustment's that are used to signal changes between the scrollbars and the widget. The Qt model is simpler and this is the way that I will implement it in my widget.
It's been a while, but I ran across this same issue.
You can inherit QAbstractScrollArea if you'd like, but QScrollArea will work as well.
Your custom inner widget (i.e. the one that you are scrolling), should do the following when its size changes:
void MyCustomControl::resize_me() {
// recompute internal data such that sizeHint() returns the new size
...
updateGeometry();
adjustSize();
}
QSize MyCustomControl::sizeHint() {
return ... ; // Return my internally computed size.
}
I was missing the adjustSize() call, and without it the QScrollArea will ignore size changes of the internal widget.