I'm making a widget that consists of a QGridLayout which maps out a QSlider and a few QPushButtons. In my widget, I'm able to position the buttons against the rightmost side of the container widget. The slider, however, is a bit more problematic.
I want the slider to be positioned such that the groove and handle extend all the way over to the point where the handle can be positioned flush against the widget boundary. I've tried a few things including changing the stylesheet margin properties for the groove and messing with the functions provided by QGridLayout, but I can't seem to figure out how to accomplish this.
Does anyone have any suggestions?
I discovered that there is no easy, reliable method of ensuring that a QSlider be dynamically sizeable within a QGridLayout.
The best way of implementing a widget like this that I've found was to place the labels using QWidget::move(x,y) and using coordinates relative to the slider's size/position.
Related
So, I have a QFrame with its layout set as a QGridLayout.
Within this layout I have tiles in rows of 16 which represent something of a palette.
I want this grid of tiles to be separated by lines, like a grid should be. I can do this easily with the tiles' paintEvents.
However, the obvious problem is that between the tiles, the lines are doubled up. When I scale this up for other applications, the difference becomes even more noticeable.
So, is there a way to create a gridline overlay for my QFrame? I have considered converting the whole thing to a view/scene solution, and using drawForeground, however this seems like a completely inappropriate use of the paradigm.
Thanks for any assistance!
Put the QFrame into a QGridLayout, then put a custom QWidget with transparent background and paintEvent that paints the grid on top of it (same QGridLayout position).
Or since you already have a QGridLayout, just put the custom QWidget in that, above the tiles, filling the entire grid.
A side note, are you sure you want QFrame there, or if just QWidget would do? Just saying, because with QFrame you get that 1990's look into your UI... If you do want that then go ahead, just saying.
Background: I need Command Link-like controls. Normally, I would use Qt's builtin QCommandLinkButton, but in this case I need to also support Right-to-Left layouts. Regrettably, QCommandLinkButton doesn't seem to respect Qt::RightToLeft when set explicitly via setLayoutDirection. There also doesn't seem to be a way to override the layout direction via style sheets.
I tried to work around this issue by using QPushButton: I instantiated QPushButton and replaced its contents with a custom layout containing two labels stacked vertically. This did not work because QPushButton refused to expand horizontally.
Failing to make QPushButton instances work, I decided to try sub-classing it. No matter what I tried (overriding sizeHint, setting vertical sizePolicy to expanding, resizeing explicitly, etc) the button refuses to grow more than 30 pixels high.
If I change QPushButton to QWidget, the new widget grows normally.
The question: How can I force a QPushButton to grow vertically and fit its inner widgets? If this is not possible, what are my options for a button-like widget that is both visually and behaviorally consistent with QPushButton and other "native" controls?
I managed to get the button to grow normally by setting the maximum height to 16777214 (instead of the default 16777215), and then setting the content margins of the button to 10.
Perplexingly, the default maximum height of a QPushButton should be plenty, but for some reason it refuses to grow past 30 pixels unless the maximum height is explicitly set to something else.
Place the button inside a layout and set its vertical size policy to Maximum.
So I currently have got a custom widget, and I want to add them to the main window after clicking a button. I would like to add them all to one fixed position first and then I will be able to drag them wherever I like. I am able to create and display these custom widgets with help of QHBoxLayout or QVBoxLayout, but in this case they will not be in the same position after I create them. Any help will be appreciated!
As the names suggest, the QLayout classes manage the position and geometry of the items added to them. You cannot move (eg. drag) an item out of a layout w/out first removing it from the layout (QLayout::removeItem() and derivatives). For example when you drag a toolbar or dock widget out of a QMainWindow it goes through all sorts of machinations to remove it from the MW layout, change the widget's window flags, remember the old position in the layout, and so on. And the reverse to dock it again.
To do what you describe (drag widgets arbitrarily around a window) you would need to not use a QLayout and position the widgets manually by specifying a QWidget::setGeometry() for example. After initial position, and assuming the user has some way to grab the widget (title bar or drag handle you made, etc), you'll probably still need to manage their positions, for example if the main window is resized (if you care about keeping them contained). Essentially you'd have a bunch of separate widgets acting as individual windows and probably need some way to keep track of them.
I don't know what kind of widgets you're talking about, but one option may be a QMdiArea which lets the user drag windowed widgets around, tabify them, save/restore state, and so on.
For more flexibility you could also look into the Qt Graphics Framework. The graphics scene has a lot of features for user-movable items/widgets, keeping track of them, and so on. It is probably the most flexible method overall, and you can also use regular QWidgets inside a graphics scene.
A couple other Q/A about arbitrarily positioning widgets (I'm sure there are more to be found):
QPushButton alignment on top another widget
How to keep Push Buttons constant in relative to change of Label Size in PyQt4
I've inherited my class from QWidget. Basically no extra code, just changes with the editor.
The way I use it:
focusWidget = new FocusWidget(this); //this points to the mainWindow
focusWidget->show();
focusWidget->hide();
Now the widget appears like this (it now looks ugly because of the bad 4k scaling), at the top left corner of the mainWindow.
I intend to use my application mostly full screen.
Is this usage correct?
How can I make it a floating widget?
If I want multiple widgets like that, how can I control their position?
I'm working on a simple widget system, and I'm implementing some containers right now.
Here's the situation I find myself in:
I have a Widget base class, a Container class, which is a widget that can contain other widgets, and several widget sub classes like Button.
I have two types of container: Container itself, which positions children absolutely, and Box, which will stack widgets next to each other, either horizontally or vertically.
Each widget draws itself at x=0, y=0. Therefore, containers need to add an offset to the drawing context before the widgets are told to draw themselves.
Each widget does its own hit testing based on its x/y position.
So far, it works fine. But it falls apart now that I'm implementing Box: What I do is that I overwrite the drawfunction inherited from Container to draw them all in next to each other, instead of based on their x/y position. Quite simple.
But event handling is totally off now, as the widget's x/y position has become meaningless.
I think I have two options:
Have the widget do hit testing at position x=0, y=0, like drawing. Then recalculate the mouse position to match that in Container.
Make each layout set x/y for its children, and make children draw themselves at their x/y position again. No more offsets for the drawing context
The first one is a bit ugly, I think. The second one is pretty complicated to implement, since I need to react to position changes in widgets.
How to other widget systems like Qt, Gtk and wxWidgets generally tackle this? I've looked at the source of some of these, but can't quite figure that out, it's too sophisticated. I don't have any resizing or packing issues to consider.
You are trying to implement your own layout system. You should expect it to be difficult.
I would advise against the first method. The x,y coordinates of a widget are not only used by the widgets themselves, but by anyone outside of the container who wants to do something with the widget.
The second solution is what I've chosen to implement custom widgets made of several smaller widgets and it's not that hard to put together if you don't want too many features.
Just get the widgets when they are added to your container, set their position to the current free spot, and move on to the next.