Qt: Tab Icon when QDockWidget becomes docked - qt

Qt's QMainWindow has a ability to dock windows derived from QDockWidget. It also would put one on top on the other if few of them are stacked, producing a tab bar. Whenever a QDockWidget's state changes a signal topLevelChanged() is emmitted. At this point I would like to get access to underlying QTabWidget to set an icon for a a newly added tab. How can I do it? My patience is over trying to dig the answer out from Qt's documentation and source code. Thank you in advance.
So icon I want to be on Contents/Index tabs.

Once at least one dockwidget has been tabified, the main-window will create a QTabBar to provide the dock-tabs. Each dock-area can have its own tab-bar. These tab-bars will become children of the main-window, so you can use findChildren() or children() to get references to them.
The main difficulty will be in finding which dock-widget belongs to which tab and in which tab-bar. If the dock-widget window-titles are all unique, you can just search using the tabText(). Otherwise, you might be able to use the tabData(), which Qt sets internally to a quintptr from the dock-widget.
Once you have the correct tab, you can of course use setTabIcon() to add your icon. But note that every time a dock-widget is untabified or moved to another tab-bar, the icon will be lost.

Related

Qt desktop application

The Qt desktop application I am required to develop has the following GUI:
The application window is split into 3 parts -
left-side window - has a stack of clickable menu items one below the other. Clicking on each item will show up the corresponding UI elements on the prominent right-side window which is much bigger.
right-side window - contains UI to display some data depending on which menu item is clicked on the left-side window. Each left-side window menu item has a different corresponding right-side window UI.
top (header) window - contains some company "brand" related graphics and also a panel to select a serial port from a list along with graphics to represent connect/disconnect status.
How do I develop this kind of UI? What Qt classes should I be using? I'm a beginner to Qt and would deeply appreciate any help. Thank you.
I'd suggest starting in Qt Designer or Qt Creator to create your UI by dragging and dropping different kinds of objects. Qt Designer is a standalone form designer where Qt Creator is full development environment that also includes the functionality of Qt Designer. Using the form designer is a lot easier, particularly when starting out, than creating widgets programmatically.
There's multiple ways to do the list of items on the left. You can use a QListWidget or a series of individual QPushButton instances, one per option. If the list of items changes, then managing the QListWidget content is going to be easier than instantiating a QPushButton for each item, but you might like the appearance of the QPushButton better. It just depends on what you want.
For the right side, look into QStackedWidget. It's specifically designed to display a stack of content where only one item is available at a time.
For the top panel, again, use the form designer to create the layout. You can store an image in a QLabel. A QComboBox might be what you want for the list, or again, you may want a QListWidget. It just depends on what appearance and user experience you're looking for. For the connect/disconnect status, you can use a QLabel and change out the graphics as the status changes.
You'll need to learn about slots and signals; those are crucial to anything Qt-related.

How do I get rid of this anonymous draggable bar in qtcreator?

I wrote a program in qt creator, but it includes this anonymous draggable toolbar that I would like to get rid of. It does not show up in design mode. If I right click on it, it gives me a menu with a checkbox, which I can select to get rid of it while the program is running. What is this bar? How do I get rid of it? If I knew what it was, I could just programmatically tell it to hide when the program loads.
Here are some screenshots demonstrating this weird problem. In the first screenshot, the mouse is pointed at the bar. The second one demonstrates the right-click context menu. The third one shows the program without the bar. The box can also be dragged out of the program's window entirely. I can also upload a picture of that, if necessary.
(mouse pointing at bar)
(bar has a right-click menu!)
(bar is gone)
First things first, make sure you haven't added the toolbar yourself in code (the Designer form is nothing magical, it just generates normal Qt code to ui_XXXX.h, which you should totally study, so you understand what is really happening "under the hood").
Second, perhaps that is the main menu bar, not the main tool bar.
Then, on to remove the nasty bar. On the upper right corner of Design view, you have a tree of all items in your UI. Find the QToolBar there. It is probably called mainToolBar. Right click it and remove it there. Or, if you actually have menu bar, then find QMenuBar, probably called menuBar, and remove it instead. Remember to make version control commit (or other backup) before doing this, so you can easily revert changes.
If this fails for whatever reason, and you just want to get it to work, you can always find and delete (be careful about the dangling pointers left behind, set them to nullptr if possible):
ui->setupUi(this);
// a hack: we want to get rid of the toolbar and the menubar,
// but can't remove it from the .ui, so we delete them like this.
delete findChild<QToolBar *>(); // NULL return value is ok for delete
delete findChild<QMenuBar *>(); // NULL return value is ok for delete
Doc links for findChild and alternative findChildren.
What you have there is probably the mainToolBar QToolBar object you get with every QDesigner-created QMainWindow .ui file.
If you want to get rid of it, locate it in your .ui file and just delete it.
But better think twice: you might later decide you want a QToolBar object and (at least AFAIK) there is no way to recreate it in QDesigner...
you must use this code in your constructor.
ui->mainToolBar->toggleViewAction()->setVisible(false);
mainToolBar is my toolbar name.

