PDA

View Full Version : QLabel not sized from dimensions in designer during runtime



astodolski
25th October 2013, 15:09
I have a QLabel used to display a QImage. In design mode the label geometry is (9,65), 1384 × 616 as listed in the Property Editor. At runtime when the MainWindow containing the label constructs (i.e. ui->setupUi(this)), the label always appears to be 100×30 at startup which leads to images displaying only a really small portion.

Why do I have to set it to a fixed size to be anything but 100×30?

Source for the form is below.

Thanks in advance for any help.



/************************************************** ******************************
** Form generated from reading UI file 'mainwindowfX1656.ui'
**
** Created by: Qt User Interface Compiler version 5.1.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
************************************************** ******************************/

#ifndef MAINWINDOWFX1656_H
#define MAINWINDOWFX1656_H

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSlider>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MainWindow
{
public:
QAction *actionOpen_File;
QAction *actionAbout;
QAction *actionAbout_Qt;
QAction *actionZoom_In;
QAction *actionZoom_Out;
QAction *action_Normal_Size;
QWidget *centralWidget;
QGridLayout *gridLayout;
QHBoxLayout *horizontalLayout_2;
QPushButton *btnChange;
QSpacerItem *horizontalSpacer;
QHBoxLayout *horizontalLayout;
QLabel *label;
QSpinBox *sbScaleImage;
QSlider *sliChangeXPos;
QLabel *xposition;
QLabel *lblImage;
QSlider *sliChangeYPos;
QLabel *yposition;
QMenuBar *menuBar;
QMenu *menu_File;
QMenu *menuHelp;
QMenu *menuView;
QStatusBar *statusBar;

void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QStringLiteral("MainWindow"));
MainWindow->resize(1427, 731);
MainWindow->setMinimumSize(QSize(0, 0));
actionOpen_File = new QAction(MainWindow);
actionOpen_File->setObjectName(QStringLiteral("actionOpen_File"));
actionAbout = new QAction(MainWindow);
actionAbout->setObjectName(QStringLiteral("actionAbout"));
actionAbout_Qt = new QAction(MainWindow);
actionAbout_Qt->setObjectName(QStringLiteral("actionAbout_Qt"));
actionZoom_In = new QAction(MainWindow);
actionZoom_In->setObjectName(QStringLiteral("actionZoom_In"));
actionZoom_Out = new QAction(MainWindow);
actionZoom_Out->setObjectName(QStringLiteral("actionZoom_Out"));
action_Normal_Size = new QAction(MainWindow);
action_Normal_Size->setObjectName(QStringLiteral("action_Normal_Size"));
action_Normal_Size->setCheckable(true);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
gridLayout = new QGridLayout(centralWidget);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
gridLayout->setContentsMargins(-1, 9, -1, 9);
horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
btnChange = new QPushButton(centralWidget);
btnChange->setObjectName(QStringLiteral("btnChange"));

horizontalLayout_2->addWidget(btnChange);

horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

horizontalLayout_2->addItem(horizontalSpacer);

horizontalLayout = new QHBoxLayout();
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
label = new QLabel(centralWidget);
label->setObjectName(QStringLiteral("label"));

horizontalLayout->addWidget(label);

sbScaleImage = new QSpinBox(centralWidget);
sbScaleImage->setObjectName(QStringLiteral("sbScaleImage"));
sbScaleImage->setEnabled(false);
sbScaleImage->setMinimum(-25);
sbScaleImage->setMaximum(10);
sbScaleImage->setValue(1);

horizontalLayout->addWidget(sbScaleImage);


horizontalLayout_2->addLayout(horizontalLayout);


gridLayout->addLayout(horizontalLayout_2, 0, 0, 1, 2);

sliChangeXPos = new QSlider(centralWidget);
sliChangeXPos->setObjectName(QStringLiteral("sliChangeXPos"));
sliChangeXPos->setMinimum(0);
sliChangeXPos->setMaximum(200);
sliChangeXPos->setPageStep(1);
sliChangeXPos->setValue(0);
sliChangeXPos->setSliderPosition(0);
sliChangeXPos->setOrientation(Qt::Horizontal);
sliChangeXPos->setInvertedAppearance(false);
sliChangeXPos->setInvertedControls(true);
sliChangeXPos->setTickInterval(0);

gridLayout->addWidget(sliChangeXPos, 1, 0, 1, 1);

xposition = new QLabel(centralWidget);
xposition->setObjectName(QStringLiteral("xposition"));

gridLayout->addWidget(xposition, 1, 1, 1, 1);

lblImage = new QLabel(centralWidget);
lblImage->setObjectName(QStringLiteral("lblImage"));
lblImage->setStyleSheet(QStringLiteral("background-color: rgb(85, 170, 255);"));
lblImage->setFrameShape(QFrame::Panel);
lblImage->setFrameShadow(QFrame::Plain);
lblImage->setAlignment(Qt::AlignCenter);
lblImage->setTextInteractionFlags(Qt::NoTextInteraction);

gridLayout->addWidget(lblImage, 2, 0, 2, 1);

sliChangeYPos = new QSlider(centralWidget);
sliChangeYPos->setObjectName(QStringLiteral("sliChangeYPos"));
sliChangeYPos->setPageStep(1);
sliChangeYPos->setOrientation(Qt::Vertical);
sliChangeYPos->setInvertedAppearance(true);

gridLayout->addWidget(sliChangeYPos, 2, 1, 1, 1);

yposition = new QLabel(centralWidget);
yposition->setObjectName(QStringLiteral("yposition"));

gridLayout->addWidget(yposition, 3, 1, 1, 1);

MainWindow->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindow);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 1427, 21));
menu_File = new QMenu(menuBar);
menu_File->setObjectName(QStringLiteral("menu_File"));
menuHelp = new QMenu(menuBar);
menuHelp->setObjectName(QStringLiteral("menuHelp"));
menuView = new QMenu(menuBar);
menuView->setObjectName(QStringLiteral("menuView"));
MainWindow->setMenuBar(menuBar);
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QStringLiteral("statusBar"));
MainWindow->setStatusBar(statusBar);

menuBar->addAction(menu_File->menuAction());
menuBar->addAction(menuHelp->menuAction());
menuBar->addAction(menuView->menuAction());
menu_File->addAction(actionOpen_File);
menuHelp->addAction(actionAbout);
menuHelp->addSeparator();
menuHelp->addAction(actionAbout_Qt);
menuView->addAction(actionZoom_In);
menuView->addAction(actionZoom_Out);
menuView->addSeparator();

retranslateUi(MainWindow);

QMetaObject::connectSlotsByName(MainWindow);
} // setupUi

void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
actionOpen_File->setText(QApplication::translate("MainWindow", "Open File", 0));
#ifndef QT_NO_TOOLTIP
actionOpen_File->setToolTip(QApplication::translate("MainWindow", "Open an image for viewing", 0));
#endif // QT_NO_TOOLTIP
actionAbout->setText(QApplication::translate("MainWindow", "About", 0));
actionAbout_Qt->setText(QApplication::translate("MainWindow", "About Qt", 0));
actionZoom_In->setText(QApplication::translate("MainWindow", "Zoom In", 0));
actionZoom_In->setShortcut(QApplication::translate("MainWindow", "Ctrl++", 0));
actionZoom_Out->setText(QApplication::translate("MainWindow", "Zoom Out", 0));
actionZoom_Out->setShortcut(QApplication::translate("MainWindow", "Ctrl+-", 0));
action_Normal_Size->setText(QApplication::translate("MainWindow", "&Normal Size", 0));
action_Normal_Size->setShortcut(QApplication::translate("MainWindow", "Ctrl+S", 0));
btnChange->setText(QApplication::translate("MainWindow", "Invert Image", 0));
label->setText(QApplication::translate("MainWindow", "Scale", 0));
xposition->setText(QString());
lblImage->setText(QString());
yposition->setText(QString());
menu_File->setTitle(QApplication::translate("MainWindow", "File", 0));
menuHelp->setTitle(QApplication::translate("MainWindow", "Help", 0));
menuView->setTitle(QApplication::translate("MainWindow", "View", 0));
} // retranslateUi

};

namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

#endif // MAINWINDOWFX1656_H

ChrisW67
25th October 2013, 21:34
The widget size is driven by the layout within the constraints imposed by the widget itself, the available screen space for the layout, stretch factors, and the other widgets in the layout. If your label still has the default size policies then it is resizable to make space for other widgets that might need it or to fit a default sized container window... and probably is. If your widget must have at least a certain size then set that size and set the size policy to something other than preferred. You may also need to allow for the possibility the widget cannot fit on the user's screen.

astodolski
25th October 2013, 21:40
I don't think I quite understand all you just wrote. What constraints other than the code for the UI I posted are being imposed? I put a QLabel on a QmainWindow and performed a grid layout on the the central widget.

ChrisW67
25th October 2013, 23:10
Designer is not a literal WYSIWYG editor with absolute placement and sizing (like the UI editor of Visual Basic 6 and similar vintage). Designer provides a mechanism for placing widgets into a layout. You see the general relationship of widgets in Designer but the layout code determines at run time what the end result will be. Each widget can have a minimum size, maximum size, a size hint (preferred size), and policies describing how a layout should treat their size hint. Layouts may also support minimum and maximum constraints that are used also. These are all set in Designer or derived from other characteristics of the widget (e.g. the amount text and font size in a label) and taken into consideration at run time by the layout code. When more space becomes available to a layout, i.e. its container is resized, then the new space is allocated to the contained widgets according to any stretch factors that are present (or evenly allocated otherwise).

