5

私はこのコードを持っています:

import QtQuick 2.3
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2

Dialog {
    standardButtons: StandardButton.Ok | StandardButton.Cancel

    width: layout.implicitWidth
    height: layout.implicitHeight

    RowLayout {
        id: layout
        anchors.fill: parent

        Item {
            width: 10
            height: 1
        }

        GridLayout {
            columns: 2
            rowSpacing: 10

            Layout.fillHeight: true
            Layout.fillWidth: true

            Text {
                text: "Hello world? "
            }
            Text {
                text: "Hello world!"
            }

            Text {
                text: "Goodbye world? "
            }
            Text {
                text: "Goodbye world!"
            }

        }

        Item {
            width: 10
            height: 1
        }
    }
}

実行するとこのようになり、ダイアログは任意のサイズに変更できます。また、ご覧のとおり、RowLayout実際にはその親を埋めません。

くそ お願いします

ダイアログがレイアウトの最小サイズを下回るサイズに変更できず、レイアウトがダイアログを埋めるようにするにはどうすればよいですか?

4

2 に答える 2

6

残念ながら、これは Qt のバグです。現在、ドキュメントは誤解を招きやすく、内容に合わせてサイズが正しくありDialogません。に基づいたこの実用的な例を考えてみましょうDefaultFontDialog:

AbstractDialog {
    title: "Hello"
    id: root
//  standardButtons: StandardButton.Ok | StandardButton.Cancel
    modality: Qt.NonModal
    Rectangle {
        id: content
        implicitWidth: mainLayout.implicitWidth + outerSpacing * 2
        implicitHeight: mainLayout.implicitHeight + outerSpacing * 2

        property real spacing: 6
        property real outerSpacing: 12

        color: "white"
        GridLayout {
            id: mainLayout
            anchors { fill: parent; margins: content.outerSpacing }
            rowSpacing: content.spacing
            columnSpacing: content.spacing
            columns: 5

            Text { text: "Hello" } Text { text: "Hello" } Text { text: "Hello"  } Text { text: "Hello" } Text { text: "Hello" }
            Text { text: "Hello" } Text { text: "Hello" } Text { text: "Hello"  } Text { text: "Hello" } Text { text: "Hello" }
            Text { text: "Hello" } Text { text: "Hello" } Text { text: "Hello"  } Text { text: "Hello" } Text { text: "Hello" }
            Text { text: "Hello" } Text { text: "Hello" } Text { text: "Hello"  } Text { text: "Hello" } Text { text: "Hello" }
        }
    }
}

もちろん、ボタンは表示されませんが、これは期待どおりに機能します。

に変更して のDialogコメントを外すだけではstandardButtons、機能しなくなります。ダイアログのサイズを変更して、その内容を (少なくとも幅方向に) クリップすることができますが、内容はダイアログのサイズに拡大されません。

最小幅が機能しない理由は、Dialog(in qtquickcontrols/src/dialogs/DefaultDialogWrapper.qml)のソース コードを見ると明らかになります。

