Qt5-QML:ColumnLayout 在嵌套循环中覆盖另一个 ColumnLayout

Posted

技术标签:

【中文标题】Qt5-QML:ColumnLayout 在嵌套循环中覆盖另一个 ColumnLayout【英文标题】:Qt5-QML: ColumnLayout is overwriting another ColumnLayout when in a nested loop 【发布时间】:2019-11-29 23:54:12 【问题描述】:

从我的previous post 成功设计一个小型应用程序的布局后,我正在添加事件的逻辑。我几乎完成了它,但有些事件并没有按照我的计划发生。下面的逻辑和完整的源代码here以防万一想验证:

1) 如下图所示,当我选择要连接的机器人后,它确实显示我正在连接,但我根本无法与QML 页面进行交互动作被阻止。我认为这可能是因为我有 2 个 ColumnLayout 并且我认为一个正在覆盖另一个,但我不确定为什么会发生这种情况,因为我认为逻辑是完整的:

预期结果是当我连接到机器人时,整个页面都可以正常工作,而不是(或看起来)被禁用。

在构成问题的Minimal Reproducible Example的代码中最重要的部分下方:

ma​​in.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

int main(int argc, char *argv[])

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) 
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    , Qt::QueuedConnection);
    engine.load(url);
    return app.exec();

ma​​in.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtWebEngine 1.8
import QtQuick.Controls.Styles 1.4

ApplicationWindow 
    id: root
    visible: true
    width: 440
    height: 630
    title: qsTr("Conn")
    property Page1 page1: Page1 
    property Page2 page2: Page2 
    Component.onCompleted: 
        page1.selectDialog.connect(function()  
            mystackview.push(page2);
        );
        page2.onButtonClicked.connect(function(buttonId) 
            page1.dialogId = buttonId;
            mystackview.pop();
        );
    
    StackView 
        id: mystackview
        anchors.fill: parent
        initialItem: page1
    

Page1.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import QtQuick.Controls.impl 2.12  // for IconLabel
import QtWebEngine 1.8

Page 
    property int dialogId: -1
    signal selectDialog()

    function buttonClick(button)
    
        button.text = qsTr("Connecting to %1...").arg(button.text);
        button.enabled = false;
        if (button.background && button.background instanceof Rectangle) 
            button.background.color = "green";
            button.background.gradient = null;
            button.background.visible = true;
        
        if (button.contentItem && button.contentItem instanceof IconLabel) 
            button.contentItem.color = "white";
            button.contentItem.font.bold = true;
            button.contentItem.font.pointSize = 20;
        
    
    function buttonClearList(buttonClear)
    
        buttonClear.text = qsTr("Clear List").arg(buttonClear.text);
        buttonClear.enabled = true;
        if (buttonClear.background && buttonClear.background instanceof Rectangle) 
            buttonClear.background.color = "red";
            buttonClear.background.gradient = null;
            buttonClear.background.visible = true;
        
        if (buttonClear.contentItem && buttonClear.contentItem instanceof IconLabel) 
            buttonClear.contentItem.color = "white";
            buttonClear.contentItem.font.bold = true;
            buttonClear.contentItem.font.pointSize = 20;
        
    
    ColumnLayout 
        // anchors.fill: parent
        // anchors.topMargin: 0 // margin from top of the page
        Layout.fillWidth: true
        width: parent.width
        spacing: 5
        Button 
            id: button1
            text: "Select Robot"
            width: parent.width
            onClicked: selectDialog()
            Layout.fillWidth: true
            font.pointSize: 20
        
        Button 
            id: dialogA
            text: "Freddie Mercury: Connected"
            visible: dialogId === 1
            Layout.fillWidth: true
            font.pointSize: 20
            spacing: 10
            onClicked: 
                buttonClick(this)
            
            ColumnLayout 
                anchors.fill: parent
                anchors.topMargin: 50 // margin from top of the page
                Layout.fillWidth: true
                spacing: 10
                GroupBox 
                    id: box1
                    width: parent.width
                    title: "Connection"
                    font.pointSize: 20
                    Layout.fillWidth: parent
                    spacing: 10
                    GridLayout 
                        width: parent.width
                        columns: 1
                        RowLayout 
                            id: row1
                            spacing: 200
                            Layout.fillWidth: true
                            Layout.fillHeight: false
                            Label 
                                id: textField
                                text: "Connection:"
                                font.pointSize: 15
                                Layout.fillWidth: true
                            
                            Text 
                                id: connected
                                text: "Not-Connected"
                                color: "red"
                                font.pointSize: 15
                                horizontalAlignment: Text.AlignRight
                                Layout.fillWidth: true
                            
                        
                    
                
                Button 
                    id: clist
                    text: "Clear List";
                    Layout.fillWidth: true
                    font.pointSize: 20
                    width: parent.width
                    onClicked: 
                        buttonClearList(this)
                    
                
            
        
    

Page2.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

Page 
    signal onButtonClicked(var buttonId)
    Component.onCompleted: 
        button1.clicked.connect(function() 
            onButtonClicked(1);
        );
    
    ColumnLayout 
        id: mybuttons
        anchors.fill: parent
        spacing: 5
        Button 
            id: button1
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "Freddie Mercury"
            font.pointSize: 20
        
    

