2015-03-03 8 views
9

Scrivo codice Qt5 per principianti su OSX Mavericks e desidero sovrascrivere solo una proprietà: coppia di valori di StyleSheet per un determinato widget.Come eseguire l'override di una sola proprietà: coppia di valori in Qt StyleSheet

Se corro il seguente codice dimostrativo autosufficiente:

#include <QApplication> 
#include <QMainWindow> 
#include <QtGui> 
#include <QPushButton> 

int 
main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 

    QMainWindow* mw = new QMainWindow(); 

    QPushButton* AButton = new QPushButton("A Button", mw); 

    mw->show(); 

    return app.exec(); 
} 

ottengo un bel pulsante con Macintosh default stile - angoli arrotondati, di colore blu-OSX standard quando premuto, ecc .:

QPushButton with OSX defaults

Se però ho impostato il foglio di stile per rendere il colore pulsante di sfondo rosso, sembra perdo tutte le altre impostazioni predefinite OSX stile nel processo - senza angoli più arrotondati, i margini standard, ecc .:

#include <QApplication> 
#include <QMainWindow> 
#include <QtGui> 
#include <QPushButton> 

int 
main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 

    QMainWindow* mw = new QMainWindow(); 

    QPushButton* AButton = new QPushButton("A Button", mw); 

    AButton->setStyleSheet("QPushButton { background-color: red; }"); 

    mw->show(); 

    return app.exec(); 
} 

Ecco il risultato:

QPushButton style override, with loss of other OSX defaults

Come posso sostituire solo una proprietà: coppia di valori, preservando il resto degli elementi di stile per il widget, ad esempio, nell'esempio precedente, il colore dello sfondo diventa rosso ma mantenere tutti gli arrotondamenti dei bordi, i margini ecc. lo stesso?

Grazie molto

+0

Si potrebbe provare ad aggiungere il nuovo stile a quello esistente con 'AButton-> setStyleSheet (AButton-> styleSheet() +" ... ");' – leemes

+0

Grazie, tuttavia, sembra ancora di ignorare tutta l'altra piattaforma impostazioni predefinite (ho usato 'AButton-> setStyleSheet (AButton-> styleSheet() +" QPushButton {background-color: red;} ");') – lcikgl

+1

Ah wait ... Ciò di cui stai parlando non sono attributi di stile CSS che ottengono sovrascritto, ma lo * stile di sistema * Il motore di stile di QtWidget tenta di imitare. Non può simulare lo stile del sistema quando si specificano manualmente alcuni attributi, AFAIK, e si riduce a un "vecchio stile di Windows" quando il motore di stile non riesce ad adattare l'attributo CSS specificato. Prova invece a usare le tavolozze. Date un'occhiata a 'QWidget :: setPalette()' e 'palette()', quindi provate a impostare i colori per alcuni ruoli (giocare attorno al quale si usano gli sfondi dei pulsanti, non me lo ricordo). Questo sarà quindi considerato dal motore di stile. – leemes

risposta

4

L'analisi nel commento che una chiamata a QApplication::setStyleSheet() sostituirà completamente lo stile attualmente attivo non è corretto. Hai ragione che uno stile attuale viene sostituito con QStyleSheetStyle. Tuttavia, QStyleSheetStyle delega il suo disegno allo stile originale, nel tuo caso lo stile Mac. Se guardi lo source of QStyleSheetStyle, lo vedrai in molti posti, chiamate allo baseStyle()->drawControl().

Ciò significa che i fogli di stile funzionano su qualsiasi stile. Ora, chiaramente non ha funzionato nel tuo caso, quindi cosa è successo? QStyleSheetStyle torna al disegno in stile Windows se le regole del foglio di stile non possono essere applicate allo stile di base. Ciò significa che alcune regole del foglio di stile funzionano bene, mentre altre attiveranno il fallback. Le tue regole hanno innescato il fallback.

