qt删除布局代码

时间:2018-02-19 15:22:25

标签: c++ qt layout

我在QT的经验不到1天(这就是为什么我不太了解它)我有一个窗口,里面装满了按布局组织的信息(标签,文字,按钮等)。

我需要按下一个按钮后,窗口中的所有组件都被隐藏(我已经做过),除了一个标签应该增加到几乎不是整个窗口的大小

尽管我尝试修改“几何”属性(带代码),但隐藏的布局不会让标签增加。我还想到了使用布局中断的选项,但标签失去了它的活力。有人可以推荐我做任何事吗?感谢。

之前有没有人做过这样的事情。感谢。

2 个答案:

答案 0 :(得分:1)

我曾经为SO: Qt - How to create Image that scale with window, and keeps aspect ratio?提供了答案。实际意图是使用原始宽高比缩放QLabel中的图像以消耗最大可用大小。

但是,我得到的反馈是,当我的标签用于QGridLayout时,建议的解决方案将无法正常工作。 (这听起来非常类似于OP的问题。)因此,我修改了样本以重现问题并且稍微摆弄了一下。对我来说,似乎主窗口的调整大小事件在QGridLayout处理,但仅部分影响布局图像标签。 (缩小是应用但不是增长。)幸运的是,我发现了一个非常简单的解决办法:将一个非空框架设置为QLabel解决了问题。我查看了woboq.org上的源代码。我希望得到一个提示,即更改的框架样式将被激活(将其应用于修复我的调整大小问题)。最后,我没有耐心,把它放在一边。

除了QLabel调整大小问题中的QGridLayout之外,更改窗口小部件的可见性应该会导致正确的重新布局。我更喜欢显示/隐藏(而不是删除和重新创建),因为这肯定更容易实现,更高效,更不容易出错。

我拿了旧的示例代码并添加了一个工具按钮,可以用来切换一些布局小部件的可见性:

// 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();
}

我在Windows 10上的VS2013中进行了编译和测试:

Snapshot of testQLabelImageResize – initial state

切换装饰工具按钮后:

Snapshot of testQLabelImageResize – with hidden widgets

注意:

出于好奇,我评论了改变框架风格的线条

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

再次,图像的大小调整不再适用。

答案 1 :(得分:0)

您可以使用QLayout::removeWidget(*widget)删除和隐藏布局中的小部件;但你不需要实际删除它。您应该使用QWidget::hide()来消除内容,并使视频标签的单元格能够占用该空间。我认为如果视频标签的尺寸没有增加,你需要注意它。假设你有QGridLayout这样:

  

label1 label2 label3
  label4 videoLabel label5
  button1 button2 button3

让我们说,当您点击button3时,label1label2label4应该全部消失,videoLabel接受新创建空间。我会将小部件label1label2label4videoLabel分组到具有自己的子布局的单个小部件中。我使用QSizePolicy::Expaning来确保我的videoLabel占用最大空间。以下是实施:

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;
    }

}

我得到了以下结果:

Compact View Full Screen View

请记住,此问题还有其他方法。在记忆方面,这个并不一定是最好的,但它很容易理解。