AbstractDialog {
    id: root
    default property alias data: defaultContentItem.data
    onVisibilityChanged: if (visible && contentItem) contentItem.forceActiveFocus()

    Rectangle {
        id: content
        property real spacing: 6
        property real outerSpacing: 12
        property real buttonsRowImplicitWidth: minimumWidth
        property bool buttonsInSingleRow: defaultContentItem.width >= buttonsRowImplicitWidth
        property real minimumHeight: implicitHeight
        property real minimumWidth: Screen.pixelDensity * 50
        implicitHeight: defaultContentItem.implicitHeight + spacing + outerSpacing * 2 + buttonsRight.implicitHeight
        implicitWidth: Math.min(root.__maximumDimension, Math.max(
            defaultContentItem.implicitWidth, buttonsRowImplicitWidth, Screen.pixelDensity * 50) + outerSpacing * 2);

minimumWidthScreen.pixelDensity * 50!!にハードコードされています。ダイアログの内容と一致するという希望はまったくありませんでした。minimumHeightよりうまく機能します(完璧ではありませんが、間隔が考慮されていないためだと思います)。

defaultContentItem が正しく展開されない理由はわかりませんが、とにかく。現時点での唯一の解決策はAbstractDialog、ボタンとaccepted()/rejected()などを使用して実装することです。自分に合図します。少し痛い。

編集/解決策

さらに調査を行いました。

  1. defaultContentItem が展開されない理由は、下部のアンカーがボタン行の上部に関連付けられていないためです。

    Item {
        id: defaultContentItem
        anchors {
            left: parent.left
            right: parent.right
            top: parent.top
            margins: content.outerSpacing
        }
        implicitHeight: childrenRect.height
    }
    
  2. アンカーベースのレイアウトでは、最小サイズはうまく機能しません。それらは GridLayout ベースのレイアウトで行います。

  3. 残念ながら、childrenRect には暗黙の Width/Height がないため、実際には子項目を ColumnLayout ではなく ColumnLayout に配置する必要があります。

...

import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2

// A Dialog that resizes properly. The defualt dialog doesn't work very well for this purpose.
AbstractDialog {
    id: root
    default property alias data: defaultContentItem.data
    onVisibilityChanged: if (visible && contentItem) contentItem.forceActiveFocus()

    Rectangle {
        id: content
        property real spacing: 6
        property real outerSpacing: 12
        property real buttonsRowImplicitWidth: minimumWidth
        property bool buttonsInSingleRow: defaultContentItem.width >= buttonsRowImplicitWidth
        property real minimumHeight: implicitHeight
        property real minimumWidth: implicitWidth // Don't hard-code this.
        implicitWidth: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 10, mainLayout.implicitWidth + outerSpacing * 2))
        implicitHeight: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 10, mainLayout.implicitHeight + outerSpacing * 2))
        color: palette.window
        Keys.onPressed: {
            event.accepted = true
            switch (event.key) {
                case Qt.Key_Escape:
                case Qt.Key_Back:
                    reject()
                    break
                case Qt.Key_Enter:
                case Qt.Key_Return:
                    accept()
                    break
                default:
                    event.accepted = false
            }
        }

        SystemPalette { id: palette }

        // We use layouts rather than anchors because there are no minimum widths/heights
        // with the anchor system.
        ColumnLayout {
            id: mainLayout
            anchors { fill: parent; margins: content.outerSpacing }
            spacing: content.spacing

            // We have to embed another item so that children don't go after the buttons.
            ColumnLayout {
                id: defaultContentItem
                Layout.fillWidth: true
                Layout.fillHeight: true
            }

            Flow {
                Layout.fillWidth: true

                id: buttonsLeft
                spacing: content.spacing

                Repeater {
                    id: buttonsLeftRepeater
                    Button {
                        text: (buttonsLeftRepeater.model && buttonsLeftRepeater.model[index] ? buttonsLeftRepeater.model[index].text : index)
                        onClicked: root.click(buttonsLeftRepeater.model[index].standardButton)
                    }
                }

                Button {
                    id: moreButton
                    text: qsTr("Show Details...")
                    visible: false
                }
            }

            Flow {
                Layout.fillWidth: true

                id: buttonsRight
                spacing: content.spacing
                layoutDirection: Qt.RightToLeft

                Repeater {
                    id: buttonsRightRepeater
                    // TODO maybe: insert gaps if the button requires it (destructive buttons only)
                    Button {
                        text: (buttonsRightRepeater.model && buttonsRightRepeater.model[index] ? buttonsRightRepeater.model[index].text : index)
                        onClicked: root.click(buttonsRightRepeater.model[index].standardButton)
                    }
                }
            }
        }
    }
    function setupButtons() {
        buttonsLeftRepeater.model = root.__standardButtonsLeftModel()
        buttonsRightRepeater.model = root.__standardButtonsRightModel()
        if (!buttonsRightRepeater.model || buttonsRightRepeater.model.length < 2)
            return;
        var calcWidth = 0;

        function calculateForButton(i, b) {
            var buttonWidth = b.implicitWidth;
            if (buttonWidth > 0) {
                if (i > 0)
                    buttonWidth += content.spacing
                calcWidth += buttonWidth
            }
        }

        for (var i = 0; i < buttonsRight.visibleChildren.length; ++i)
            calculateForButton(i, buttonsRight.visibleChildren[i])
        content.minimumWidth = calcWidth + content.outerSpacing * 2
        for (i = 0; i < buttonsLeft.visibleChildren.length; ++i)
            calculateForButton(i, buttonsLeft.visibleChildren[i])
        content.buttonsRowImplicitWidth = calcWidth + content.spacing
    }
    onStandardButtonsChanged: setupButtons()
    Component.onCompleted: setupButtons()
}

通常の とは少し違った使い方をする必要がありますDialog。想像してみてくださいColumnLayout(これは元の質問とは少し異なる例です):

