2014-11-23 24 views
9

Desidero utilizzare il tipo ComboBox nel mio progetto. È possibile modificare l'aspetto del menu a discesa (colore, forma, stile del testo) o devo utilizzare una combinazione di rettangoli, ListView s e altri tipi?QML elemento ComboBox stile DropDownMenu

Il codice seguente applica personalizzazioni ma nessuna modifica è definito per il menu a discesa che rimane grigio:

ComboBox { 
    currentIndex: 2 
    activeFocusOnPress: true 
    style: ComboBoxStyle { 
     id: comboBox 
     background: Rectangle { 
      id: rectCategory 
      radius: 5 
      border.width: 2 
      color: "#fff" 

      Image { 
       source: "pics/corner.png" 
       anchors.bottom: parent.bottom 
       anchors.right: parent.right 
       anchors.bottomMargin: 5 
       anchors.rightMargin: 5 
      } 
     } 
     label: Text { 
      verticalAlignment: Text.AlignVCenter 
      horizontalAlignment: Text.AlignHCenter 
      font.pointSize: 15 
      font.family: "Courier" 
      font.capitalization: Font.SmallCaps 
      color: "black" 
      text: control.currentText 
     } 
    } 

    model: ListModel { 
     id: cbItems 
     ListElement { text: "Banana" } 
     ListElement { text: "Apple" } 
     ListElement { text: "Coconut" } 
    } 
    width: 200 
} 

risposta

11

Le attuali API pubbliche non consentono la personalizzazione del menu a discesa come indicato here. Qt 5.4, ovvero Styles 1.3, ha appena introdotto alcune proprietà per personalizzare i caratteri e il testo (documenti here) ma ancora nessun accesso pubblico alla personalizzazione del menu a discesa.

Inoltre, l'esempio fornito nel collegamento non funziona con le versioni più recenti di Qt. Ecco una versione modificata che ho provato con Qt 5.3, Qt 5.4 e Qt 5.5 (ricordati di aggiungerlo import QtQuick.Controls.Private 1.0 alle importazioni):

ComboBox { 
    id: box 
    currentIndex: 2 
    activeFocusOnPress: true 
    style: ComboBoxStyle { 
     id: comboBox 
     background: Rectangle { 
      id: rectCategory 
      radius: 5 
      border.width: 2 
      color: "#fff" 
     } 
     label: Text { 
      verticalAlignment: Text.AlignVCenter 
      horizontalAlignment: Text.AlignHCenter 
      font.pointSize: 15 
      font.family: "Courier" 
      font.capitalization: Font.SmallCaps 
      color: "black" 
      text: control.currentText 
     } 

     // drop-down customization here 
     property Component __dropDownStyle: MenuStyle { 
      __maxPopupHeight: 600 
      __menuItemType: "comboboxitem" 

      frame: Rectangle {    // background 
       color: "#fff" 
       border.width: 2 
       radius: 5 
      } 

      itemDelegate.label:    // an item text 
       Text { 
       verticalAlignment: Text.AlignVCenter 
       horizontalAlignment: Text.AlignHCenter 
       font.pointSize: 15 
       font.family: "Courier" 
       font.capitalization: Font.SmallCaps 
       color: styleData.selected ? "white" : "black" 
       text: styleData.text 
      } 

      itemDelegate.background: Rectangle { // selection of an item 
       radius: 2 
       color: styleData.selected ? "darkGray" : "transparent" 
      } 

      __scrollerStyle: ScrollViewStyle { } 
     } 

     property Component __popupStyle: Style { 
      property int __maxPopupHeight: 400 
      property int submenuOverlap: 0 

      property Component frame: Rectangle { 
       width: (parent ? parent.contentWidth : 0) 
       height: (parent ? parent.contentHeight : 0) + 2 
       border.color: "black" 
       property real maxHeight: 500 
       property int margin: 1 
      } 

      property Component menuItemPanel: Text { 
       text: "NOT IMPLEMENTED" 
       color: "red" 
       font { 
        pixelSize: 14 
        bold: true 
       } 
      } 

      property Component __scrollerStyle: null 
     } 
    } 

    model: ListModel { 
     id: cbItems 
     ListElement { text: "Banana" } 
     ListElement { text: "Apple" } 
     ListElement { text: "Coconut" } 
    } 
    width: 200 
}  

Qui __dropDownStyle viene assegnato con un tipo MenuStyle. Alcune proprietà di questo tipo sono personalizzate per ottenere lo stile desiderato, in particolare itemDelegate (che definisce l'aspetto di un elemento all'interno della casella combinata) e frame (sfondo generale). Fare riferimento alle API collegate MenuStyle per ulteriori dettagli. Risultato complessivo:

