【问题标题】:qt remove layouts codeqt删除布局代码
【发布时间】:2023-03-27 00:37:01
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你能分享你代码的相关部分吗?
  • 我相信您需要更改QLabel 的字体大小。更改几何属性会增加标签的大小,但不会增加其内容。如果这不起作用,那么您能展示一下您是如何隐藏其他小部件和布局的吗?
  • 感谢您的建议,不幸的是标签的大小没有改变(因为它被其他组件包围)实际上该标签用于运行视频。我只需要增加标签的大小以使视频看起来更大。我用例如隐藏组件。组件->setHidden(true)。有没有办法完全停用它们? (喜欢删除它们但能够再次将它们带回来)
  • 您可以根据需要使用 layout->removeWidget(*widget) 从布局中删除任何小部件。然后您可以将删除的小部件设置为隐藏。这样,您的QLabel 视频将占用更多空间。当然,这取决于您选择隐藏和显示的内容。如果这不起作用,要正确控制大小可能是将单独的布局项分组到具有自己布局的QWidget

标签: c++ qt layout


【解决方案1】:

我曾经向SO: Qt - How to create Image that scale with window, and keeps aspect ratio? 提供过答案。实际意图是使用原始纵横比以QLabel 缩放图像以占用最大可用尺寸。

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

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

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

// 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 编译测试:

切换装饰工具按钮后:

注意:

出于好奇,我评论了改变框架样式的行

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

再一次,调整图像大小不再正常工作。

【讨论】:

    【解决方案2】:

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

    标签1 标签2 标签3
    label4 videoLabel label5
    按钮1 按钮2 按钮3

    假设当您单击button3label1label2label4 时应该全部消失,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;
        }
    
    }
    

    我得到了以下结果:

    请记住,这个问题还有其他方法。就记忆而言,这不一定是最好的,但很容易理解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多