2015-12-17 12 views
9

Ho un oggetto C++ esposto a QML con una proprietà di tipo "sola lettura", eccetto che la proprietà deve ancora essere impostata da QML, quindi ha un WRITE metodo definito, ma diverso da obbligatorio, l'impostazione non cambia mai, quindi mi sento come un NOTIFY è ridondante, in quanto avrà già quel valore impostato al momento del suo utilizzo, e non cambierà mai.Come gestire l'avviso "dipende da proprietà non NOTIFYable"

Tuttavia, QML non condivide le mie impressioni e, indipendentemente da ciò, emette un avviso "Espressione dipende da proprietà non NOTIFICABILI".

A causa del modo in cui gli oggetti vengono istanziati utilizzando una proprietà è l'unico modo applicabile di impostare quel valore, non è possibile utilizzare un setter invocabile in quanto tale richiederebbe che l'oggetto sia già "completato" e non possa realmente completarsi senza quel valore. Quindi la necessità del meccanismo di proprietà e di un metodo WRITE, che sfortunatamente porta Qt a credere che la proprietà cambierà. Ho provato a impostare la proprietà come CONSTANT ma non sembra impilare con il metodo WRITE.

Ho messo un segnale fittizio come misura temporanea per gestire il flusso di avvisi, ma preferirei se ci fosse un modo più elegante per affrontare questo. Anche in questo caso, il design stesso elimina praticamente la possibilità di impostare questo valore dopo l'impostazione iniziale, ma poiché si tratta di un oggetto C++ e il valore deve essere impostato su una base per oggetto, non è applicabile neanche a un QML readonly property. C'è un aggiramento per questo che non coinvolge il segnale ridondante?


solo per chiarire, il problema di fondo qui è che nel suo stato attuale, QML ha praticamente alcun modo per inizializzare una proprietà di sola lettura di un oggetto, implementato in C++. Una proprietà di questo tipo non avrebbe un setter (se dovesse quindi sputare l'avviso "dipende da ..."), e non c'è modo di passare un valore al costruttore dell'oggetto. Come descritto nella mia risposta qui sotto, ci sono degli hack in giro, ma sono limitati nell'applicazione o piuttosto scomodi. In C++ è possibile eseguire anche l'inizializzazione dei membri const su una base per istanza passando il valore al costruttore che esegue l'inizializzazione nell'elenco di inizializzazione, ma non in QML. Anche in QML puro, le proprietà di sola lettura devono essere inizializzate sul posto, non è possibile lasciarle non inizializzate (readonly property type name senza : statement) e ritardarle fino all'istanziazione e ottenere l'inizializzazione peristanza (Obj { name : initValue }). Si potrebbe fare questo:

Item { // T.qml 
    readonly property int r : w 
    property int w 
} 
... 
T { w: value } 

ma ... un po 'contrasta con l'obiettivo ... E considerando che una proprietà può essere "legato" solo una volta nel corpo della sua esemplificazione, credo che questo potrebbe essere visto come atto di inizializzazione, mentre è vietato un ulteriore incarico o una riconferma imperativa (Qt.binding()). Un setter senza il segnale di notifica ridondante farebbe il trucco, tuttavia il progetto di implementazione di qtquick presuppone che se ha un setter cambierà, quindi si lamenterà che non ha un segnale di notifica, che IMO è una supervisione del progetto - cioè , non fornendo alcun modo per inizializzare una proprietà di sola lettura sul lato QML per ogni istanza. E attualmente, come ho già detto, le 3 possibili soluzioni sono o con overhead (hanno un segnale di notifica), limitazioni (valore impostato prima della creazione dell'oggetto - applicabile solo per l'istanziazione dinamica) o maggiori inconvenienti (usare setter e slot getter senza implementare l'effettivo interfaccia di proprietà).

risposta

0

Una possibile soluzione è quella di avere solo un setter e le funzioni getter esposte a QML, ma senza la proprietà effettiva. È un po 'meno elegante e più dettagliato (un extra ()), ma almeno si occupa dello spam di avviso nella console.Probabilmente finirà per essere più efficiente, poiché oltre a eliminare il segnale ridondante, potrebbero esserci meno osservatori di rivalutazione delle espressioni vincolanti.

C'è anche un altro modo, ma funziona solo per creare oggetti dinamicamente - non funzionerà se si creano gli oggetti in modo dichiarativo. Questo approccio implica il richiamo di una funzione prima di ogni creazione di un oggetto, tale funzione imposta un valore membro statico, che il costruttore dell'oggetto utilizza come parametro implicito per inizializzare la proprietà di sola lettura. Quindi diventa ovvio perché questo può funzionare solo per oggetti che vengono creati dinamicamente, nell'altro caso non si arriva a chiamare la funzione e si imposta il valore prima che venga invocato il costruttore dell'oggetto.

1

Dipende un po 'da quello che ti serve il valore.

Se la proprietà viene utilizzata in qualsiasi legame di proprietà, è necessario ricevere la notifica, altrimenti si finisce in una situtazione in cui si fa affidamento sull'ordine di istanze di oggetti e valutazioni di associazione.

E.g. se viene utilizzato in un binding altrove senza avere un segnale di notifica associato, si fa affidamento sull'impostazione iniziale che si verifica prima che tale associazione venga valutata per la prima volta.

Se, d'altra parte, il valore viene utilizzato solo per inizializzare il lato C++ ma non viene mai utilizzato in QML altrove, è possibile considerare l'utilizzo di una funzione/slot "setter".

+0

Se il valore non cambia mai, non è necessario alcun preavviso. Naturalmente, questo impone l'impostazione iniziale, il problema è che, a prescindere da ciò, se non ha un segnale di notifica, Qt si lamenta a riguardo. È solo una delle numerose sviste progettuali di qml che ho incontrato. Nel mio caso è stato un ID unico che persiste in tutte le sessioni. Una volta impostato, non cambierà mai ... mai. Sfortunatamente, qtquick non ha la nozione di "sarà impostato una volta e non cambierà mai", quindi impone il segnale fasullo di notifica, o per implementare è come un getter di slot invece di una proprietà. – dtech

+0

Non cambiare mai ed essere impostato è una contraddizione. È un valore fisso o può essere impostato. Il primo non ha bisogno di un segnale di notifica poiché la proprietà può essere contrassegnata come costante, il secondo ha bisogno di un modo per notificare al motore quando il valore cambia. Anche una singola modifica è una modifica –

+0

Se il valore fisso non può essere impostato mai, allora è completamente inutile e inutile, poiché non sarà mai possibile impostarlo su un valore significativo, sarebbe solo indefinito e indeterminato. Ciò che è diverso sui valori const non è che non possano essere impostati, ma che possano essere impostati solo una volta. In C++ puoi impostare i membri const nella lista di inizializzazione del costruttore. Quindi dico "controllo del design", poiché con QML non si riesce a passare dati al costruttore e non c'è praticamente alcun modo di inizializzare una proprietà di sola lettura di un oggetto C++ in QML. – dtech

Problemi correlati