How to draw something in a tooltip?

I am trying to develop a functionality using Qt which I don't know whether it is possible to implement. Here is the requirement:
When the user hovers over a node (an object derived from QGraphicsItem), a window will be shown near the node, in the window there might be some histograms or buttons that can be clicked to show further information. When the mouse leaves the window, it will automatically close.
I tried to use a tooltip, because it can pop-up near the node and close when the mouse leaves it, but it can only show text. So, it still cannot work that way. I am wondering if there is another way to do this? I did lots of google search, but there is still no answer.
Thanks so much for helping me with this.
If you're ok with using a 3rd party library, Qxt provides a class that provides a tooltip that is QWidget based, which will let you use an arbitrary widget as the tooltip rather than just text.
See: Qxt::ToolTip
you don't have to use tooltip for your app
you can use or call widget or dialog, on hover mouse event
Please refer Qt Example EmbeddedDialog Example, It is advanced, But you can understand how hover Enter/Leaving events are working. I personally prefer don not create instance of Popupdialog for each item, create it if only nesessary. Otherwise create one dialog and pass its reference to all the items through the constructor initialization.
1. These are the API you are intrested on, reimplemet this.
QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) and void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
2. When You create Dialog, You can pass Qt::WindowFlags as Qt::ToolTip.

Drag and drop of QDockWidget between two or more windows

I would like to know if anybody knows if it is possible to drag a QDockWidget from one window to another.
I am developping an application that has a lot of windows. Each of these windows has a specific usage. I want to use QDockWidget because of the automatic rescaling when docking a widget in the main window. But I would also like to have the possibility to have a new dock area in a new window so that I can put together all the widgets related one to each other.
Does anyone have a suggestion?
As far as I know, you cannot drag a QDockWidget from one application to another if they are developed separately.
On the other hand, I think that you can reparent a QDockWidget to another QMainWindow, only if it's part of the same application.
...aaaaand you can always try to intercept the drap/drop events and pass information between the two windows with a protocol of your own: define a new mime type for the drag and define the syntax of the data associated to the QDockWidget. Then, implement the code to analyze the data and reconstruct the contents of the QDockWidget in the target window... not an easy task!

Qt Parent child relationship for independent qmainwindows

Using Pyside, but a general Qt question:
I am building a Qt app with a controlling QMainWindow. From this window the user can open other QMainWindows (or QDialogs) and from some of those she can open more. The user is intended to think of the first QMainWindow as "the app" and the others as lots of different views on more or less the same data.
So I'd like all the windows to be independently stackable so the user can set up the screen to their own requirements. In particular I want the user to be able to bring the first QMainWindow on top if wanted. But I don't really want each window to have its own task bar entry (though I can live with that). Also I would like them to minimise and restore together, and I would like them all to close when the first main window closes.
If I parent them all on the first mainwindow it works nicely except they stay on top of it which is not what I want.
Instead I have it kind of working by making them all independent with parent = None. Then I register them all with the main window and close them all when it closes. But this makes them a bit too independent - they minimise separately and have their own task bar entry.
Am I missing some obvious fix to this? Is there any easy way (a flag?) to stop the children staying on top of the parent?
Or is there some UI guideline that I am breaking by desiring this?
Or is there a cleaner design somehow? I thought of adding a dummy parent that they could all descend from but maybe that's messy. Would that parent need a visual presence? I wouldn't want that.
Suggestions?
You can have as many QMainWindows as you want, or parentless QWidgets. I think the best way to handle your situation is to create your own pseudo parent-child relationship like this:
In your QMainWindow subclass, store a QList of all the QWidgets you want it to manage. Then, again in your QMainWindow subclass, reimplement methods such as QWidget::closeEvent(), QWidget::hideEvent() (for when the window is minimized), and QWidget::showEvent() (for when it is restored) so that it also closes, hides, or shows all of the widgets in its QList. Make sure to also delete them in the QMainWindow subclass's destructor. Now, whenever you create a sub-window, pass the main window a pointer to it not as a normal QWidget child, but just so that it can be added to the main window's QList of QWidgets to manage. E.g.:
MainWindowSubclass::addPseudoChild(QWidget *pseudoChild)
{
myListOfPseudoChildren.append(pseudoChild);
}
Another alternative that hasn't been mentioned yet is populating a QMdiArea with QMdiSubWindows. It doesn't do exactly what you asked for, but it's a pretty clean design nonetheless.
So I thought I would add what I eventually settled upon. This was particularly inspired by the comments of #leemes (Thanks - good stuff) and a little experimentation of my own.
I used the code attached here DetachTabExample
to develop a "Detachable Tab" widget and tab bar. This allows tabs to be dragged outside the main window when they become independent windows. Then if closed they return to the tab bar.
Then I placed all my content in the QMainWindow but in separate tabs. The users can drag the ones they want out on to the other monitor. Seems to be working fine. There are still some extra windows that I have floating but it has cut down the clutter and clarified the structure.

Resources