简体   繁体   English

qt 删除布局代码

[英]qt remove layouts code

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.我在 QT 方面的经验不到 1 天(这就是为什么我对此知之甚少)我有一个按布局组织的充满信息(标签、文本、按钮等)的窗口。

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.谢谢。

I once provided an answer to SO: Qt - How to create Image that scale with window, and keeps aspect ratio?我曾经为SO提供过答案:Qt - 如何创建随窗口缩放并保持纵横比的图像? . . The actual intention was to scale an image in a QLabel with original aspect ratio to consume maximum available size.实际意图是使用原始纵横比缩放QLabel的图像以消耗最大可用尺寸。

However, I got the feedback that the suggested solution would not work properly when my Label would be used in a QGridLayout .但是,我得到的反馈是,当我的 Label 用于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. (这听起来与 OP 的问题非常相似。)因此,我修改了示例以重现该问题并稍微摆弄了一下。 For me, it seems that resize events of the main window are processed in the QGridLayout but affect layouted image label only partially.对我来说,似乎主窗口的调整大小事件在QGridLayout中处理,但仅部分影响QGridLayout图像标签。 (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. (应用收缩但不增长。)幸运的是,我找到了一个非常简单的解决方法:为QLabel设置一个非空框架解决了这个问题。 I had a look into the source code on woboq.org .我查看了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.除了QGridLayout调整大小问题中的QLabel之外,更改小部件的可见性应该会导致正确的重新布局。 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:我在 Windows 10 上的 VS2013 中编译和测试:

testQLabelImageResize 快照——初始状态

After toggling the Decoration tool button:切换装饰工具按钮后:

testQLabelImageResize 快照 – 带有隐藏的小部件

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.再次,调整图像大小不再正常工作。

You can remove and hide widgets inside a layout using QLayout::removeWidget(*widget) ;您可以使用QLayout::removeWidget(*widget)删除和隐藏布局内的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.您应该使用QWidget::hide()使内容消失,并使视频标签的单元格能够占据该空间。 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:假设你有一个QGridLayout像这样:

label1 label2 label3标签1 标签2 标签3
label4 videoLabel label5 label4 videoLabel label5
button1 button2 button3按钮 1 按钮 2 按钮 3

And let's say, when you click button3 , label1 , label2 and label4 should all disappear and videoLabel takes the newly created space.假设,当您单击button3label1label2label4都应该消失, videoLabel会占用新创建的空间。 I would group the widgets label1 , label2 , label4 and videoLabel into a single widget having its own sub-layout.我会将小部件label1label2label4videoLabel到一个具有自己子布局的小部件中。 I use QSizePolicy::Expaning to make sure my videoLabel takes the maximum space possible.我使用QSizePolicy::Expaning来确保我的videoLabel占用最大空间。 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:我得到了以下结果:

紧凑视图 全屏视图

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.当涉及到记忆时,这不一定是最好的,但它很容易遵循。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM