在Qt4中获取QVBoxLayout的布局单元格的大小

时间:2011-04-08 13:10:46

标签: c++ qt4

我正在尝试在QVBoxLayout内以适当的大小渲染图像,但我无法检索正确的大小。布局包含QLabel,在设计器视图中以适当的大小显示(参见图像)。目标是以最大可用尺寸显示图像。

Layout

以下是我尝试获取尺寸(全部失败):

VideoResourceWidget::VideoResourceWidget(VideoResource* resource, QWidget *parent) :
        QWidget(parent),
        ui(new Ui::VideoResourceForm),
        m_videoResource(resource)
{
    ui->setupUi(this);

    // INFO: -> size = (670,463) // this seems to be too small
    m_videoSize = this->geometry().size();

    // first attempt -> size = (0,0)
    m_videoSize = this->geometry().size();
    m_videoSize.setHeight(m_videoSize.height() - ui->controllerLayout->geometry().height());

    // second attempt -> size = (100,30) way too small
    m_videoSize = ui->videoLayout->itemAt(ui->videoLayout->indexOf(ui->frameLabel))->geometry().size();

    ui->videoLayout->activate(); // hint from another question

    // forth attempt -> size = (145,428) better but not still too small
    m_videoSize = ui->videoLayout->itemAt(ui->videoLayout->indexOf(ui->frameLabel))->geometry().size();

    // third attempt -> size = (670,434) there is still a lot more room
    m_videoSize = this->geometry().size();
    m_videoSize.setHeight(m_videoSize.height() - ui->controllerLayout->geometry().height());

    ui->videoLayout->setSpacing(1);
    ui->frameLabel->setMargin(0);

    ui->videoLayout->activate(); // hint from another question

    // fifth attempt -> size = (145,428) same as before
    m_videoSize = ui->videoLayout->itemAt(ui->videoLayout->indexOf(ui->frameLabel))->geometry().size();

    // sixth attempt -> size = (670,434) same as before
    m_videoSize = this->geometry().size();
    m_videoSize.setHeight(m_videoSize.height() - ui->controllerLayout->geometry().height());

    QImage frame = m_videoResource->firstFrame();
    ui->frameLabel->setPixmap(QPixmap::fromImage(frame).scaled(m_videoSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));

    connect(ui->nextFrameButton, SIGNAL(clicked()), this, SLOT(nextFrame()));
}

这是第一次显示VideoResourceWidget后的GUI。

Displaying the first frame

虽然最终结果不一定非常好,但我希望能有效地利用可用空间。

更新:我更新了屏幕截图以反映我最近的尝试。

更新:最小例子:

mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>771</width>
    <height>580</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
    <item>
     <layout class="QHBoxLayout" name="displayLayout" stretch="0,0,0">
      <item>
       <spacer name="horizontalSpacer">
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
    <property name="sizeHint" stdset="0">
     <size>
      <width>40</width>
      <height>20</height>
     </size>
    </property>
       </spacer>
      </item>
      <item>
       <widget class="QLabel" name="frameLabel">
    <property name="text">
     <string>TextLabel</string>
    </property>
       </widget>
      </item>
      <item>
       <spacer name="horizontalSpacer_2">
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
    <property name="sizeHint" stdset="0">
     <size>
      <width>40</width>
      <height>20</height>
     </size>
    </property>
       </spacer>
      </item>
     </layout>
    </item>
    <item>
     <layout class="QHBoxLayout" name="controllerLayout" stretch="1,0">
      <item>
       <widget class="QScrollBar" name="horizontalScrollBar">
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="nextButton">
    <property name="text">
     <string>PushButton</string>
    </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>771</width>
     <height>25</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:
    void next();

private:
    Ui::MainWindow *ui;

    QSize m_imageSize;
    QImage m_image;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->layout()->activate();

    connect(ui->nextButton, SIGNAL(clicked()), this, SLOT(next()));

    // Goal: display the image centered using the maximally available space
    m_image = QImage("/tmp/lena.jpg");
    m_imageSize = ui->frameLabel->size();
    ui->frameLabel->setPixmap(QPixmap::fromImage(m_image).scaled(m_imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::next()
{
    // just redraw
    m_imageSize = ui->frameLabel->size();
    ui->frameLabel->setPixmap(QPixmap::fromImage(m_image).scaled(m_imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}

2 个答案:

答案 0 :(得分:1)

减小布局的边距和间距(使用它。我不确定哪个是什么)的大小。通过这种方式,标签可以获得更多空间,您的图片也是如此。

我不确定你的期望是什么,但第二次屏幕截图对我来说非常好。 (保持纵横比例使其占据标签的高度)。它只是没有居中。

答案 1 :(得分:0)

我首先尝试移除垫片。然后设置Label的sizeHint(正如其他人已经指出的那样)。

如果你真的需要放置间隔物,请将它们的stretchFactors设置为“0”,将Label的stretchFactor设置为“1”。

实际上我不会使用QLabel来渲染视频,但我想这只是一个测试,我知道QLabel很容易用于显示pixmaps。我的选择是获得性能并重新实现QGLWidget并通过OpenGL进行视频渲染。