Non penso sia documentato quali regole attivano il fallback. Per questo abbiamo bisogno di guardare la fonte, in questo caso QStyleSheetStyle::drawControl(). Troveremo il seguente in là:

case CE_PushButton: 
    if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 
     if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() || 
       ((btn->features & QStyleOptionButton::HasMenu) && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator))) { 
      ParentStyle::drawControl(ce, opt, p, w); 
      return; 
     } 
    } 

ParentSyle è lo stile di Windows fallback. La regola background-color restituisce true rule.hasPalette(), attivando quindi il fallback.

2

Come illuminato nel post parallelamente How to obtain entire Qt StyleSheet for QMacStyle, la mia domanda iniziale era basata sulla premessa confuso.

In Qt, tutti i widget sono in stile tramite QStyle(). Per impostazione predefinita per il codice Qt su OSX (come nel mio primo blocco di codice dimostrativo nella domanda originale), i widget Qt sono disegnati da una sottoclasse di QStyle() denominata QMacStyle() (attualmente apparentemente un derivato di QProxyStyle(), per la pagina QMacStyle -- File Not Found).

La chiamata di funzione setStyleSheet(), come nel mio secondo blocco di codice di dimostrazione nella domanda originale, crea un'istanza di QStyleSheetStyle(), che quindi sostituisce in anticipo qualsiasi QStyle era in uso per il widget - in questo caso il simpatico QMacStyle che speravo di conservare. Uno può vedere i dettagli di implementazione per questo in, ad es. qtbase/src/widgets/kernel/qapplication.cpp nel metodo QApplication::setStyleSheet(). QStyleSheetStyle() stesso è in qtbase/src/widgets/styles/qstylesheetstyle.cpp. Come punto di riferimento, QStyleSheetStyle() è derivato da QWindowsStyle(), da cui l'aspetto windows-ish al pulsante modificato nella mia domanda originale.

La storia breve è che Qt StyleSheets è implementato su QStyle(). Chiamando setStyleSheet() si decide implicitamente che si utilizzerà QStyleSheetStyle() anziché QMacStyle().

Il messaggio da portare a casa è che quando si impostano i widget è necessario scegliere il proprio approccio, con i compromessi in entrambi i casi. È necessario scegliere quale QStyle() si intende utilizzare. Se esegui il codice predefinito su Mac, hai scelto di iniziare da QMacStyle(). È quindi possibile modificare tale QStyle() per documentazione esistente. Se invochi setStyleSheet(), hai scelto implicitamente di avviare QStyleSheetStyle(), che per impostazione predefinita ha l'aspetto di QWindowsStyle(). Qualsiasi valore di proprietà del foglio di stile che applichi modificherà tale aspetto.

Per la mia domanda come sopra, ci sono due scelte. Uno è che una persona potrebbe apportare tutte le modifiche di aspetto attraverso i meccanismi disponibili attraverso QStyle(). Come farlo è documentato altrove.L'altra opzione sarebbe quella di generare da zero un foglio di stile che riproducesse il look and feel del Mac in questione, quindi modificarlo con le modifiche desiderate e applicarlo tramite setStyleSheet().

In un mondo ideale qualcuno sarebbe già passato attraverso quell'esercizio - cioè digerito qtbase/src/widgets/styles/qmacstyle_mac.mm nel suo equivalente di fogli di stile - tuttavia quel lavoro sembra oneroso e non sembra come se qualcuno lo abbia fatto, almeno non con pubblico distacco. Suppongo che un'altra possibile alternativa sia quella di reimplementare QStyleSheetStyle in base a QMacStyle anziché a QWindowsStyle, quindi in qualche modo integrare nuovamente il risultato nel codice (magari con un setStyleSheet (QStyle * baseStyle, QString styleSheet)). Ciò tuttavia è ben al di là delle competenze Qt dei principianti, per non parlare della missione attuale.

Problemi correlati