Список кнопок Qml не отображается при использовании повторителя - PullRequest
0 голосов
/ 28 мая 2020

Сообщение очень длинное, так как оно содержит много кода, но я чувствую, что моя проблема тривиальна.

Я только начал изучать Qt Qml, следуя книге Николаса Шерифа: Build современные, отзывчивые кроссплатформенные настольные приложения с Qt, C ++ и QML , из которых исходит вся идея.

Следуя идее авторов, я пытаюсь реализовать контекстно-зависимые кнопки, которые будут отображаться в разные представления.

Для этого я реализовал класс Command, который представляет одну кнопку:

#ifndef COMMAND_H
#define COMMAND_H

#include <functional>

#include <QObject>
#include <QScopedPointer>
#include <QString>

#include <cms-lib_global.h>

namespace cms {
namespace framework {

class CMSLIBSHARED_EXPORT Command : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString ui_iconCharacter READ iconCharacter CONSTANT)
    Q_PROPERTY(QString ui_description READ description CONSTANT)
    Q_PROPERTY(bool ui_canExecute READ canExecute NOTIFY canExecuteChanged)

public:
    explicit Command(QObject* parent = nullptr,
                     const QString& iconCharacter = "",
                     const QString& description = "",
                     std::function<bool()> canExecute = [](){ return true; });
    ~Command();

    const QString& iconCharacter() const;
    const QString& description() const;
    bool canExecute() const;

signals:
    void canExecuteChanged();
    void executed();

private:
    class Implementation;
    QScopedPointer<Implementation> implementation;
};

}
}


#endif // COMMAND_H



//command.cpp

#include "command.h"

namespace cms {
namespace framework {

class Command::Implementation{
public:
    QString iconCharacter;
    QString description;
    std::function<bool()> canExecute;

    Implementation(const QString& _iconCharacter,
                   const QString& _description,
                   std::function<bool()> _canExecute)
        : iconCharacter(_iconCharacter),
          description(_description),
          canExecute(_canExecute) {}

};

Command::Command(QObject* parent, const QString& iconCharacter,
                 const QString& description, std::function<bool()> canExecute)
    : QObject(parent){
    implementation.reset(new Implementation(iconCharacter, description, canExecute));
}

Command::~Command()
{
}

const QString& Command::iconCharacter() const
{
    return implementation->iconCharacter;
}

const QString& Command::description() const
{
    return implementation->description;
}

bool Command::canExecute() const
{
    return implementation->canExecute();
}

}
}


Класс Command обрабатывается в классе CommandController:

#ifndef COMMANDCONTROLLER_H
#define COMMANDCONTROLLER_H


#include <QObject>
#include <QtQml/QQmlListProperty>

#include <cms-lib_global.h>
#include <framework/command.h>


namespace cms {
namespace controllers {

class CMSLIBSHARED_EXPORT CommandController : public QObject{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<cms::framework::Command>
               ui_createPatientViewContextCommands READ
               ui_createPatientViewContextCommands CONSTANT)
public:
    explicit CommandController(QObject* _parent = nullptr);
    ~CommandController();

    QQmlListProperty<cms::framework::Command> ui_createPatientViewContextCommands();
public slots:
    void onCreateClientSaveExecuted();

private:
    class Implementation;
    QScopedPointer<Implementation> implementation;
};

}
}

#endif // COMMANDCONTROLLER_H

//commandcontroller.cpp

#include "commandcontroller.h"

#include <QList>
#include <QDebug>

using namespace cms::framework;

namespace cms{
namespace controllers{

class CommandController::Implementation{

public:
    //Controller
    CommandController* commandController {nullptr};
    //Commands
    QList<Command*> createClientViewContextCommands{};


    Implementation(CommandController* _commandController) :
        commandController(_commandController)
    {

        Command* createClientSaveCommand = new Command(commandController,
                                                       QChar( 0xf0c7 ),
                                                       "Save");

        QObject::connect(createClientSaveCommand,
                         &Command::executed,
                         commandController,
                         &CommandController::onCreateClientSaveExecuted);

        createClientViewContextCommands.append(createClientSaveCommand);

    }


};

CommandController::CommandController(QObject* parent) : QObject(parent){
    implementation.reset(new Implementation(this));
}

CommandController::~CommandController(){

}

QQmlListProperty<Command> CommandController::ui_createPatientViewContextCommands(){
    return QQmlListProperty<Command>(this, implementation->createClientViewContextCommands);
}

void CommandController::onCreateClientSaveExecuted(){
    qDebug() << "You executed the Save command!";
}


}
}


