QToolbar force shrink - qt

Qt toolbars shrink and display an 'extend' button when there isn't enough space.
Is there anyway to create a toolbar pre-shrunk? I want to display just the first label so I can use a large number of toolbars as floatable popup-menus (or a linear dialogboxs ).
I specifically want to use toolbars (rather than dialogs) because they are already created for another app.

Internally a class called QToolbarLayout makes this decision about the "extension" button, based on the size of the space the toolbar is given:
http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/widgets/qtoolbarlayout.cpp#line398
So there's no method or slot for it, beyond setting its size. However, you could make your application persist the toolbar information between sessions via QSettings:
http://doc.qt.nokia.com/latest/qsettings.html#details
http://doc.qt.nokia.com/latest/qsettings.html#restoring-the-state-of-a-gui-application
That would allow your users who wished to work in this style the option of setting it up like that, and let those who didn't like it save their preferred layout as well.

Related

JavaFX nodes - How to make them resizable by the end user?

I am developing a JavaFX application where a class I have developed (extended from javafx.scene.Parent) is created on-the-fly based on what entry the user has clicked in a ListView control.
Just to be clear about this node, it is not created using a layout tool like SceneBuilder, it is created at runtime based on the user's actions.
The constructor for my custom node class creates a VBox and a Label and uses passed coordinates (X,Y) in the constructor method to set its own Layout coords. I then use a custom utility class to make the node draggable. This new node is then added to the main application Pane.
However, I have failed to find out how I can make these nodes resizable by the user. That is, allow the user to mouse over the corner of the node, hold and drag to resize. An operation that all users are used to, no matter what the OS.
Has anyone done anything like this in JavaFX? (My searches on the subject only seem to pull up subjects on the automatic resizing that a parent node does with its child nodes.)
Many thanks,
Ian.
As you can see on the documentation of VBox you can only define minimum, prefered and maximum range, there's not really a way to make it manually resizable.
The only proper solution to solve your problem is to develop your own class to do it, because what you want seems very specific, with your problem description, I don't think use some layouts or panels will do what you exactly want.
I found something that you can use : Dragging to resize a JavaFX Region
This allows you to resize a region, all you have to do after is to put you VBox in this region, but notice in this article that :
Only height resizing is currently implemented.
This code won't work in JavaFX8, you'll have to check the comment to see how it worls in JavaFX8
Hope this helps.

JavaFX Secondary Screen "Always on Top" of All Applications

I've read about using a JDialog to wrap a JFXPanel in order to use JDialog's alwaysOnTop method. It works, but I'm having a small issue with this hack.
Since I'm using this technique to make secondary windows to my main application (popups etc), I need to set them on top of the main window. If I use the wrapper hack to do this, the top panel is "always on top" of everything (including other applications).
Is there a way to put the secondary screen only on top of my application? I don't like the fact that another application can be dragged in between the main window and secondary window of my application.
I suggest not using JDialog and JFXPanel, but only using JavaFX Stages.
Make your secondary screen a Stage and invoke secondaryStage.initOwner(primaryStage) before you show the secondary stage.
From the Stage documentation:
A stage can optionally have an owner Window. When a window is a stage's owner, it is said to be the parent of that stage . . . A stage will always be on top of its parent window.
I believe setting the owner of the secondary stage, correctly fulfills your requirement of "secondary screen only on top of my application".
Update: answers to additional questions from comments
I don't want there to be any interaction with the main stage once the secondary is open (the secondary window must be closed to allow interaction again).
To block input to the primary stage, Before showing the secondary stage, call: secondaryStage.initModality(Modality.WINDOW_MODAL).
You could use APPLICATION_MODAL instead of WINDOW_MODAL if you preferred to block all input to any other of your application windows - which one to use depends on the user experience you want.
There's nothing obvious in the api that would center the secondary screen on the main screen. It just always centers on the monitor, no matter where the main screen is.
This part of the question is a duplicate of Center location of stage. The answer to the duplicate has sample code for performing the centering of the child window.
That's right, there is nothing in the public api around positioning child windows relative to parent windows. I've filed a feature request for this functionality Add helper methods for positioning popups relative to nodes, but the feature request has not yet been implemented as of JavaFX 2.2.
There is a sample project I created to do relative positioning of child dialogs, which might be useful.
Just for centering within the parent, you are probably best off querying the stage location and width before displaying the child and then setting the x and y co-ordinates of the child appropriately when you display it. All of this can be done based on x, y and width properties of windows.
There is also a dialog project in the JavaFX UI controls sandbox which might provides some of the functionality you require so that you don't need to code it yourself.
In time all of the functionality you are requesting will probably end up in the JavaFX core platform, but I don't think it's all quite there yet for JavaFX 2.2.
I agree with jewelsea, but if you need to use JDialog and JavaFX stages (like it was my case), then you can't set your primaryStage's parent or modality.
The only solution i found is to use a little "hack":
I use JNA, Java Native Access API to do my own setAlwaysOnTop() method using User32.INSTANCE.setWindowPos(...) with HWND_TOPMOST parameter.
edit: see microsoft doc
and jna doc

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.

