我在QT的经验不到1天(这就是为什么我不太了解它)我有一个窗口,里面装满了按布局组织的信息(标签,文字,按钮等)。
我需要按下一个按钮后,窗口中的所有组件都被隐藏(我已经做过),除了一个标签应该增加到几乎不是整个窗口的大小
尽管我尝试修改“几何”属性(带代码),但隐藏的布局不会让标签增加。我还想到了使用布局中断的选项,但标签失去了它的活力。有人可以推荐我做任何事吗?感谢。
之前有没有人做过这样的事情。感谢。
答案 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中进行了编译和测试:
切换装饰工具按钮后:
注意:
出于好奇,我评论了改变框架风格的线条
qLblImg.setFrameStyle(QLabel::Raised | QLabel::Box);
再次,图像的大小调整不再适用。
答案 1 :(得分:0)
您可以使用QLayout::removeWidget(*widget)
删除和隐藏布局中的小部件;但你不需要实际删除它。您应该使用QWidget::hide()
来消除内容,并使视频标签的单元格能够占用该空间。我认为如果视频标签的尺寸没有增加,你需要注意它。假设你有QGridLayout
这样:
label1 label2 label3
label4 videoLabel label5
button1 button2 button3
让我们说,当您点击button3
时,label1
,label2
和label4
应该全部消失,videoLabel
接受新创建空间。我会将小部件label1
,label2
,label4
和videoLabel
分组到具有自己的子布局的单个小部件中。我使用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;
}
}
我得到了以下结果:
请记住,此问题还有其他方法。在记忆方面,这个并不一定是最好的,但它很容易理解。