1

I have less than 1 day of experience in QT (that's why I do not know much of it) I have a window full of information (labels, text, buttons, etc) organized by layouts.

I need that after I press one button, all of the components in a window be hidden (which I already did) except for one label which should increase to barely the size of the whole window

Despite I tried modifying the "geometry" attribute (with code) the hidden layouts do not let the label to be increased. I thought also of using the option of layout breaking, but the label losses its dynamism. Could anyone please recommend me anything to do? Thanks.

Has anyone done something like this before. Thanks.

  • Can you share the relevant parts of your code? – JLev Feb 19 '18 at 15:28
  • I believe you nee to change the font size for the `QLabel `. Change the geometry attribute increases the size of the label, but not its contents. If that does not work, then can you show how you are hiding the other widgets and layouts? – Aditya Feb 19 '18 at 15:37
  • Thanks for the advice, unfortunately the size of the label was not changed (since it is surrounded by other components) Actually that label is used to run a video. I just need to increase the size of the label to make the video look bigger. I'm hiding the components with eg. component->setHidden(true). Is there a way to deactivate them completely? (like to remove them but to be able to bring them back again) – Diego Alejandro Gómez Pardo Feb 19 '18 at 15:49
  • You can remove any widget from the layout as necessary with layout->removeWidget(*widget). Then you can set the removed widget to hidden. That way, your `QLabel` video will take more space. Of course, this would depend on what you choose to hide and show. To properly control the size if this does not work would probably be to group separate layout items into a `QWidget` with a layout of its own. – Aditya Feb 20 '18 at 16:31

2 Answers2

1

I once provided an answer to SO: Qt - How to create Image that scale with window, and keeps aspect ratio?. The actual intention was to scale an image in a QLabel with original aspect ratio to consume maximum available size.

However, I got the feedback that the suggested solution would not work properly when my Label would be used in a QGridLayout. (This sounds very similar to the issue of the OP.) Hence, I modified the sample to reproduce the issue and fiddled a little bit around with. For me, it seems that resize events of the main window are processed in the QGridLayout but affect layouted image label only partially. (Shrinking is applied but growing not.) Fortunately, I found a very simple work-around: Setting a non-empty frame to the QLabel solved the problem. I had a look into the source code on woboq.org. I hoped to get a hint what the changed frame style would activate (to apply this as fix for my resize issue). Finally, I was not patient enough and put it aside.

Beside of this QLabel in a QGridLayout resize issue, changing the visibility of widgets should cause a proper re-layout. I would prefer show/hide (instead of delete and re-new) as this is surely easier to implement, more efficient, and less error-prone.

I took the old sample code and added a tool button which can be used to toggle the visibilty of some of the layouted widgets:

// Qt header:
#include <QtWidgets>

class LabelImage: public QLabel {

  private:
    QPixmap _qPixmap, _qPixmapScaled;

  public:
    void setPixmap(const QPixmap &qPixmap) { setPixmap(qPixmap, size()); }

  protected:
    virtual void resizeEvent(QResizeEvent *pQEvent);

  private:
    void setPixmap(const QPixmap &qPixmap, const QSize &size);
};

void LabelImage::resizeEvent(QResizeEvent *pQEvent)
{
  QLabel::resizeEvent(pQEvent);
  setPixmap(_qPixmap, pQEvent->size());
}

void LabelImage::setPixmap(const QPixmap &qPixmap, const QSize &size)
{
  _qPixmap = qPixmap;
  _qPixmapScaled = _qPixmap.scaled(size, Qt::KeepAspectRatio);
  QLabel::setPixmap(_qPixmapScaled);
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  // main application
  QApplication app(argc, argv);
  // setup GUI
  QMainWindow qWin;
  QToolBar qToolbar;
  QAction qCmdTgl(QString::fromUtf8("Decoration"));
  qCmdTgl.setCheckable(true);
  qCmdTgl.setChecked(true);
  qToolbar.addAction(&qCmdTgl);
  qWin.addToolBar(&qToolbar);
  QGroupBox qBox;
  QGridLayout qGrid;
  // a macro for the keyboard lazy:
#define Q_LBL_WITH_POS(ROW, COL) \
  QLabel qLbl##ROW##COL(QString::fromLatin1(#ROW", "#COL)); \
  /*qLbl##ROW##COL.setFrameStyle(QLabel::Raised | QLabel::Box);*/ \
  qGrid.addWidget(&qLbl##ROW##COL, ROW, COL, Qt::AlignCenter)
  Q_LBL_WITH_POS(0, 0);
  Q_LBL_WITH_POS(0, 1);
  Q_LBL_WITH_POS(0, 2);
  Q_LBL_WITH_POS(1, 0);
  LabelImage qLblImg;
  qLblImg.setFrameStyle(QLabel::Raised | QLabel::Box);
  qLblImg.setAlignment(Qt::AlignCenter);
  //qLblImg.setMinimumSize(QSize(1, 1)); // seems to be not necessary
  qLblImg.setSizePolicy(
    QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
  QPixmap qPM;
  if (qPM.load("cats.jpg")) qLblImg.setPixmap(qPM);
  else {
    qLblImg.setText(
      QString::fromLatin1("Sorry. Cannot find file 'cats.jpg'."));
  }
  qGrid.addWidget(&qLblImg, 1, 1, Qt::AlignCenter);
  qGrid.setRowStretch(1, 1); // tell QGridLayout to stretch this cell...
  qGrid.setColumnStretch(1, 1); // ...prior to other cells (w/ stretch 0)
  Q_LBL_WITH_POS(1, 2);
  Q_LBL_WITH_POS(2, 0);
  Q_LBL_WITH_POS(2, 1);
  Q_LBL_WITH_POS(2, 2);
  qBox.setLayout(&qGrid);
  qWin.setCentralWidget(&qBox);
  qWin.show();
  // install signal handlers
  QObject::connect(&qCmdTgl, &QAction::triggered,
    [&](bool on) {
      qLbl00.setVisible(on); qLbl01.setVisible(on); qLbl02.setVisible(on);
      qLbl10.setVisible(on);                        qLbl12.setVisible(on);
      qLbl20.setVisible(on); qLbl21.setVisible(on); qLbl22.setVisible(on);
    });
  // run application
  return app.exec();
}

I compiled and tested in VS2013 on Windows 10:

Snapshot of testQLabelImageResize – initial state

After toggling the Decoration tool button:

Snapshot of testQLabelImageResize – with hidden widgets

Note:

Out of curiosity, I commented the line which changes the frame style

qLblImg.setFrameStyle(QLabel::Raised | QLabel::Box);

and again, resizing of image didn't work properly anymore.

Scheff's Cat
  • 16,517
  • 5
  • 25
  • 45
0

You can remove and hide widgets inside a layout using QLayout::removeWidget(*widget); but you do not need to actually remove it. You should use QWidget::hide() for the content to disappear and for the video label's cell to be able to take that space. I think you need to pay attention to the video label's size policy if it does not increase in size. Assuming you have a QGridLayout like so:

label1 label2 label3
label4 videoLabel label5
button1 button2 button3

And let's say, when you click button3, label1, label2 and label4 should all disappear and videoLabel takes the newly created space. I would group the widgets label1, label2, label4 and videoLabel into a single widget having its own sub-layout. I use QSizePolicy::Expaning to make sure my videoLabel takes the maximum space possible. Here is the implementation:

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    setStyleSheet("QLabel{font-size:20px;}");
    fullScreen = false; //current fullscreen state

    //main grid layout
    baseLayout = new QGridLayout(this);
    baseLayout->setMargin(0);
    baseLayout->setAlignment(Qt::AlignCenter);
    setLayout(baseLayout);

    //widget container for label1, label2, label4, videolabel
    groupWidget = new QWidget();
    //sub-layout inside the group layout
    subLayout = new QGridLayout();
    subLayout->setAlignment(Qt::AlignCenter);
    subLayout->setMargin(0);
    groupWidget->setLayout(subLayout);

    //label and button instantializing. I set background colors to show their sizes
    label1 = new QLabel("Label1");
    label1->setStyleSheet("background-color:white;");
    label2 = new QLabel("Label2");
    label2->setStyleSheet("background-color:orange;");
    label3 = new QLabel("Label3");
    label4 = new QLabel("Label4");
    label4->setStyleSheet("background-color:blue;color:white;");
    label5 = new QLabel("Label5");
    videoLabel = new QLabel("videoLabel");
    videoLabel->setStyleSheet("background-color:red;");
    videoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    button1 = new QPushButton("button1");
    button2 = new QPushButton("button2");
    button3 = new QPushButton("button3");

    //the grouped widget spans for 2 rows and columns, hence "2,2"
    baseLayout->addWidget(groupWidget, 0,0,2,2);
    subLayout->addWidget(label1, 0, 0);
    subLayout->addWidget(label2, 0, 1);
    subLayout->addWidget(label4, 1, 0);
    subLayout->addWidget(videoLabel, 1, 1);

    //adding rest of the labels and buttons to the base grid
    baseLayout->addWidget(label3, 0, 2);
    baseLayout->addWidget(label5, 1, 2);
    baseLayout->addWidget(button1, 2, 0);
    baseLayout->addWidget(button2, 2, 1);
    baseLayout->addWidget(button3, 2, 2);

    //button3 toggles fullscreen
    connect(button3, SIGNAL(clicked(bool)), this, SLOT(onButton3Clicked(bool)));
}

//slot for button3 click
void Widget::onButton3Clicked(bool)
{
    if (!fullScreen){
        //removing widget from layouts is not really necessary. Make sure to hide
        /*subLayout->removeWidget(label1);
        subLayout->removeWidget(label2);
        subLayout->removeWidget(label4);*/
        label1->hide();
        label2->hide();
        label4->hide();
        fullScreen = true;
    }
    else{
        label1->show();
        label2->show();
        label4->show();
        /*subLayout->addWidget(label1, 0, 0);
        subLayout->addWidget(label2, 0, 1);
        subLayout->addWidget(label4, 1, 0);*/
        fullScreen = false;
    }

}

I got the following results for this:

Compact View Full Screen View

Keep in mind there are other approaches to this question. This one need not be necessarily the best when it comes to memory, but it is quite easy to follow.

Community
  • 1
  • 1
Aditya
  • 429
  • 4
  • 12