Strange behavior of margins for Qt controls



  • Hello,

    I have just started using Qt (5.3) and encountered the fact that some controls appears with margins which I cannot control.

    First, I tried to put QLabel and QPushButton right inside QMainWindow

    @window = new QMainWindow;
    label = new QLabel( title, window );@

    In this case label appears with a margin of 12 pixels at the top (see picture).
    QPushButton appears with 1 pixel top & left margins.
    But if I insert QFrame with a border, it appears without any margin.

    !http://i.stack.imgur.com/Dsll7.jpg()!

    So the margins seem to be attributes of QLabel and QPushButton.
    BUT:

    When I tried to add extra QFrame between windows and controls:
    @window = new QMainWindow;
    frame = new QFrame(window );
    label = new QLabel( title, frame);
    @

    I had got different picture:
    QLabels top margin had shortened to 1 pixel
    QPushButton 1 pixel margins remained intact, but the height of the button had changed

    I have tried:
    setStyleSheet( "padding:0px" )
    and
    setContentsMargins( 0, 0, 0, 0 )

    for all elements, but without any success.

    Any help would be greatly appreciated


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    What are you trying to achieve ?

    It's not really a margin question it's how the widgets are drawn. Since you just give you widget a parent, they are positioned (IIRC) at the top left point available. You should have a look at the layout system of Qt to build custom widgets.



  • I am trying to port existing application from Win32 to Qt.
    Application uses lots of UI forms automatically generated from XML description, so am porting an engine that creates controls on the fly.

    I started with migrating of Win32 logic to Qt - placing label/button/etc. as a child of a window, or as a child of a panel inside a window. But this does not seem to be the Qt way ))

    What I need is to assign a widget exact size and positions relative to its parent (or to client area of a window), because my application uses its own layout mechanism.

    What is the best way to do it?


  • Lifetime Qt Champion

    You could consider creating your own layout manager based on QLayout, this way you won't need to rewrite the mechanism for each widget.



  • Things are still unclear to me.
    First I added central widget to my windows, as it was sugested on forums:

    @QWidget *central;
    central = new QWidget( window );
    @

    and added button to the central widget.

    This just reduced the height of the button to 21px (it should be 23px on Windows). But button->size() returns 23px height - so here is my mysterious "margin".

    Then added a layout:
    @layout = new QVBoxLayout( central );
    central->setLayout( layout );
    layout->addWidget( button );
    @

    But this just put the button to the center vertically.

    So I suppose that the problem of margins - is in how the button draws itself, rather than in positioning.
    And I think writing my own layout manager will event make things worse, because I do not understand the principles.

    So my new question is: How to create a button with correct height of 23px exactly at the top left corner of the window? Is it very difficult task?


  • Moderators

    Hi,

    [quote author="Boris L" date="1406564599"]some controls appears with margins which I cannot control.

    First, I tried to put QLabel and QPushButton right inside QMainWindow

    @window = new QMainWindow;
    label = new QLabel( title, window );@

    In this case label appears with a margin of 12 pixels at the top (see picture).
    QPushButton appears with 1 pixel top & left margins.
    But if I insert QFrame with a border, it appears without any margin.

    !http://i.stack.imgur.com/Dsll7.jpg()!
    [/quote]Those aren't margins.

    Your first QLabel looks like it has a big top margin simply because:

    • It is taller than the second QLabel, and
    • The labels' text are centered vertically.

    (You didn't specify what size the child widgets should be, so Qt gave them arbitrary sizes)

    To see the true rectangle covered by the QLabels, colour them:
    @label->setStyleSheet("QLabel {background-color : red;}");@

    [quote]This just reduced the height of the button to 21px (it should be 23px on Windows). But button->size() returns 23px height – so here is my mysterious “margin”.[/quote]The 1-pixel "margin" is actually part of the button's border, according to the native Windows 8 style. I created a Windows Form project in Visual Studio and created a button. The margins are 0 everywhere and it says the button is 75x23, but the dark grey border is only 73x21:

    !http://i.imgur.com/gQiEKh9.png(Windows Form Button)!

    !http://i.imgur.com/y0ttxPD.png(Button Properties)!

    You can override the native style to get a button without the invisible 1-px border:

    @button->setStyleSheet("QPushButton {background-color : red;}");@



  • Thank you, JKSH. Things are now more clear for me.

    I have never worked with WinForms, and I am a bit confused with that fact that it provides a button with such style (which Qt in turn emulates).
    Because in Windows UI buttons have default height of 23 px (dark gray border), rather than 21 px dark gray border + 2 px invisible area. See, for example Windows "Run" dialog, or any other dialog.
    The same is true for original Windows API: If I create a "BUTTON" window with 23 px height, it will be of 23 px dark gray border height, without any invisible area.

    So I am back with my original question: Is it possible to get rid of this invisible area?

    [quote author="JKSH" date="1406649850"]Hi,
    You can override the native style to get a button without the invisible 1-px border:

    @button->setStyleSheet("QPushButton {background-color : red;}");@[/quote]

    I guess you pasted it form the previous example. I am not sure I can do it with CSS.


  • Moderators

    You're welcome :)

    [quote author="Boris L" date="1406693543"]I have never worked with WinForms, and I am a bit confused with that fact that it provides a button with such style (which Qt in turn emulates).
    Because in Windows UI buttons have default height of 23 px (dark gray border), rather than 21 px dark gray border + 2 px invisible area. See, for example Windows “Run” dialog, or any other dialog.
    The same is true for original Windows API: If I create a “BUTTON” window with 23 px height, it will be of 23 px dark gray border height, without any invisible area.[/quote]I agree that it's an unintuitive design from Microsoft.

    WPF buttons also don't have an invisible area around the dark border.

    [quote author="Boris L" date="1406693543"]So I am back with my original question: Is it possible to get rid of this invisible area?

    [quote author="JKSH" date="1406649850"]Hi,
    You can override the native style to get a button without the invisible 1-px border:

    @button->setStyleSheet("QPushButton {background-color : red;}");@
    [/quote]

    I guess you pasted it form the previous example. I am not sure I can do it with CSS.[/quote]You can apply negative margins to expand the center and chop off the edges:
    @
    // Set for a single button
    auto button = new QPushButton("Hello!");
    button->setStyleSheet("QPushButton { margin: -1px }");

    // Set for the whole application
    qApp->setStyleSheet("QPushButton { margin: -1px }");
    @



  • Thanks, that worked!
    However, need a check for Windows XP, where the button looks OK initially.


Log in to reply
 

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