ColumnLayoutDialog {
    id: dialog1
    standardButtons: StandardButton.Ok | StandardButton.Cancel

    Text {
        text: "Hello world? "
    }
    Text {
        text: "Hello world!"
    }

    // Spacer.
    Item {
        Layout.fillHeight: true;
    }

    Text {
        text: "Goodbye world? "
    }
    Text {
        text: "Goodbye world!"
    }
}

ところで、必要に応じてColumnLayoutを aに変更してプロパティGridLayoutを公開することもできます。columnsそのほうが理にかなっているかもしれません。

小さな問題

の最小幅と高さは、ダイアログがQWindowそのコンテンツよりも小さいサイズに積極的にサイズ変更されないことを保証するだけであることがわかりました。ダイアログが作成された後にコンテンツが大きくなる可能性があるため (余分なアイテムが追加されるなど)、ダイアログがそのコンテンツよりも小さくなることはありません。これを回避するために、この関数を my に追加しましたColumnLayoutDialog:

// The minimumWidth/Height values of content are accessed by the C++ class, but they
// only ensure that the window isn't resized to be smaller than its content. They
// don't ensure that if the content grows the window grows with it.
function ensureMinimumSize()
{
    if (root.width < content.minimumWidth)
        root.width = content.minimumWidth;
    if (root.height < content.minimumHeight)
        root.height = content.minimumHeight;
}

ダイアログの内容を変更するときは、手動で呼び出す必要があります。contentまたは、これを自動的に行うには、これを長方形に追加できます。

    onMinimumHeightChanged: {
        if (root.height < content.minimumHeight)
            root.height = content.minimumHeight;
    }
    onMinimumWidthChanged: {
        if (root.width < content.minimumWidth)
            root.width = content.minimumWidth;
    }
于 2015-06-10T11:13:26.570 に答える
1

これは、バージョン 5.6.0 までの QT のバグです。おそらくバグ番号 49058です。質問のコードは、QT 5.6.1 および 5.7.0 で期待どおりに動作します。

古いバージョンの部分的な回避策は、行を削除することです

width: layout.implicitWidth
height: layout.implicitHeight

そして交換

anchors.fill: parent

anchors.right: parent.right
anchors.left: parent.left

ダイアログは最小の高さを尊重し、コンテンツは水平方向に拡張されます。

これも完全な回避策ですが、文書化されていない Dialog の実装の詳細に依存しているため、注意して使用する必要があります。5.5.1、5.6.0、5.6.1、および 5.7.0 で動作します。また、動作をより明確にするために、2 番目のアイテムが赤い Rectangle に変更されていることにも注意してください。

import QtQuick 2.3
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2

Dialog {
    visible: true
    standardButtons: StandardButton.Ok | StandardButton.Cancel

    RowLayout {
        id: layout

        // In the horizontal direction, expansion and shrinking can be achieved with anchors.
        anchors.left: parent.left
        anchors.right: parent.right

        // Used only for guessing the height of the Dialog's standard buttons.
        Button {
            id: hiddenButton
            visible: false
        }

        // Repeats until the relevant parts of the dialog (parent of the parent of the RowLayout)
        // are complete, then overwrites the minimum width and implicit height and stops repeating.
        Timer {
            id: timer
            interval: 50; running: true; repeat: true;
            onTriggered: {
                if(layout.parent.parent) {
                    var lp = layout.parent
                    var lpp = layout.parent.parent
                    lpp.minimumWidth = layout.implicitWidth + 2 * lpp.outerSpacing
                    layout.buttonHeight = 2 * lpp.outerSpacing + hiddenButton.implicitHeight + lpp.spacing
                    lp.implicitHeight = layout.implicitHeight + 2 * lpp.outerSpacing
                    running = false
                }
            }
        }

        // The guessed space needed for the Dialog's buttons.
        property int buttonHeight: 80

        // Expand and shrink vertically when the dialog is resized.
        height: parent.parent ? Math.max(parent.parent.height-buttonHeight, implicitHeight) : implicitHeight

        Item {
            width: 10
            height: 1
        }

        GridLayout {
            columns: 2
            rowSpacing: 10

            Layout.fillHeight: true
            Layout.fillWidth: true

            Text {
                text: "Hello world? "
            }
            Text {
                text: "Hello world!"
            }

            Text {
                text: "Goodbye world? "
            }
            Text {
                text: "Goodbye world!"
            }

        }

        Rectangle {
            Layout.fillHeight: true
            color: 'red'
            width: 10
        }
    }
}
于 2016-12-02T12:12:42.967 に答える