Positioning QlineEdit on a QWidget without Layout Manager



  • Hey.
    I am trying to have a QLineEdit on top of a QWidget, on top of a QDialog, where the QDialog is installed with a Layout Manager, but the QWidget is not.
    Something along the line of this:

    0_1547139446196_48953763-4539-448e-ac99-5dc833110cc5-image.png

    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:
    0_1547140072638_71917820-53a4-4275-b729-36619ac1371e-image.png

    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:
    0_1547140212878_f9011179-2f3c-4eba-a012-ca3333ab2f7d-image.png

    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.


  • Qt Champions 2018

    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.


  • Lifetime Qt Champion

    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 a LineEdit (subclass of QLineEdit), and I want to be able to place QLabels above that LineEdit, where the QLabels have uneven space between them, which can be changed in a button-click.

    Example of what I mean:
    0_1547197357656_dc0885eb-8f3e-469d-a354-67e9622b0221-image.png
    (blue arrows indicates spacing, "L" means QLabel)

    Now, say some button was clicked, and Widget might possibly be changed to that:
    0_1547197474060_55b5926c-7420-4542-86d2-711f725eae22-image.png

    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 the Widget 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.


  • Qt Champions 2018

    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...)


  • Lifetime Qt Champion

    @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 ?


  • Qt Champions 2018

    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 put QSpacerItem wherever the blue arrow appears...

    Thanks for the help!


  • Lifetime Qt Champion

    @Absurd
    Hi, what does the labels represent?



  • @mrjj
    The labels represent "Fields" in a "DWORD" (32-bit Register):

    0_1547224018160_c34650f2-916a-4fbc-abb8-2ed080fa19b1-image.png

    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 a QLabel (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 being QLabels, 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 of QLineEdit), of width W points.
    The DWORD's "Fields Layout" (not to be confused with Qt's Layout Managers) is a QVector 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, and int 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 over fieldsLayout[i].second * W/32 points, and be positioned above its corresponding bits in the DWORD.

    Something along the line of:
    0_1547234103380_1b759fc1-8760-4550-b6f9-71d29a7bc6d5-image.png

    Maybe I don't even need QSpacerItems? Maybe all I need is making sure that each QLabel spans over the correct amount of W/32?
    If so, how can that be achieved?

    Please advise.

    Thanks!

    CORRECTION
    I don't want the QLabel to span over the correct amount of W/32 (I just realized it's easy - all I need is to set the QLabel to a fixed size of fieldsLayout[i].second * W/32), but rather I want it to be positioned in the center of the correct amount of W/32:

    0_1547237412241_ba98d0ee-1bd1-4309-8529-72f9449eacc3-image.png

    (The QLabel should take the minimum size it needs to display the text, and to be in the center of fieldsLayout[i].second * W/32 space)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.