MessageDialog-文本从c ++更改,但屏幕上没有更新 [英] MessageDialog - text change from c++ but no update on screen

查看:111
本文介绍了MessageDialog-文本从c ++更改,但屏幕上没有更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法在包含MessageDialog的QML Item中动态更改了几个属性.我可以读取新设置的属性,但它们不会在屏幕上更新-仍然是可见的QML设置的文本.我什至手动发送了textChanged()信号(见下文),但无济于事.

I've managed to dynamically change several properties in a QML Item that contains a MessageDialog. I can read the newly set properties but they are not updated on the screen - it's still the text set by QML which is visible. I've even manually sent a textChanged() signal (see below) to no avail.

知道我想念的是什么吗?这是我的工作:

Any idea what I am missing? Here's what I do:

"ErrorDialog.qml":

"ErrorDialog.qml":

Item{
    id: baseItem
    property string text: "myText"
    property string title: "myTitle"
    signal acceptedSignal()
    onTextChanged: {
        errorDialogItem.text=baseItem.text
    }
    MessageDialog {
        id: errorDialogItem
        objectName: "errorDialogItem"
        text: baseItem.text
        title: baseItem.title
        onAccepted: {
            acceptedSignal()
        }
    Component.onCompleted: visible=true
}

现在使用c ++:

this->component = QSharedPointer<QQmlComponent>(new QQmlComponent(&this->engine));
QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
component->loadUrl(QUrl(QStringLiteral("qrc:///main.qml")));

topLevel = QSharedPointer<QObject>(component->create());
window = qobject_cast<QQuickWindow *>(topLevel.data());

surfaceFormat = window->requestedFormat();
window->setFormat(surfaceFormat);
window->show(); 

QQmlComponent dialogComponent(&engine, QUrl(QStringLiteral("qrc:///ErrorDialog.qml")));
QObject *myObject = dialogComponent.create();
QQuickItem *item = qobject_cast<QQuickItem*>(myObject);

QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership);
qDebug()<<"title"<<item->property("title");
qDebug()<<"text"<<item->property("text");
QString newText="TEXT SET FROM C++";
qDebug()<<"setTextProp: "<<item->setProperty("text",newText);
//-> true
qDebug()<<"new text"<<item->property("text"); 
//-> correctly set!

已设置属性,但外观没有更改. 因此,我获取了嵌入式MessageDialog本身:

property is set, but not visually changed. So I fetch the embedded MessageDialog itself:

QObject* dialogObject=item->findChild<QObject*>("errorDialogItem");
QQuickItem* dialogItem=reinterpret_cast<QQuickItem*>(dialogObject);

item->setFlag(QQuickItem::ItemHasContents,true);
dialogItem->setFlag(QQuickItem::ItemHasContents,true);

我正在尽我所能想到的一切,以便在屏幕上更新文本:

I am doing everything I can currently think of, to get the text updated on Screen:

dialogItem->polish();
item->polish();

int methodIndex=item->metaObject()->indexOfMethod("textChanged()"); 
QMetaMethod method = item->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(item,Qt::DirectConnection);
//-->true

methodIndex=item->metaObject()->indexOfMethod("update()"); 
method = item->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(item,Qt::DirectConnection);
//-->true