到目前为止,我一直在尝试将ColumnLayout 定位在不同位置的非常不同的组合。但我的怀疑是:我已经有一个ColumnLayout,之后我有另一个ColumnLayout,我认为它们正在相互覆盖。 但是,从official documentation 并咨询其他sources 重新在嵌套循环中使用它是没有问题的。 同样的post 谈到ColumnPositioner,而ColumnLayout 是一个布局。 我确定我以正确的方式使用,但缺少一些东西。 请指出正确的方向来解决这个问题。

【问题讨论】:

提供minimal reproducible example @eyllanesc,非常感谢您阅读我的问题,最小可验证示例可以在这里找到https://bitbucket.org/ERaggi/signalsqml/src/master/ 我还更新了添加它的问题,以便它可用 我没有要求你提供链接,我要求你提供一个 MRE,根据定义,它应该是一个代码,应该在你的问题中允许你进行复制粘贴,然后执行它并然后重现您的问题。我认为根据您在该网站上的经验,您知道我的意思。 对不起,给我一分钟 【参考方案1】:

基本设计规则:如果父项也禁用子项。

说明:

在您的情况下, ColumnLayout 是 Button 的子项,这是您的子项的其他项目的容器,因此如果 Button 被前面的 ColumnLayout 规则禁用,它也会被禁用,因此整个ColumnLayout 的内容。

解决方案:

在您的情况下,ColumnLayout 不必是 Button 的子级,但它可以位于同一级别。


另一方面,您还有其他错误:

如果您要使用 Layout.XXX,那么您不应该使用 widths.YYY,因为它们完成相同的任务,但如果您同时使用两者,您可能会遇到问题,因为它的行为可能不确定,因为它们会相互竞争.
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import QtQuick.Controls.impl 2.12  // for IconLabel

Page 
    property int dialogId: -1
    signal selectDialog()

    function buttonClick(button)
    
        button.text = qsTr("Connecting to %1...").arg(button.text);
        button.enabled = false;
        if (button.background && button.background instanceof Rectangle) 
            button.background.color = "green";
            button.background.gradient = null;
            button.background.visible = true;
        
        if (button.contentItem && button.contentItem instanceof IconLabel) 
            button.contentItem.color = "white";
            button.contentItem.font.bold = true;
            button.contentItem.font.pointSize = 20;
        
    
    function buttonClearList(buttonClear)
    
        buttonClear.text = qsTr("Clear List").arg(buttonClear.text);
        buttonClear.enabled = true;
        if (buttonClear.background && buttonClear.background instanceof Rectangle) 
            buttonClear.background.color = "red";
            buttonClear.background.gradient = null;
            buttonClear.background.visible = true;
        
        if (buttonClear.contentItem && buttonClear.contentItem instanceof IconLabel) 
            buttonClear.contentItem.color = "white";
            buttonClear.contentItem.font.bold = true;
            buttonClear.contentItem.font.pointSize = 20;
        
    
    ColumnLayout 
        Layout.fillWidth: true
        width: parent.width
        spacing: 5
        Button 
            id: button1
            text: "Select Robot"
            width: parent.width
            onClicked: selectDialog()
            Layout.fillWidth: true
            font.pointSize: 20
        

        Button 
            id: dialogA
            text: "Freddie Mercury: Connected"
            visible: dialogId === 1
            Layout.fillWidth: true
            font.pointSize: 20
            spacing: 10
            onClicked: 
                buttonClick(this)
            
        
        ColumnLayout 
            id: layout
            visible: dialogId === 1
            Layout.fillWidth: true
            spacing: 10
            GroupBox 
                id: box1
                width: parent.width
                title: "Connection"
                font.pointSize: 20
                Layout.fillWidth: parent
                spacing: 10

                GridLayout 
                    width: parent.width
                    columns: 1
                    RowLayout 
                        id: row1
                        spacing: 200
                        Layout.fillWidth: true
                        Layout.fillHeight: false
                        Label 
                            id: textField
                            text: "Connection:"
                            font.pointSize: 15
                            Layout.fillWidth: true
                        
                        Text 
                            id: connected
                            text: "Not-Connected"
                            color: "red"
                            font.pointSize: 15
                            horizontalAlignment: Text.AlignRight
                            Layout.fillWidth: true
                        
                    
                
            
            Button 
                id: clist
                visible: dialogId === 1
                text: "Clear List";
                Layout.fillWidth: true
                font.pointSize: 20
                width: parent.width
                onClicked: 
                    buttonClearList(this)
                
            
        
    

【讨论】:

以上是关于Qt5-QML:ColumnLayout 在嵌套循环中覆盖另一个 ColumnLayout的主要内容,如果未能解决你的问题,请参考以下文章

在 ColumnLayout 周围添加空间的最佳方法?

QML 将 ColumnLayout 子项堆叠在一起?

如何在 QML 的 ColumnLayout 中使用 topMargin

ScrollView 内的 ColumnLayout 不会调整其内容的大小

QML在Component中使用createObject填充ColumnLayout

如何在 QML 的 ColumnLayout 中使用自己的对象?