Сообщение очень длинное, так как оно содержит много кода, но я чувствую, что моя проблема тривиальна.
Я только начал изучать 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 - нет.
Может ли кто-нибудь указать, что я делаю не так?