methodIndex=dialogItem->metaObject()->indexOfMethod("textChanged()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection);
//-->true   

methodIndex=dialogItem->metaObject()->indexOfMethod("windowGeometryChanged()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection);
//-->true

methodIndex=dialogItem->metaObject()->indexOfMethod("geometryChanged()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection);
//-->true

methodIndex=dialogItem->metaObject()->indexOfMethod("reset()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection);
//-->true

methodIndex=dialogItem->metaObject()->indexOfMethod("setVisible()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection,Q_ARG(bool,falseVar));
//-->false

methodIndex=dialogItem->metaObject()->indexOfMethod("setVisible()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection, Q_ARG(bool,trueVar));
//-->false

methodIndex=dialogItem->metaObject()->indexOfMethod("setText()"); 
method = dialogItem->metaObject()->method(methodIndex);
QString textStr = "a different text";
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection, Q_ARG(QString,textStr));
//-->false

methodIndex=dialogItem->metaObject()->indexOfMethod("polish()"); 
method = dialogItem->metaObject()->method(methodIndex);
qDebug()<<"invoke: "<<method.invoke(dialogItem,Qt::DirectConnection);
//-->false

推荐答案

感谢@BaCaRoZzo,在创建该最小示例时,我发现了问题所在.绝对必须在打开Dialog 之前(即处于关闭状态)进行属性更改.如果要更改已打开的MessageDialog中的内容,则必须将其关闭,更改属性,然后再次将其打开.更改属性然后关闭然后重新打开(例如重新绘制")是不够的.参见

Thanks @BaCaRoZzo, when creating that minimal example I've found out what the problem is. It is absolutely mandatory to do property changes before opening the Dialog, i.e. in a closed state. If I want to change things in a MessageDialog already opened, I have to close it, change the properties and then open it again. It is not sufficient to change properties and then to close and reopen (like a "redraw"). See

bool setItemProperty(QString role, T value)

在下面的.h文件中.

这是我的工作代码,如有任何其他建议,我们将不胜感激.注意:"Controller"类只是提供GUI QQmlApplicationEngine的某些类.

Here is my working code, any further recommendations are gratefully appreciated. Note: the "Controller" class is just some class providing the QQmlApplicationEngine of the GUI.

C ++类头文件:MessageDialog.h

C++-Class header: MessageDialog.h

#ifndef MESSAGEDIALOG_H
#define MESSAGEDIALOG_H
#include <QObject>
#include <QQuickItem>
#include <QDialog>
#include <QQmlApplicationEngine>
#include "src/controller/controller.h"

class MessageDialog : public QObject
{
    Q_OBJECT
public:
    enum StandardButton {
       Ok = 0x00000400,         //  An "OK" button with AcceptRole.
       Open = 0x00002000,       //  An "Open" button with AcceptRole.
       Save = 0x00000800,       //  A "Save" button with AcceptRole.
       Cancel = 0x00400000,     //  A "Cancel" button with RejectRole.
       Close = 0x00200000,      //  A "Close" button with RejectRole.
       Discard = 0x00800000,    //  A "Discard" button, DestructiveRole.
       Apply = 0x02000000,      //  An "Apply" button with ApplyRole.
       Reset = 0x04000000,      //  A "Reset" button with ResetRole.
       RestoreDefaults = 0x08000000,//"Restore Defaults", ResetRole.
       Help = 0x01000000,       //  A "Help" button with HelpRole.
       SaveAll = 0x00001000,    //  A "Save All" button with AcceptRole.
       Yes = 0x00004000,        //  A "Yes" button with YesRole.
       YesToAll = 0x00008000,   //  A "Yes to All" button with YesRole.
       No = 0x00010000,         //  A "No" button with NoRole.
       NoToAll = 0x00020000,    //  A "No to All" button with NoRole.
       Abort = 0x00040000,      //  An "Abort" button with RejectRole.
       Retry = 0x00080000,      //  A "Retry" button with AcceptRole.
       Ignore = 0x00100000,     //  An "Ignore" button with AcceptRole.
       NoButton = 0x00000000    //  An invalid button.
    };
    typedef QFlags<StandardButton> StandardButtons;

    enum ButtonRole {
        InvalidRole = -1,   //button is invalid.
        AcceptRole = 0,     //accepted (e.g. OK).
        RejectRole = 1,     //rejected (e.g. Cancel).
        DestructiveRole = 2,//destructive change 
        ActionRole = 3,     //changes dialog.
        HelpRole =  4,      //request help.
        YesRole =   5,      //Yes"-like button.
        NoRole =    6,      //"No"-like button.
        ApplyRole = 8,      //applies current changes.
        ResetRole = 7       //resets the dialog to default values.
    };
    enum Icon {
        NoIcon = 0,     // the message box does not have any icon.
        Question = 4,   // message is asking a question.
        Information = 1, // message is nothing out of the ordinary.
        Warning = 2,    // message is a warning, but can be dealt with.
        Critical = 3    // message represents a critical problem.
    };

    MessageDialog(Controller* controller,
            QString title=QString(),
            QString text=QString(),
            QString informativeText=QString(),
            QString detailedText=QString(),
            StandardButtons buttons=QFlags<StandardButton>());
    ~MessageDialog();

    void setText (const QString &text);
    void setInformativeText (const QString &text);
    void setDetailedText (const QString &text);
    void setTitle(const QString &title);
    bool open();
    bool close();

    void setStandardButtons(StandardButtons buttons);
    void addButton(StandardButton button);
    void setIcon(Icon icon);
    StandardButton clickedButton();

    void setModality(Qt::WindowModality modality);

    int result();
    StandardButton exec();

    static void about(Controller* controller,
            const QString &title,
            const QString &text,
            const QString &informativeText="",
            const QString &detailedText="");
    static StandardButton warning(
            Controller* controller,
            const QString &title,
            const QString &text,
            const QString &informativeText,
            const QString &detailedText,
            StandardButton button0 = NoButton,
            StandardButton button1 = NoButton,
            StandardButton button2 = NoButton,
            StandardButton button3 = NoButton);

    static MessageDialog::StandardButton information(
            Controller* controller,
            const QString &title,
            const QString &text,
            const QString &informativeText,
            const QString &detailedText,
            StandardButton button0 = NoButton,
            StandardButton button1 = NoButton,
            StandardButton button2 = NoButton,
            StandardButton button3 = NoButton);


signals:
        void buttonClicked(StandardButton standardButton);
        void accepted();
        void apply();
        void discard();
        void help();
        void no();
        void rejected();
        void reset();
        void yes();
public slots:



protected:
    void initItem(Controller* controller);
    void connectQMLSignals();
    bool invokeMethod(QString methodSignature);
    bool setStrings(
            const QString &title,
            const QString &text,
            const QString informativeText,
            const QString detailedText);
    template <typename T>
    bool setItemProperty(QString role, T value) {
        Q_ASSERT(m_item);
        bool wasOpen=m_isOpen;
        close();
        bool success;
        success=m_item->setProperty(role.toLocal8Bit(),QVariant(value));
        if(!success)
            qDebug()<<"setProperty("<<role<<","<<value<<") failed.";
        if (wasOpen) open();
        return success;
    }

    QQmlApplicationEngine* m_engine;
    QQuickItem* m_item;
    bool m_isOpen;
    StandardButtons m_standardButtons;
    StandardButton m_result;
};

#endif // MESSAGEDIALOG_H

C ++类实现:MessageDialog.cpp

C++-Class implementation: MessageDialog.cpp

#include "messagedialog.h"
#include <QQuickItem>
#include <QQmlApplicationEngine>
MessageDialog::MessageDialog(
        Controller *controller,
        QString title,
        QString text,
        QString informativeText,
        QString detailedText,
        StandardButtons buttons)
{
    Q_ASSERT(controller);
    this->initItem(controller);
    m_isOpen=false;
    m_result=MessageDialog::NoButton;
    this->setTitle(title);
    this->setText(text);
    this->setInformativeText(informativeText);
    this->setDetailedText(detailedText);
    this->setStandardButtons(buttons);
    this->connectQMLSignals();
}

MessageDialog::~MessageDialog()
{
    delete m_item;

}

void MessageDialog::setText(const QString &text)
{
    setItemProperty("text",text);
}

void MessageDialog::setInformativeText(const QString &text)
{
    setItemProperty("informativeText",text);
}

void MessageDialog::setDetailedText(const QString &text)
{
    setItemProperty("detailedText",text);
}

void MessageDialog::setTitle(const QString &title)
{
    setItemProperty("title",title);
}

void MessageDialog::setStandardButtons(StandardButtons buttons)
{
    setItemProperty("standardButtons",buttons);
    m_standardButtons=buttons;
}

void MessageDialog::addButton(MessageDialog::StandardButton button)
{
    m_standardButtons|=button;
    setItemProperty("standardButtons",m_standardButtons);
}


void MessageDialog::setIcon(MessageDialog::Icon icon)
{
    setItemProperty("icon",icon);
}

MessageDialog::StandardButton MessageDialog::clickedButton()
{
    int i=m_item->property("clickedButton").toInt();
    return static_cast<MessageDialog::StandardButton>(i);
}

void MessageDialog::setModality(Qt::WindowModality modality)
{
    setItemProperty("modality",modality);
}

int MessageDialog::result()
{
    return this->clickedButton();
}

MessageDialog::StandardButton MessageDialog::exec()
{
    QEventLoop loop;

    connect(m_item, SIGNAL(accepted()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(apply()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(discard()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(help()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(no()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(rejected()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(reset()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    connect(m_item, SIGNAL(yes()),& loop,
           SLOT(quit()),Qt::UniqueConnection);
    invokeMethod("open()");
    setModality(Qt::ApplicationModal);
    loop.exec();
    return this->clickedButton();
}

void MessageDialog::about(
        Controller *controller,
        const QString &title,
        const QString &text,
        const QString &informativeText,
        const QString &detailedText)

{
    MessageDialog dialog(controller);
    dialog.setStrings(title,text,informativeText,detailedText);
    dialog.setIcon(MessageDialog::Information);
    dialog.setStandardButtons(Ok);
    dialog.exec();
}

MessageDialog::StandardButton MessageDialog::warning(
        Controller *controller,
        const QString &title,
        const QString &text,
        const QString &informativeText,
        const QString &detailedText,
        MessageDialog::StandardButton button0,
        MessageDialog::StandardButton button1,
        MessageDialog::StandardButton button2,
        MessageDialog::StandardButton button3)
{
    MessageDialog dialog(controller);
    dialog.setStrings(title,text,informativeText,detailedText);
    dialog.setIcon(MessageDialog::Warning);
    dialog.setStandardButtons(
           StandardButtons(button0|button1|button2|button3));
    dialog.exec();
    return dialog.clickedButton();
}

MessageDialog::StandardButton MessageDialog::information(
        Controller *controller,
        const QString &title,
        const QString &text,
        const QString &informativeText,
        const QString &detailedText,
        MessageDialog::StandardButton button0,
        MessageDialog::StandardButton button1,
        MessageDialog::StandardButton button2,
        MessageDialog::StandardButton button3)
{
    MessageDialog dialog(controller);
    dialog.setStrings(title,text,informativeText,detailedText);
    dialog.setIcon(MessageDialog::Information);
    dialog.setStandardButtons(
           StandardButtons(button0|button1|button2|button3));
    dialog.exec();
    return dialog.clickedButton();
}

bool MessageDialog::open()
{
    Q_ASSERT(m_item);
    if (m_isOpen) return false;
    m_isOpen=invokeMethod("open()");
    return m_isOpen;
}

bool MessageDialog::close()
{
    Q_ASSERT(m_item);
    if (!m_isOpen) return false;
    m_isOpen=!invokeMethod("close()");
    return !m_isOpen;
}

bool MessageDialog::invokeMethod(QString methodSignature)
{
    Q_ASSERT(m_item);
    int methodIndex;
    methodIndex=m_item->metaObject()->indexOfMethod(
                                       methodSignature.toLocal8Bit());
    QMetaMethod method = m_item->metaObject()->method(methodIndex);
    return method.invoke(m_item,Qt::DirectConnection);
}

bool MessageDialog::setStrings(
        const QString &title,
        const QString &text,
        const QString informativeText,
        const QString detailedText)
{
    bool success=true;
    success &= this->setItemProperty("title",title);
    success &= this->setItemProperty("text",text);
    success &= this->setItemProperty("informativeText",informativeText);
    success &= this->setItemProperty("detailedText",detailedText);
    return success;
}

void MessageDialog::initItem(Controller *controller)
{
    m_engine=controller->engine();
    Q_ASSERT(m_engine);
    QQmlComponent* myComponent=new QQmlComponent(
           m_engine, QUrl(QStringLiteral("qrc:/MessageDialog.qml")));
    Q_ASSERT(myComponent);
        if (!myComponent->isReady()) {
        qWarning("%s", qPrintable(myComponent->errorString()));
    }
    QObject *myObject = myComponent->create();
    Q_ASSERT(myObject);
    m_item = qobject_cast<QQuickItem*>(myObject);
    Q_ASSERT(m_item);
    QQmlApplicationEngine::setObjectOwnership(
               m_item,QQmlApplicationEngine::CppOwnership);

}

void MessageDialog::connectQMLSignals()
{
    connect(m_item, SIGNAL(accepted()),this, SIGNAL(accepted()));
    connect(m_item, SIGNAL(apply()),this, SIGNAL(apply()));
    connect(m_item, SIGNAL(discard()),this, SIGNAL(discard()));
    connect(m_item, SIGNAL(help()),this, SIGNAL(help()));
    connect(m_item, SIGNAL(no()),this, SIGNAL(no()));
    connect(m_item, SIGNAL(rejected()),this, SIGNAL(rejected()));
    connect(m_item, SIGNAL(reset()),this, SIGNAL(reset()));
    connect(m_item, SIGNAL(yes()),this, SIGNAL(yes()));
}

这是对应的MessageDialog.qml

And this is the correspondent MessageDialog.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2
Item{
    id: baseItem
    property alias text: errorDialogItem.text
    property alias detailedText: errorDialogItem.detailedText
    property alias informativeText: errorDialogItem.informativeText
    property alias title: errorDialogItem.title
    property alias modality: errorDialogItem.modality
    property alias standardButtons: errorDialogItem.standardButtons
    property alias icon: errorDialogItem.icon
    property alias clickedButton: errorDialogItem.clickedButton
    property alias standardIconSource: 
                       errorDialogItem.standardIconSource

    signal accepted()
    signal apply()
    signal discard()
    signal help()
    signal no()
    signal rejected()
    signal reset()
    signal yes()


    function open() {
        return errorDialogItem.open()
    }
    function close() {
        return errorDialogItem.close()
    }
    MessageDialog {
        id: errorDialogItem
        objectName: "errorDialogItem"

        onAccepted: baseItem.accepted()
        onApply: baseItem.apply()
        onDiscard: baseItem.discard()
        onHelp: baseItem.help()
        onNo: baseItem.no()
        onRejected: baseItem.rejected()
        onReset: baseItem.reset()
        onYes: baseItem.yes()

    }

}

我希望这可以帮助将来节省时间.

I hope this might help somebody save time in the future.

这篇关于MessageDialog-文本从c ++更改,但屏幕上没有更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