Positioning QlineEdit on a QWidget without Layout Manager
-
Hey.
I am trying to have aQLineEdit
on top of aQWidget
, on top of aQDialog
, where theQDialog
is installed with a Layout Manager, but theQWidget
is not.
Something along the line of this:My first attempt was this:
main.cpp:int main(int argc, char* argv[]) { QApplication app(argc, argv); Dialog dialog; dialog.show(); return app.exec(); }
Dialog.cpp:
Dialog::Dialog(QWidget *parent) : QDialog(parent) { Widget* widget = new Widget(this); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(widget); setLayout(layout); setWindowTitle("Tester"); }
Widget.cpp:
Widget::Widget(QWidget* parent) : QWidget(parent) { QLineEdit* lineEdit = new QLineEdit("Default Text", this); QVBoxLayout* layout = new QVBoxLayout; layout->addWidget(lineEdit); setLayout(layout); }
This gave me the exact desired result:
How can I achieve the same result, without installing Layout Manager on the QWidget?
I tried changing the Widget to the following:
Widget::Widget(QWidget* parent) : QWidget(parent) { QLineEdit* lineEdit = new QLineEdit("Default Text", this); //QVBoxLayout* layout = new QVBoxLayout; //layout->addWidget(lineEdit); //setLayout(layout); lineEdit->setGeometry(9, 18, lineEdit->size().width(), lineEdit->size().height()); }
But that failed horribly:
Now I have to resize the window to see the
QLineEdit
...What does the
Widget::setLayout()
does that I am not doing? Why is using the Layout on the Widget affects the Dialog dimensions (which is the parent) ?Thanks.
-
Because when you set a proper layout the sizeHint() of the Widget can return the correct sizes. If there is no layout, sizeHint() can't do much.
-
Hi
can i ask why you want to do it manually with code instead of a layout ? -
@Christian-Ehrlicher So what's the solution? overriding sizeHint() at
Widget
?@mrjj the code snippet I've been putting above isn't really my operational code, but only some small demo that exhibits my problem.
In reality,
Widget
is an object that needs to have its children laid out on it in a way that doesn't conform to anything that the "conventional" layouts can provide (not Vertically, nor Horizontally, and not even in a Grid).
In reality,Widget
has aLineEdit
(subclass ofQLineEdit
), and I want to be able to placeQLabel
s above thatLineEdit
, where theQLabel
s have uneven space between them, which can be changed in a button-click.Example of what I mean:
(blue arrows indicates spacing, "L" means QLabel)Now, say some button was clicked, and
Widget
might possibly be changed to that:
So, I need the flexibility of changing spacing between the Labels - with floating-point (
QPointF
) precision.
I couldn't find any Layout that can meet these requirements, so I figured it will be best to just control the position of the Widgets onto theWidget
myself (recalculating the desired position of Labels with every button-click).WDYT?
Does that sound reasonable?
Can you suggest some better way to do it?Thanks for the help.
-
If you want spaces between widgets take a look at QSpacerItem
-
I have been familiarizing myself with the
QSpacerItem
when I used it in some other place in my code, however, I mentioned that I'll need to lay out widgets in a floating-point precision, which I am not sure can be achieved using that method.
I'll try to see if giving up on the precision requirement is possible (I remember trying to use integer precision and it wasn't quite good for me, but I did so many experiments I might be wrong...) -
I have been familiarizing myself with the
QSpacerItem
when I used it in some other place in my code, however, I mentioned that I'll need to lay out widgets in a floating-point precision, which I am not sure can be achieved using that method.
I'll try to see if giving up on the precision requirement is possible (I remember trying to use integer precision and it wasn't quite good for me, but I did so many experiments I might be wrong...)@Absurd
Hi
the x,y of a Widgets are ints so not sure QPointF would do you any good.
Also there is only fixed amount pixels to be placed on anyway.you cannot place it like 45.123 pixels in . only 45.
So i wonder if plain Widgets are the way to go ?
-
And how does a user see if the widget starts at 42.2 or 42.3 ? This constraint is not really useful...
-
Fair enough...
So, I will try to putQSpacerItem
wherever the blue arrow appears...Thanks for the help!
-
@mrjj
The labels represent "Fields" in a "DWORD" (32-bit Register):This is what I currently have, unfortunately, what you see in that picture above (Fmt/Type/R etc...) are not labels, but rather a draw created by
QPainter::drawText()
, and I don't like it being drawn, because when it's aQLabel
(instead of a painting) it can be interactive - accept events, emit signals and even display tooltips easily...EDIT
btw, the frame and the "fields markers" in grey are also painted. It was easier to just draw this text while I am drawing the markers.
Now with the Fields beingQLabel
s, I need to make sure they will be placed exactly between two "fields markers"... -
As it turns out - using
QSpacerItem
for this task is not so trivial, at least not to me...
At this point, you probably figured out what I am trying to do.I have a DWORD (which is actually a
LineEdit
- a subclass ofQLineEdit
), of width W points.
The DWORD's "Fields Layout" (not to be confused with Qt's Layout Managers) is aQVector
describing the breakdown of the DWORD:typedef std::pair<QString, int> Field; typedef QVector<Field> FieldsLayout;
Where the
QString
is the name of the Field, andint
is its bit-size.Assume that an instance of FieldsLayout always sums up to 32. In other words:
// let 'fieldsLayout' be an instance of FieldsLayout int sum = 0; for (int i = 0; i < fieldsLayout.size() i++) sum += fieldsLayout[i].second; assert(sum == 32); // this assertion never fails
Now suppose 'labels' is an instance of
QVector<QLabel*>
:QVector<QLabel*> labels; for (int i = 0; i < fieldsLayout.size() i++) labels.push_back(new QLabel(fieldsLayout[i].first))
Given the above, my goal is to have
labels[i]
span overfieldsLayout[i].second
* W/32 points, and be positioned above its corresponding bits in the DWORD.Something along the line of:
Maybe I don't even need
QSpacerItem
s? Maybe all I need is making sure that eachQLabel
spans over the correct amount of W/32?
If so, how can that be achieved?Please advise.
Thanks!
CORRECTION
I don't want theQLabel
to span over the correct amount of W/32 (I just realized it's easy - all I need is to set theQLabel
to a fixed size offieldsLayout[i].second
* W/32), but rather I want it to be positioned in the center of the correct amount of W/32:(The
QLabel
should take the minimum size it needs to display the text, and to be in the center offieldsLayout[i].second
* W/32 space)