enter image description here

noti che questo approccio non perfettamente funziona su Windows e Android, mentre su OSX il codice è completamente ignorato . È possibile controllare il file di stile qml all'interno dell'installazione Qt (cercare un sottotracciato come qml/QtQuick/Controls/Styles/Desktop) per vedere quali modifiche vengono apportate a w.r.t. Windows e prova ad adattare la soluzione fornita. Questa parte è lasciata al lettore.

+0

Ho appena provato questo codice su Mac OS X 10.9 e si chiese che non funziona per me. Potresti suggerirmi alcune modifiche relative a OS X per far funzionare tutto questo. Tuttavia, sulla piattaforma Windows va tutto bene. –

+0

Bene, ho provato il codice solo su Windows/Android al momento, mi dispiace. :) È possibile controllare il file di stile qml all'interno dell'installazione Qt (cercare un sottotracciato come 'qml/QtQuick/Controls/Styles/Desktop') per vedere quali modifiche cambiano. Windows e prova ad adattare la soluzione. Da parte mia testerò il codice sul mio Mac per fornire una modifica che risolva questo problema specifico (ovviamente perché ho tempo libero). – BaCaRoZzo

+1

Questo è così incredibilmente utile! Grazie! –

4

Grazie mille! Ho risolto questo codice successivo:

Item { 
id: app 
width: 200 
height: 150 

ListModel{ 
    id: dataModel 
    ListElement{ name: "Day" } 
    ListElement{ name: "Week" } 
    ListElement{ name: "Month" } 
    ListElement{ name: "Year" } 
} 

Button { 
    id: comboButton 
    width: parent.width 
    height: parent.height/5 
    checkable: true 

    style: ButtonStyle { 
     background: Rectangle { 
      color: control.pressed ? "#888" : "#fff" 
      smooth: true 
      radius: 5 
      border.width: 2 

      Image { 
       source: "pics/corner.png" 
       anchors.bottom: parent.bottom 
       anchors.right: parent.right 
       anchors.bottomMargin: 5 
       anchors.rightMargin: 5 
      } 
     } 
     label: Text { 
      renderType: Text.NativeRendering 
      verticalAlignment: Text.AlignVCenter 
      horizontalAlignment: Text.AlignHCenter 
      font.family: "Courier" 
      font.capitalization: Font.SmallCaps 
      font.pointSize: 15 
      color: "black" 
      text: "Day" 
     } 
    } 
    onVisibleChanged: { 
     if(!visible) 
      checked = false 
    } 
} 

TableView { 
    id: tableView 
    height: 120 
    width: parent.width 
    anchors.bottom: parent.bottom 
    highlightOnFocus: true 
    headerVisible: false 
    visible: comboButton.checked ? true : false 

    TableViewColumn { 
     role: "name" 
    } 
    model: dataModel 

    itemDelegate: Item { 
     Rectangle { 
      color: styleData.selected ? "#888" : "#fff" 
      height: comboButton.height - 0.5 
      border.width: 0.5 
      width: parent.width 

      Text { 
       renderType: Text.NativeRendering 
       anchors.verticalCenter: parent.verticalCenter 
       anchors.horizontalCenter: parent.horizontalCenter 
       font.family: "Courier" 
       font.capitalization: Font.SmallCaps 
       font.pointSize: 15 
       color: "black" 
       elide: styleData.elideMode 
       text: styleData.value 
      } 
     } 
    } 

    rowDelegate: Item { 
     height: comboButton.height - 0.5 
    } 

    onClicked: { 
     comboButton.checked = false 
     tableView.selection.clear() 
    } 
} 
} 

enter image description here

+0

Ottimo risultato. :) – BaCaRoZzo

+0

Questa è la risposta molto migliore. Grazie per quello! –

0

Sto usando approcci del genere, ma hanno un sacco di limitazioni con focus gestione e z-index gestione.

Mi sono ritrovato con l'implementazione di ComboBox che consiste di 2 parti: un'intestazione che viene effettivamente inserita da qualche parte e un componente a discesa creato in modo dinamico. Quest'ultimo è costituito da un Item che copre tutto (e intercetta l'attività del mouse) e un menu a discesa che viene accuratamente posizionato sotto l'intestazione.

codice è piuttosto massiccia a inclusi qui in modo da poter vedere i dettagli in my blogpost with all the code