How to update a QLayout and get the new dimensions before returning?

This is driving me nuts. I have a custom menu class that, when set visible, shows a list of items located in a particular folder. When a hardware button is pressed, my application gets the latest list of items, populates the menu with them, and returns.
The menu displaying these items uses a QListWidget filled with custom widgets. Each of the widgets contains one or more QLabels in a horizontal layout, and is created at the time the menu is shown. In order to adjust the text displayed based on the menu width available, I need to get the size of the QLabel AFTER it has been resized according to the layout, but before the menu becomes visible to the user. The problem is, my layout does not get updated until all of the functions constructing my list return.
I have tried QApplication::ProcessEvents() and the layout update functions, but none of them have updated the values of my QLabels before returning. I can set a QTimer when the button is initially pressed, and have it show the menu, update the items, and stop itself, but that seems like a terrible solution.
Any help would really be appreciated! I've spent most of a day on this.
Marlon
I had this exact problem and could not find an answer anywhere on the Internet. Calling Layout.update(), Layout.activate(), or widget.adjustSize() (all suggested in various places) all did not work.
I had a widget with a vertical layout that I wanted to add a QLabel to and then immediately use the size of the QLabel.
The only thing that worked reliably was
layout->addWidget(myLabel);
myLabel->show();
size = myLabel->size();
It would seem that layouts will just not recalculate until you either return from a function and allow the Qt event loop to progress or manually call show() yourself.
How to update a QLayout and get the new dimensions before returning?
Don't. You're not meant to do that. It'll drive you "nuts" because you're doing it backwards. Layout updates are handled asynchronously from the event loop. Instead of getting layout dimensions right away, set yourself up to be part of the system. Some options are:
Implement a custom widget that will interact properly with the layout, growing to fill the available width of the layout. Perhaps all you need is a size policy and a way to elide text?
Make a custom layout that takes the special properties of your use case into account.
You want to call QWidget::adjustSize() on your parent widget. This will force the layout recalculations.
Have you tried using layout()->update(); ?
I've tried many but nothing works for me on Qt 5.15.
Only invented little patch - create timer and get size after 20 msec:
QTimer::singleShot(20, this, [this]
{
const auto height = myLayout->contentsRect().height();
// ...
});

flex expand and collapse icon in Tree control

I am having some trouble with the flex Tree control.
I have a control in my system and of course it is data driven.
I have a group which shows a folder icon and that's fine but it also shows an expand icon when the item has no children.
I don't what it to show the expand icon when the group has no children but I do want to show the folder icon, because it is different entities in my system.
here's an example of what I'm talking about. I still want to show the folder icon, the expand Icon should be hidden in this case only for the child icon.
It's easy to get this problem if you're trying to use a non-XML data provider (e.g. setting the dataProvider property of the Tree to a structure of nested ArrayCollections). In that case, the trick is to give each node a children() function that returns null (as opposed to an empty set) if there are no children.
However, assuming you're using a plain old XMLListCollection, what are you doing to make it display a folder icon at all? If you're giving the node an empty set of children, then once again, the expand icon will be displayed. The list of child nodes must be null. Alternatively, if you set the isBranch property of the node to true, it will display 'incorrectly' as you have it above.
The easiest way to display a folder icon without the expand icons is to just replace all the (really rather ugly) default icons with your own, which gives you complete control of how they appear. What you would do is set three properties: defaultLeafIcon, folderClosedIcon, and folderOpenIcon (good example at Flex Examples):
[Embed(source="folder.png")]
public var iconFolder:Class;
[Embed(source="folder.png")]
public var iconFolderOpen:Class;
<mx:Tree dataProvider="{yourData}"
defaultLeafIcon="{iconFolder}"
folderClosedIcon="{iconFolder}"
folderOpenIcon="{iconFolderOpen}" />
I see you're already using the Silk icon set, which has a rather nice closed folder icon. For some reason it doesn't contain an open folder icon though, but you can just use a closed one or anything else.
You could also just use an iconFunction (Flex Examples again), though I think the approach above is easier for what you're trying to achieve.
If it's none of those problems, give us a bit more detail on the content of your data provider and existing tree properties and see if we can't figure it out then. Hope that helps a bit anyway.

Resources