После этого я зарегистрировал оба созданных типа в Qml внутри main. cpp:

 qmlRegisterType<cms::framework::Command>("CMS", 1, 0, "Command");
 qmlRegisterType<cms::controllers::CommandController>("CMS", 1, 0, "CommandController");

Я создал 2 компонентных файла Qml и успешно (по крайней мере, я так думаю) экспортировал их в свой модуль компонентов:

//CommandBar.qml
import QtQuick 2.12
import assets 1.0

Item {
    property alias commandList: commandRepeater.model

    anchors {
        left: parent.left
        bottom: parent.bottom
        right: parent.right
    }

    height: Style.heightCommandBar

    Rectangle {
        anchors.fill: parent
        color: Style.colorCommandBarBackground

        Row {
            anchors {
                top: parent.top
                bottom: parent.bottom
                right: parent.right
            }

            Repeater {
                id: commandRepeater
                delegate: CommandButton {
                    command: modelData
                }
            }
        }
    }
}


//CommandButton.qml

import QtQuick 2.12
import CMS 1.0
import assets 1.0

Item {
    property Command command
    width: Style.widthCommandButton
    height: Style.heightCommandButton

    Rectangle {
        id: background
        anchors.fill: parent
        color: Style.colorCommandBarBackground

        //Command button icon
        Text {
            id: textIcon

            anchors {
                centerIn: parent
                verticalCenterOffset: -10
            }
            font {
                family: Style.fontAwesomeSolid
                pixelSize: Style.pixelSizeCommandBarIcon
            }

            color: command.ui_canExecute ? Style.colorCommandBarFont : Style.colorCommandBarFontDisabled

            text: command.ui_iconCharacter
            horizontalAlignment: Text.AlignHCenter
        }

        //Command button description
        Text {
            id: textDescription

            anchors {
                top: textIcon.bottom
                bottom: parent.bottom
                left: parent.left
                right: parent.right
            }

            font.pixelSize: Style.pixelSizeNavigationBarText

            color: command.ui_canExecute ? Style.colorCommandBarFont : Style.colorCommandBarFontDisabled
            text: command.ui_description
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
        }

        MouseArea {
            anchors.fill: parent
            cursorShape: Qt.PointingHandCursor
            hoverEnabled: true
            onEntered: background.state = "hover"
            onExited: background.state = ""
            onClicked: if(command.ui_canExecute) {
                           command.executed();
                       }
        }

        states: [
            State {
                name: "hover"
                PropertyChanges {
                    target: background
                    color: Qt.darker(Style.colorCommandBarBackground)
                }
            }

        ]
    }
}

Я использовал созданные компоненты внутри CreatePatientView.qml

import QtQuick 2.12
import assets 1.0
import components 1.0

Item {

    Rectangle {
        anchors.fill: parent
        color: Style.colorBackground
        Text {
            anchors.centerIn: parent
            text: "Create patient view"
        }
    }

    CommandBar {
        commandList: masterController.ui_commandController.ui_createClientViewContextCommands
    }

}

И использовал представление внутри MasterView.qml

Для Вначале я пытаюсь отобразить одну кнопку «сохранить» (значок + описание) на моем CreatePatientView, прежде чем я добавлю больше кнопок.

К сожалению, кнопка значок + описание не отображается, область наведения мыши не нет ни того ни другого. Я новичок в Qml и пользовательском интерфейсе, поэтому я не могу понять, в чем может быть проблема.

Извините за много кода, но я просто не знаю, где мне искать источник проблемы.

С уважением.

РЕДАКТИРОВАТЬ:

После некоторого рытья я обнаружил следующее:

  • , если CommandButton объявлен явно вне CommandBar , и инициализируется с использованием псевдонимов, кнопка заполняется и отображается правильно - поэтому я думаю, что моя проблема связана с заполнением CommandButton с помощью Repeater ИЛИ отображением ее в строке в CommandBar.qml

  • I поместили простые журналы консоли onCompleted внутри CommandBar и CommandButton root Item - если я НЕ использую какие-либо явные CommandButtons, кроме тех, которые заполнены метаданными, CommandBar qml читается, а CommandButton - нет.

Может ли кто-нибудь указать, что я делаю не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...