MessageDialog-文本从c ++更改,但屏幕上没有更新 [英] MessageDialog - text change from c++ but no update on screen
问题描述
我设法在包含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屋!