Qt应用程序的布局设计问题 [英] Layout design issue with Qt application

查看:55
本文介绍了Qt应用程序的布局设计问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我为我的丑陋绘画技巧表示歉意.我有一个应用程序,我在QLabels中加载了大小为 640x480 的4张图像,如图所示.

字母V,H和G分别表示垂直,水平和网格布局.

QLabel 实施了 sizeHint() heightForWidth() widthForHeight().在我的 QMainwindow resizeEvent()中,我调用 QLabel 上的 setFixedWidth()图像的 QLabel 的大小,并保持宽高比.我想一直保持图像的长宽比.

问题:

  1. QLabel 上设置固定宽度会使小部件3在像我的笔记本电脑这样的较小分辨率的屏幕中看不见.

我尝试不为 QLabel 设置固定宽度,并尝试加载保持宽高比的图像.尺寸政策设置为扩大

QSizePolicy sizePolicy(QSizePolicy :: Expanding,QSizePolicy :: Expanding);

我得到这样的东西

问题:

在保持宽高比的同时加载图像会导致 QLabel 超出图像水平水平的多余扩展,看起来很难看.

我想要什么:

  1. QLabel 应该始终适合图像,而不管其自身的大小如何.
  2. widget1 QLabel
  3. 之间不应有任何奇怪的空白
  4. 通过更改 QLabel 的大小,同时保持图像的长宽比,整个应用程序应适合任何分辨率.

我觉得这是一种定义/设计问题,而不是技术问题.我尝试了各种限制和政策,但无法实现我想要的目标.我相信我可以在这里得到一些建议.

解决方案

我不确定100%如何实现OP的精确布局要求.

在我准备的样品中稍微摆弄拉伸因子后,情况并没有变好.

因此,我的回答详述了恕我直言,必须考虑两个重要方面.

设置拉伸因子

这是我有关小部件集的布局的经验,我首先在OSF/Motif中收集,然后在GTK +(具有IMHO最佳布局管理),最后在Qt中收集:

不要试图与布局管理器抗争–您最终会感到沮丧(例如

这看起来还不错.

缩放图像标签

但是, QLabel 中的图像大小不变.为了解决这个问题,我想起了我的一个旧答案

布局管理不能很好地发挥作用(正如预期的那样-我没有给出任何延伸提示).但是,至少 ImageLabel

  • 确保正确考虑纵横比的图像缩放
  • (尝试)根据图像纵横比调整 QLabel 的大小(如果可能).

QSizePolicy 扮演着重要角色.阅读文档后.向上和向下,我必须承认,在找到最符合我的期望的设置之后,我尝试了一些看起来很有希望的设置.


恕我直言,OPs解决方案是两个示例中技术的正确组合.

Firstly, I apologise for my ugly drawing skills. I have an application where i load 4 images of size 640x480in the QLabels as shown in the image.

Letters V, H and G here mean Vertical, Horizontal and Grid layouts respectively.

Implemented sizeHint(), heightForWidth() and widthForHeight()for the QLabel. In the resizeEvent() of my QMainwindow i call setFixedWidth() on QLabelwhich solves the issue of fitting the size of QLabel to the image keeping the aspect ratio. I want to maintain the aspect ratio of the image at all times.

Issues:

  1. Setting a fixed width on QLabel pushes the widget3 out of view in smaller resolution screens like my laptop.

I tried setting no fixed widths for the QLabel and tried to load the images keeping the aspect ratio. Size policy is set to expanding

QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

I get something like this

Issues:

Loading the image while keeping the aspect ratio leads to unwanted expanding of QLabelbeyond the image horizontally which looks ugly.

What do i want:

  1. QLabel should fit to the image all the time irrespective of its own size.
  2. There should not be any weird empty spaces between widget1 and QLabel
  3. The whole application should fit on any resolution by changing the size of the QLabel while keeping the aspect ratio of the image.

I feel it is kind of definition/design problem than being a technical problem. I tried all sorts of constraints and policies but couldn't achieve what i wanted. I believe i could get some suggestions here.

解决方案

I'm not 100 % sure how to achieve the precise layout requirements of the OP.

This didn't became better after fiddling a bit with stretch factors in the samples I have prepared.

So, my answer elaborates the IMHO two essential aspects which have to considered.

Setting up Stretch Factors

This is my experience about layout of widget sets which I first collected in OSF/Motif, then in GTK+ (which has the IMHO best layout management) and finally in Qt:

Don't try to fight against layout manager – you will end up in frustration (like Don Quixote). Instead, try to provide the right hints (however this is possible) to let the layout manager do something which does match your expectations most.

(Or just write an own which provides fixed widget positions and sizes to the underlying widget set. This can be enlighting to realize why the layout manager are that damn complicated to use.)

So, my first attempt was to set up the stretch factors right:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  QImage img("cats.jpg");
  QPixmap pixmap; 
  // setup GUI
  QWidget winMain;
  winMain.setWindowTitle("Layout Sample");
  QVBoxLayout v;
  QHBoxLayout h;
  QLabel widget1("Widget1");
  widget1.setFrameStyle(QLabel::Box | QLabel::Plain);
  h.addWidget(&widget1, 1); // remark widget1 for growing (horizontally in HBox h)
  QGridLayout g;
  QLabel img1;
  img1.setPixmap(QPixmap::fromImage(img));
  g.addWidget(&img1, 0, 0);
  QLabel img2;
  img2.setPixmap(QPixmap::fromImage(img));
  g.addWidget(&img2, 0, 1);
  QLabel img3;
  img3.setPixmap(QPixmap::fromImage(img));
  g.addWidget(&img3, 1, 0);
  QLabel img4;
  img4.setPixmap(QPixmap::fromImage(img));
  g.addWidget(&img4, 1, 1);
  h.addLayout(&g, 0); // remark g for not growing (horizontally in HBox h)
  v.addLayout(&h, 0); // remark h for not growing (vertically in VBox v)
  QLabel widget2("Widget2");
  widget2.setFrameStyle(QLabel::Box | QLabel::Plain);
  widget2.setAlignment(Qt::AlignLeft | Qt::AlignTop);
  v.addWidget(&widget2, 1); // remark widget2 for growing (vertically in VBox v)
  QLabel widget3("Widget3");
  widget3.setFrameStyle(QLabel::Box | QLabel::Plain);
  widget3.setAlignment(Qt::AlignLeft | Qt::AlignTop);
  v.addWidget(&widget3, 1); // remark widget3 for growing (vertically in VBox v)
  winMain.setLayout(&v);
  winMain.show();
  // runtime loop
  return app.exec();
}

