在前面,我會道歉: 這是一個可怕的問題,但我想提供我希望的所有相關細節。
我有一個基于 QML 的 GUI,我的任務是接管和開發從概念驗證到發布的程序。我相信 GUI 是基于 QT 提供的示例(也許是汽車?)。GUI 正在為 web-assembly (emscripten) 進行編譯,并具有一個“后端資料客戶端”,它通過套接字與我們的硬體控制器通信,并通過信號與 GUI 通信。GUI 可通過 Web 瀏覽器訪問并與Data_Clientvia 進行通信QWebSocket。

GUI 證明最初是使用非常“扁平”的層次結構創建的,其中每個元素都是在ApplicationWindow單個“主”QML 檔案中的單個物件中創建和管理的。在那里實體化一個Data_Client物件,所有其他視覺元素都是 的子級(在各個級別)ApplicationWindow:
ApplicationWindow {
id: appWindow
//various properties and stuff
Item {
id: clientHolder
property Data_Client client
}
ColumnLayout {
id: mainLayout
anchors.fill: parent
layoutDirection: Qt.LeftToRight
//And so on...
C 當前發出各種信號以回應控制器應用程式中發生的Data_Client各種事情。在主 .QML 中,信號處理如下:
Connections {
target: client
onNew_status_port_data:
{
textStatusPort.text = qdata;
}
onNew_status_data_act_on:
{
imageStatusData.source = "../imagine-assets/ledGoodRim.png";
}
//and so on...
我要做的是創建一個物件,該物件包含各種狀態欄位并在從后端ChannelStatusPanel接收資訊時處理這些欄位(文本、影像等)的更新。在 main 中可見或不可見的 a 中包含Data_Clientthis 的多個實體:ChannelStatusPanelMainStatusPanelApplicationWindow

說了這么多(呸!),我終于來回答我的問題了。使用驅動更改視覺元素所需的各種資料項來指示ChannelStatusPanel物件的特定實體的正確方法是什么?Data_ClientChannelStatusPanel
我認為我通過定義 aChannelStatusObject來保存值很聰明:
Item {
id: channelStatusObject
property int channel
property int enabled //Using the EnabledState enum
property string mode
property int bitrate
property int dataActivity //Using the LedState enum
//and more...
property int packetCount
}
在 中ChannelStatusPanel.qml,然后我創建了一個ChannelStatusObject屬性和一個插槽來處理屬性更改:
property ChannelStatusObject statusObject
onStatusObjectChanged: {
//..do the stuff
From the Data_Client C I will get the information from the controller application and determine which "channel" I need to update. As I see it, I need to be able to do the following things:
- I need to determine which instance of
ChannelStatusPanelI need to update. How do I intelligently get a reference to the instance I want to signal? Is that just accomplished throughQObject::findChild()? Is there a better, faster, or smarter way? - In the
Data_ClientC , do I want to create an instance ofChannelStatusObject, set the various fields within it appropriately, and then set theChannelStatusPanelinstance'sChannelStatusObjectproperty equal to the newly createdChannelStatusObject? Alternatively, is there a mechanism to get a reference to the Panel'sChannelStatusObjectand set each of its properties (fields) to what I want? In C , something like this:
QQmlComponent component(&engine, "ChannelStatusObject.qml");
QObject *statObj= component.create();
QQmlProperty::write(statObj, "channel", 1)
QQmlProperty::write(statObj, "bitrate", 5000);
QQmlProperty::write(statObj, "enabled", 0);
//Then something like using the pointer from #1, above, to set the Panel property
//QObject *channelPanel;
QQmlProperty::write(channelPanel, "statusObject", statObj)
Is there some other, more accepted or conventional paradigm for doing this? Is this too convoluted?
uj5u.com熱心網友回復:
下面是我如何設定我的應用程式。
前端在 QML 中。后端使用 Qt C 。硬體控制器應用程式是 C 語言。
在 Qt C 后端,我有 QObject 派生的資料庫和 databasePoint 類。
資料庫物件擁有一個由 databasePoint 物件組成的 QMap。
每個 databasePoint 物件都有一個唯一的點名稱,用作識別符號。
資料庫物件在 main.cpp 中創建并作為背景關系屬性暴露給 QML。
資料庫類有一個方法可以回傳指向 databasePoint 物件的指標。
在 QML 中,此方法用于創建 databasePoint 物件。
呼叫此方法時,會創建一個 databasePoint 物件并將其添加到 QMap(如果它尚不存在)。
databasePoint 類具有讀寫值屬性。
這些屬性用于 UI、后端和控制器之間的通信。
在計時器中,會定期從控制器輪詢最新值,只要有變化,就會更新 value 屬性。
當從 UI 更新 value 屬性時,會將 value 寫入控制器。
class database : public QObject
{
public slots:
databasePoint* getDbpointObject(QString pointName);
private:
QMap<QString, databasePoint*> dbPointMap;
};
class databasePoint : public QObject
{
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
public:
QVariant value(void);
void setValue(QVariant value);
QVariant my_value;
signals:
void valueChanged();
};
DatabasePointComponent.qml:
Item {
required property string pointName
property var pointObj: database.getDbpointObject(pointName)
}
MyScreen.qml:
DatabasePointComponent{
id: dbTEMP
pointName: "TEMP"
}
TextInput {
text: dbTEMP.pointObj.value
onAccepted: dbTEMP.pointObj.value = text
}
uj5u.com熱心網友回復:
我將使用 Qt 的模型-視圖-控制器(委托)范例來解決這個問題。也就是說,您的 C 代碼應該公開一些類似串列Q_PROPERTY的通道狀態物件,這些物件又將自己的資料作為屬性公開。這可以使用 a 來完成QQmlListProperty,如此處所示。
但是,如果串列本身是由 C 代碼控制的——也就是說,QML 代碼不需要直接編輯模型,而只需控制在視圖中顯示哪些并可能修改現有元素——那么它可以是像QListofQObject派生指標一樣簡單。只要您在更改串列時確實發出信號,這應該沒問題:
class ChannelStatus : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(int channel READ channel CONSTANT)
Q_PROPERTY(int enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
// etc.
};
class Data_Client : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QList<ChannelStatus*> statusList READ statusList NOTIFY statusListChanged)
// ...
};
list 屬性型別需要在應用程式的 main 函式中注冊為元型別,以使 QML 知道它:
qRegisterMetaType<QList<ChannelStatus*>>();
否則,它只會識別實際QObject指標的串列,您必須照此提供。
然后,您可以在 QML 端使用客戶端的此屬性作為model合適 QML 組件的屬性,例如容器內的aListView或 a 。例如:RepeaterRowLayout
ListView {
model: client.statusList
delegate: Column {
Label { text: modelData.channel }
Image { source: modelData.enabled ? "foo" : "bar" }
// ...
}
}
如您所見,模型資料隱式附加到委托組件。任何NOTIFY有能力的屬性都會自動更新其值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/417438.html
標籤:
