c – Qt窗口大小不正确,直到用户事件

我正在创建一个屏幕,用户可以添加某些图块以在编辑器中使用,但是在添加图块时,窗口无法正确调整大小以适应内容.除了当我拖动窗口或调整大小甚至一点点然后它立即捕捉到正确的大小.


只需拖动窗口,它就会捕捉到正确的大小.

我尝试使用resize(sizeHint());这给了我一个不正确的大小和以下错误,但在调整大小/拖动时仍然会发生正确大小的捕捉.

QWindowsWindow::setGeometry: Unable to set geometry 299x329+991+536 on QWidgetWindow/'TileSetterWindow'. Resulting geometry:  299x399+991+536 (frame: 8,31,8,custom margin: 0,minimum size: 259x329,maximum size: 16777215x16777215).

我也尝试过使用updateGeometry()和update(),但它似乎没有做太多的事情.

将窗口设置为fixedSize时,它会立即调整大小,但用户无法再调整窗口大小.我在这里做错了什么,我从哪里开始解决它?

编辑
Minimal verifiable example.ui file.
selected_layout的类型为Flowlayout
flowlayout_placeholder_1仅在那里,因为我无法将flowlayout直接放入设计器中.

EDIT2
这是minimal Visual Studio example.我使用Visual Studio进行Qt开发.我尝试在Qt Creator中创建一个项目,但我没有让它工作.

EDIT3
添加little video(80 KB).

Edit4
这是updated Visual Studio example.它有jpo38提出的新变化.它解决了调整错误的问题.虽然现在试图缩小窗口的尺寸会导致问题.如果您尝试减少水平空间,即使有更多行的空间,它们也不会正确填充垂直空间.

解决方法

伟大的MCVE,正是轻松调查问题所需要的.

看起来这个FlowLayout类的设计不是为了让用户操作的最小尺寸更改.移动窗口时,QWidget内核会“偶然”更新布局.

我可以通过修改FlowLayout :: minimumSize()行为使其工作变得聪明,以下是我所做的更改:

>添加了QSize minSize;属性为FlowLayout类
>修改FlowLayout :: minimumSize()以简单地返回此属性
>为doLayout函数添加了第三个参数QSize * pMinSize.这将用于更新此minSize属性
>修改了doLayout以将计算大小保存到pMinSize参数(如果已指定)
>如果最小尺寸发生变化,则FlowLayout :: setGeometry将minSize属性传递给doLayout并使布局无效

然后布局按预期运行.

int FlowLayout::heightForWidth(int width) const {
    const int height = doLayout(QRect(0,width,0),true,NULL); // jpo38: set added parameter to NULL here
    return height;
}

void FlowLayout::setGeometry(const QRect &rect) {
    QLayout::setGeometry(rect);

    // jpo38: update minSize from here,force layout to consider it if it changed
    QSize oldSize = minSize;
    doLayout(rect,false,&minSize);
    if ( oldSize != minSize )
    {
        // force layout to consider new minimum size!
        invalidate();
    }
}

QSize FlowLayout::minimumSize() const {
    // jpo38: Simply return computed min size
    return minSize;
}

int FlowLayout::doLayout(const QRect &rect,bool testOnly,QSize* pMinSize) const {
    int left,top,right,bottom;
    getContentsMargins(&left,&top,&right,&bottom);
    QRect effectiveRect = rect.adjusted(+left,+top,-right,-bottom);
    int x = effectiveRect.x();
    int y = effectiveRect.y();
    int lineHeight = 0;

    // jpo38: store max X
    int maxX = 0;

    for (auto&& item : itemList) {
        QWidget *wid = item->widget();
        int spaceX = horizontalSpacing();
        if (spaceX == -1)
            spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton,QSizePolicy::PushButton,Qt::Horizontal);
        int spaceY = verticalSpacing();
        if (spaceY == -1)
            spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton,Qt::Vertical);
        int nextX = x + item->sizeHint().width() + spaceX;
        if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
            x = effectiveRect.x();
            y = y + lineHeight + spaceY;
            nextX = x + item->sizeHint().width() + spaceX;
            lineHeight = 0;
        }

        if (!testOnly)
            item->setGeometry(QRect(QPoint(x,y),item->sizeHint()));

        // jpo38: update max X based on current position
        maxX = qMax( maxX,x + item->sizeHint().width() - rect.x() + left );

        x = nextX;
        lineHeight = qMax(lineHeight,item->sizeHint().height());
    }

    // jpo38: save height/width as max height/xidth in pMinSize is specified
    int height = y + lineHeight - rect.y() + bottom;
    if ( pMinSize )
    {
        pMinSize->setHeight( height );
        pMinSize->setWidth( maxX );
    }
    return height;
}

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录<future>future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...