Output:

This doesn't look that bad.

The Scaling Image Label

However, the image size in QLabel doesn't change. To fix this, I recalled an old answer of mine SO: Qt - How to create Image that scale with window, and keeps aspect ratio?.

I removed all explicit stretching factors from the above sample and replaced the QLabels with images by instances of the derived ImageLabel with resp. adjustment of QPixmap size:

#include <QtWidgets>

class LabelImage: public QLabel {

  private:
    QPixmap _qPixmap, _qPixmapScaled;

  public:
    LabelImage(const QPixmap &qPixmap, QWidget *pQParent = nullptr):
      QLabel(pQParent), _qPixmap(qPixmap)
    {
      QSizePolicy sizePolicy;
      sizePolicy.setHorizontalPolicy(QSizePolicy::Ignored);
      sizePolicy.setVerticalPolicy(QSizePolicy::Ignored);
      sizePolicy.setHeightForWidth(true);
      sizePolicy.setWidthForHeight(true);
      setSizePolicy(sizePolicy);
    }
    virtual ~LabelImage() = default;
    LabelImage(const LabelImage&) = delete;
    LabelImage& operator=(const LabelImage&) = delete;

  public:
    //virtual QSize sizeHint() const override;
    virtual int heightForWidth(int w) const override;
  protected:
    virtual void resizeEvent(QResizeEvent *pQEvent) override;
};

//QSize LabelImage::sizeHint() const { return _qPixmap.size(); }

int LabelImage::heightForWidth(int w) const
{
  if (_qPixmap.width() == 0 || _qPixmap.height() == 0) return w;
  return _qPixmap.height() * w / _qPixmap.width();
}

void LabelImage::resizeEvent(QResizeEvent *pQEvent)
{
  QLabel::resizeEvent(pQEvent);
  _qPixmapScaled = _qPixmap.scaled(pQEvent->size(), Qt::KeepAspectRatio);
  QLabel::setPixmap(_qPixmapScaled);
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  QImage img("cats.jpg");
  QPixmap pixmap; 
  // setup GUI
  QWidget winMain;
  winMain.setWindowTitle("Layout Sample");
  QVBoxLayout v;
  QHBoxLayout h;
  QLabel widget1("Widget1");
  widget1.setFrameStyle(QLabel::Box | QLabel::Plain);
  h.addWidget(&widget1);
  QGridLayout g;
  LabelImage img1(QPixmap::fromImage(img));
  g.addWidget(&img1, 0, 0);
  LabelImage img2(QPixmap::fromImage(img));
  g.addWidget(&img2, 0, 1);
  LabelImage img3(QPixmap::fromImage(img));
  g.addWidget(&img3, 1, 0);
  LabelImage img4(QPixmap::fromImage(img));
  g.addWidget(&img4, 1, 1);
  h.addLayout(&g);
  v.addLayout(&h);
  QLabel widget2("Widget2");
  widget2.setFrameStyle(QLabel::Box | QLabel::Plain);
  widget2.setAlignment(Qt::AlignLeft | Qt::AlignTop);
  v.addWidget(&widget2);
  QLabel widget3("Widget3");
  widget3.setFrameStyle(QLabel::Box | QLabel::Plain);
  widget3.setAlignment(Qt::AlignLeft | Qt::AlignTop);
  v.addWidget(&widget3);
  winMain.setLayout(&v);
  winMain.show();
  // runtime loop
  return app.exec();
}

Output:

The layout management doesn't play that nicely (as expected – I didn't gave any stretch hint). However, at least, the ImageLabel

  • ensures scaling of image considering aspect-ratio correctly
  • (tries to) resize the QLabel according to the image aspect-ratio (when possible).

The QSizePolicy plays an important role. After having read the doc. downwards and upwards, I must admit I tried some settings which seemed to be promising after I found one which matched my expectations most.


IMHO, OPs solution is the right combination of the techniques in both samples.

这篇关于Qt应用程序的布局设计问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