In your uic example, lblImage has neither minimum nor maximum size set, no explicitly set size policy (defaults to Preferred). The result is that this widget can be resized by the layout almost without restriction.

Qt4 Layout Management (http://qt-project.org/doc/qt-4.8/layout.html)
Qt5 Layout Management (http://qt-project.org/doc/qt-5.0/qtwidgets/layout.html)

astodolski
26th October 2013, 02:27
The result is that this widget can be resized by the layout almost without restriction.

Qt4 Layout Management (http://qt-project.org/doc/qt-4.8/layout.html)
Qt5 Layout Management (http://qt-project.org/doc/qt-5.0/qtwidgets/layout.html)

Fair enough. Does that mean I have no control over the dimensions? I don't think so. How then do I control the child widget's dimensions? What size policies do I impose? How do I get an image to display in the size that the QLabel appears in the designer?

ChrisW67
26th October 2013, 05:07
Does that mean I have no control over the dimensions?
No, and neither I nor the documentation I pointed you at says that.

How then do I control the child widget's dimensions?
By setting maximum, minimum, or preferred sizes (size hints in custom widgets) and size policies. Most out-of-box widgets like QLabel provide a default size hint based on their min/max size properties and their content. Have you tried anything for yourself?

What size policies do I impose?
You impose size policies that make sense for the application and widgets concerned. They are documented. QSizePolicy::Fixed, there's a hint in the name, but you need to read the docs to see what it is fixing.

How do I get an image to display in the size that the QLabel appears in the designer?
There's generally no direct connection between the size of something in Designer and the size at run time. If you fix the size of a widget Designer will generally show the widget at that size. At run time any non-fixed widget is likely to be a different size.

astodolski
28th October 2013, 12:04
There's generally no direct connection between the size of something in Designer and the size at run time. If you fix the size of a widget Designer will generally show the widget at that size. At run time any non-fixed widget is likely to be a different size.

OK, let me ask differently. How would you create a label that displays a pixmap to use the entire area of the label. For example, I colored the label background. At runtime (before loading any image), the label is displayed at full width and height. However the label reports 100 x 30.

ChrisW67
28th October 2013, 22:00
OK, let me ask differently. How would you create a label that displays a pixmap to use the entire area of the label. For example, I colored the label background. At runtime (before loading any image), the label is displayed at full width and height. However the label reports 100 x 30.

I have no idea what you are asking for. The label is the "full width and height" of what? How is the label reporting "100 x 30"? In what way is that a problem?

If the pixmap is smaller or larger than the geometry of the label then you will need to scale it in some way to fit the "entire area of the label". This is not automagical and there is more than one way to scale something to fit. Have a look at QLabel::scaledContents() for one option.

astodolski
29th October 2013, 11:44
I have no idea what you are asking for. The label is the "full width and height" of what? How is the label reporting "100 x 30"? In what way is that a problem?

If the pixmap is smaller or larger than the geometry of the label then you will need to scale it in some way to fit the "entire area of the label". This is not automagical and there is more than one way to scale something to fit. Have a look at QLabel::scaledContents() for one option.

I may have to set up the label size after construction. I see that when the main window is shown and no image loaded I can re-size the client area so small that the image gets reduced to the 100 x 30. So at construction the label is at the smallest that is allowed by the layout (100 x 30).

My comment earlier is that after construction and when the window is shown the label appears at the full width and height allowed by the layout. However, I am telling the image to be displayed in the size of the label as reported in the main window constructor. The image appears very small - not the size of the label when the window is shown

Hope that's clearer.

anda_skoa
29th October 2013, 12:39
However, I am telling the image to be displayed in the size of the label as reported in the main window constructor. The image appears very small - not the size of the label when the window is shown


So you are asking where to set the image size instead of in the constructor. My suggestion would be in showEvent().

Cheers,
_

astodolski
29th October 2013, 14:29
So you are asking where to set the image size instead of in the constructor. My suggestion would be in showEvent().

Cheers,
_

Perhaps something like below?



void MainWindow::showEvent(QShowEvent* e)
{
QMainWindow::showEvent(e);

if(e->spontaneous())
return;

if(isInitialized)
return;

MappedBuffer = new quint8[ui->lblImage->width() * ui->lblImage->height() * BITMAP_FORMAT];
origImage = new QImage(MappedBuffer, ui->lblImage->width(), ui->lblImage->height(), BITMAP_FORMAT);


isInitialized = true;
}


As an alternate, why is showEvent() preferred over event()?


bool MainWindow::event(QEvent* e)
{
int returnValue = QMainWindow::event(e);

if(e->type() == QEvent::Show)
{
widgetSize = ui->lblImage->size();

}

return returnValue;
}

anda_skoa
30th October 2013, 10:16
You can also implement it in event().

The base implementation of event() checks the type, performs a cast and then calls showEvent().
It is just more code you have to write :)


Cheers,
_