强制固定宽高比时如何阻止窗口大小跳跃?

时间:2016-11-04 09:59:57

标签: qt window qml qtquick2 aspect-ratio

这是我的测试代码:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    visible: true
    readonly property int defaultWidth: 700
    readonly property int defaultHeight: 500
    width: defaultWidth
    height: defaultHeight

    readonly property real aspectRatio: defaultWidth / defaultHeight
    readonly property real scaleFactor: width / defaultWidth

    onWidthChanged: {
        var properHeight = Math.round(width / aspectRatio);
        if ( height !== properHeight ) {
            height = properHeight
        }
    }
    onHeightChanged: {
        var properWidth = Math.round(height * aspectRatio);
        if ( width !== properWidth ) {
            width = properWidth
        }
    }

    TextEdit {
        id: textEdit
        text: "Lorem ipsum"
        font.pixelSize: 40 * scaleFactor
        anchors.fill: parent
    }
}

它实现了固定的宽高比,但它不能很好地工作:有一种闪烁(窗口大小在固定宽高比大小和鼠标大小调整大小之间跳跃),它可能调整错误尺寸取决于宽度和高度变化事件的顺序。实际上,当以编程方式调整大小时,窗口边缘可能会开始在鼠标光标位置和编程设置之间跳转,位置不同。

应该发生的是,拖动的窗口边缘应该跟随鼠标光标(就像任何调整大小一样),其他边缘应该改变以保持宽高比:

  • 如果用户拖动左/右边缘,则应移动底边以保持纵横比。
  • 如果用户拖动顶部/底部边缘,则右边缘也应移动以保持纵横比。
  • 当用户拖动角落时,可以采用两种可能的尺寸来保持纵横比,因为可以通过编程方式更改高度或宽度。只要它是一致的,如何确定这一点并不重要。
  • 没关系,如果仅在调整大小后停止宽高比,虽然实时会更好。但是如何可靠地检测调整大小何时实际停止?
  • 如果不能单独使用Qt,我对Windows和X11 / Linux特定解决方案都感兴趣。

如何在保留纵横比的同时实现调整大小,使用本机窗口调整大小控件(正常窗口边框或平台使用的任何内容),以便它在逻辑上运行并且看起来不错

编辑,"提示":我有时间做一些研究,覆盖QQuickView::resizeEvent并从那里调用resize似乎能够做到这一点,但我没有&# 39;没有时间让它正常工作。

2 个答案:

答案 0 :(得分:3)

我曾经遇到过这样的问题,我最终得到了鸡肉或鸡蛋等#34;矛盾,所以我完全禁用了窗口装饰,并自定义了大小调整条。这建立了从把手到尺寸的适当价值流,没有它,流量是尺寸的尺寸,如果这有任何意义......

如果移除窗框对你来说不是问题,你可以这样做,对我而言,因为我一直在寻找自定义和平台独立的外观,所以窗框实际上是应用程序:

Window {
    id: main
    visible: true
    width: 500
    height: 250
    flags: Qt.FramelessWindowHint | Qt.Window

    MouseArea {
      width: 20
      height: 20
      anchors.bottom: parent.bottom
      anchors.right: parent.right
      onPositionChanged: {
        var w = mouseX + x, h = mouseY + y
        if (w > (h * 2)) {
          main.width = w
          main.height = w * .5
        } else {
          main.height = h
          main.width = h * 2
        }
      }
      Rectangle {
        anchors.fill: parent
        color: "red"
      }
    }
}

这只是一个微不足道的例子,显然在一个完整的解决方案中,你应该做所有的方方面面。宽高比固定为2/1。

在我的系统上,整个窗口仍然有一些闪烁,但我认为这只是场景图,但是"尺寸在跳跃"问题得到有效解决。

编辑:

为了澄清,我的意思是"流程是维度的尺寸"是句柄操纵维度,你挂钩到changed处理程序......进行更改。我怀疑这就是为什么它的表现如此脆弱。如果是这样,为了采用窗框进行尺寸调整,必须切断手柄和窗户尺寸之间的连接以在其间插入纵横比代码。不幸的是,过滤掉QGuiApplication级别的resize事件并没有阻止调整大小,但可能还有另一种方法可以做到这一点,例如覆盖类。

答案 1 :(得分:1)

好的,这是一个可能的解决方法。它不会尝试控制窗口大小,而是在窗口内添加额外的项目,然后包含UI的其余部分,并保持所需的宽高比:如果窗口宽高比不同,则上面有空白区域内容区域的下方或左侧和右侧,用窗口颜色绘制(此处为“灰色”)。内容区域在此处填充“黄色”以显示差异。

import QtQuick 2.4
import QtQuick.Window 2.2

Window {

    readonly property int defaultWidth: 700
    readonly property int defaultHeight: 500
    readonly property real defaultAspectRatio: defaultWidth / defaultHeight

    readonly property real aspectRatio: width / height
    readonly property real scaleFactor: content.width / defaultWidth

    visible: true
    width: defaultWidth
    height: defaultHeight
    color: "gray"

    Item {
        id: content
        anchors.centerIn: parent
        width: (aspectRatio > defaultAspectRatio)
               ? parent.height * defaultAspectRatio
               : parent.width
        height: (aspectRatio < defaultAspectRatio)
                ? parent.width / defaultAspectRatio
                : parent.height

        Rectangle { color: "yellow"; anchors.fill: parent } // just to show the effect

        TextEdit {
            clip: true // text drawing needs to be clipped explicitly
            id: textEdit
            text: "Lorem ipsum"
            font.pixelSize: 40 * scaleFactor
            anchors.fill: parent
        }
    }
}

但这只是一种解决方法,而不是问题中要求的完整解决方案,所以问题仍然存在。