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.
Related
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 have a full size QGLWidget which paints the application background using QPainter (might change to native openGL commands in the future).
On top of this QGLWidget I use QWidgets (non-GL) for the user interface elements. These are, for example, QLineEdits and QPushButtons. I put them into a custom painted QWidget which uses semi-transparent background painting. The paintEvents of the QLineEdit and QPushButton are overwritten and use semi-transparent backgrounds, too.
The whole UI should look like the following (This is a screenshot where I disabled OpenGL and used QWidget instead of QGLWidget for the background. Note the semi-transparent top bar which also draws a shadow (within its own region)):
When the QLineEdit has the focus, it should have a higher opacity but still not fully opaque:
So now, with OpenGL enabled (The background then is a QGLWidget), the semi-transparent widgets above don't paint on top of the background but on (it seems to be) uninitialized data. The image shining through the top bar is sometimes the whole window itself and sometimes other windows currently being on my desktop.
This currently looks like the following (In this screenshot, the data on which the semi-transparent painting operations are painted on seems to be an image of the widget itself, having an offset.):
When I wrote text into the line edit (here: "This is some text which has been there before!"), removed it and set the focus back to the background widget (so the magnifier icon and the placeholder text appear), the previously painted things still shine through (Note that the visible border should not be visible anymore, but also still shines through):
So the problem is: Instead of being painted on top of the underlying widgets, the semi-transparent widget is painted on top of the old results, initially being something like "uninitialized memory".
Why does this happen? How can I solve the problem?
Things you should know before answering:
The background scene is a composition of tiles which are rendered off-screen. So it can be painted very fast and repainting of the background for every little change of the overlay isn't problematic.
The top bar is a custom QWidget with manual painting and arrangement of the contained two widgets (the button and line edit).
The two widgets overwrite the paintEvent, only draw their own (semi-transparent) background when they have focus and don't use frames already provided by Qt. So the white border in the second screenshot is drawn in my custom paintEvent.
I want the background and the composition of overlay widgets to be separately implementable. The background is an AbstractMapView which has some concrete map view classes. The whole window is an AbstractView (there are multiple concrete views, too), which contains both a concrete map view and the overlay widgets, composed in a way itself decides. Therefore, I don't want the logic of the overlay widgets to be part of the underlying map view. (I hope you understood this, as it is a bit complicated.)
This sounds like an issue where the GL content (i.e. your background aka the QGLWidget) is not in the Qt context. While I'm not a pro on GL painting with Qt, you may want to look at this discussion regarding GL painting and a QLabel for some direction/potential hints.
http://www.qtcentre.org/threads/40335-QLabel-on-top-of-a-QGLWidget-background-issue
In short, we here at the office use OpenGL painting and offscreen rendering of maps and it's very important to make sure Qt is aware of the pixels so your foreground widgets can have the semi-transparency applied to their backgrounds.
The particular product we use also renders the map in tiles and supports providing the GL output in a buffer (i.e. it's call a snapshot and is provided as a bitmap) at which point we use the paintEvent of a regular QWidget to paint the buffer so that the painted pixels are in Qt context.
You can define a Qframe with Qt::SplashScreen flag as the search box and set its opacity. Put your widgets inside it such as the search textbox and positon it where it should appear on the mainwindow. It will also be a good idea to reposition it as the mainwindow is moved or resized overriding its moveEvent.
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.
For those of you who haven't been reading my Qt questoins, I am learning Qt for a project. I have only limited experience with GUI design at all, and not in Qt.
I've got a horizontal layout that I want to populate with some buttons. I can feed these buttons in just fine, but my formerly-square buttons are stretched horizontally to take up more space.
I want to let the layout manager determine the best way to size these buttons, but I also want their original proportions to remain intact. For instance, if I start would with 32X32 buttons that need to shrink to fit all of them in the layout, I want them to shrink proportionally so that the width to height scale is maintained. 20X20, 16X16, 12X12 would all be just fine, but 24X16 would be an example of dimensions that are unacceptable.
I've tinkered with size policies on the buttons and stretch options. I'm not seeing, even after reading the QPushButton and QHboxLayout classes how to do this. How is it accomplished?
Thanks.
As long as I understand the question correctly, I think what you want is QBoxLayout::addStretch(). This will add a spacer object that fills the unused space. So the buttons will have their ideal size and the spacer will fill the rest. You can try experimenting with this in Designer, it's easier than the write/compile/run cycle.
You should take a look at the answers to this question. This is a recap of my answer there.
You need to create a custom derivative of QLayoutItem, which overrides bool hasHeightForWidth() and int heightForWidth( int width ) to preserve the aspect ratio. You could either pass the button in and query it, or you could just set the ratio directly. You'll also need to make sure the widget() function returns a pointer to the proper button.
Once that is done, you can add a layout item to a layout in the same manner you would a widget. So when your button gets added, change it to use your custom layout item class.
I haven't actually tested any of this, so it is a theoretical solution at this point. I don't know of any way to do this solution through designer, if that was desired.