2015-03-26 25 views
10

Potrzebuję dać użytkownikowi możliwość wyboru daty i czasu w aplikacji QML. Dla dat wyboru dostępny jest Calendar w QtQuick Controls. Nie znalazłem podobnej kontroli, aby pozwolić użytkownikowi wybrać porę dnia.Selektor czasu w QML

W Internecie istnieje kilka przykładów, takich jak Grog lub Harmattan. Zakładam jednak, że nie integrują się z rodzimym wyglądem i czują się tak, jak robią to inne kontrolki QtQuick.

Czy istnieje standardowe podejście, którego nie znam, dobre alternatywy, z którymi się nie spotkałem lub zalecenia, które wybrać?

Odpowiedz

17

Od Qt 5.5 tak zwana Qt Quick Enterprise Controls będzie dostępna również w edycji wspólnotowej Qt pod nazwą Qt Quick Extras. Między innymi, Tumbler wydaje się być wykonalnym rozwiązaniem dla twoich wymagań: możesz łatwo ustawić dwie kolumny, jedną dla godzin i jedną dla minut.

Jeśli nadal jesteś zainteresowany kołowego wyboru (lub chce zaimplementować własną szklankę) można podjąć różne trasy, takie jak stworzyć własny element dziedziczy z QQuickItem lub QQuickPaintedItem lub wykorzystywanie niestandardowego widoku z PathView. Ta ostatnia sytuacja ma miejsce w tej odpowiedzi. Wystarczy zapoznać się z zamieszczonymi linkami w celu uzyskania przykładów tworzenia niestandardowych komponentów.

Powołując dokumentację PathView:

Widok ma modelu, który definiuje dane mają być wyświetlane i delegata, który określa w jaki sposób dane powinny być wyświetlane. Delegat tworzy instancję dla każdego elementu na ścieżce. Elementy można przesuwać, przesuwając wzdłuż ścieżki.

W związku z tym ścieżka określa sposób układania przedmiotów na ekranie, nawet w cykliczny sposób. Ścieżka może być zbudowana za pomocą typu Path, tj. Sekwencji segmentów ścieżki różnego rodzaju. PathArc to ten, który nas interesuje, ponieważ zapewnia pożądany zaokrąglony kształt.

Następujący przykład wykorzystuje te elementy do zdefiniowania kołowego selektora czasu. Każda ścieżka jest konstruowana przez wykorzystanie elementu currentIndex elementu delegowanego: liczba całkowita jest używana jako model dla widoku godzinowego i 6 dla widoku minut. Tekst delegatów generowany jest przez wykorzystanie załączonej właściwości i manipulowanie nią w celu wygenerowania godzin i 10-minutowych wartości interwałów (patrz elementy delegatów: Text). Na koniec tekst bieżącego elementu (tj. currentItem) jest powiązany z etykietą czasu w środku okna: wraz ze zmianą currentIndex i currentItem również etykieta jest aktualizowana.

Ogólnym komponent wygląda następująco:

enter image description here

highlight składniki (niebieskie i zielone kółka) są wykorzystywane do graficznie reprezentujących edycji po raz: gdy widoczny czas może być edytowany, czyli kolejna Item od ścieżka może być wybrana. Przełączanie między trybem normalnym a trybem edycji następuje po kliknięciu etykiety czasu w środku.

W trybie edycji użytkownik może po prostu najechać kursorem na różne wartości godzin/minut, aby je wybrać. Jeśli kliknięta zostanie nowo wybrana godzina/minuta, edycja dla tego konkretnego PathView jest wyłączona i odpowiedni krąg podświetlenia znika.

Ten kod jest oczywiście tylko zabawnym przykładem, który daje pojęcie o tym, do czego można użyć PathView. Można wprowadzić kilka ulepszeń, np. animacje, lepsze pozycjonowanie liczb, szczegółowa reprezentacja minut, ładne tło i tak dalej. Są one jednak poza zakresem w.r.t. pytanie i nie zostały uwzględnione.

import QtQuick 2.4 
import QtQuick.Window 2.2 
import QtQuick.Controls.Styles 1.3 
import QtQuick.Layouts 1.1 

Window { 
    visible: true 
    width: 280; height: 280 

    RowLayout {    // centre time label 
     anchors.centerIn: parent 
     Text { 
      id: h 
      font.pixelSize: 30 
      font.bold: true 
      text: outer.currentItem.text 
     } 
     Text { 
      id: div 
      font.pixelSize: 30 
      font.bold: true 
      text: qsTr(":") 
     } 
     Text { 
      id: m 
      font.pixelSize: 30 
      font.bold: true 
      text: inner.currentItem.text 
     } 

     MouseArea { 
      anchors.fill: parent 
      onClicked: outer.choiceActive = inner.choiceActive = !outer.choiceActive 
     } 
    } 


    PathView {   // hours path 
     id: outer 
     property bool pressed: false 
     model: 12 

     interactive: false 
     highlightRangeMode: PathView.NoHighlightRange 
     property bool choiceActive: false 

     highlight: Rectangle { 
      id: rect 
      width: 30 * 1.5 
      height: width 
      radius: width/2 
      border.color: "darkgray" 
      color: "steelblue" 
      visible: outer.choiceActive 
     } 

     delegate: Item { 
      id: del 
      width: 30 
      height: 30 
      property bool currentItem: PathView.view.currentIndex == index 
      property alias text : textHou.text 
      Text { 
       id: textHou 
       anchors.centerIn: parent 
       font.pixelSize: 24 
       font.bold: currentItem 
       text: index + 1 
       color: currentItem ? "black" : "gray" 
      } 

      MouseArea { 
       anchors.fill: parent 
       enabled: outer.choiceActive 
       onClicked: outer.choiceActive = false 
       hoverEnabled: true 
       onEntered: outer.currentIndex = index 
      } 
     } 

     path: Path { 
      startX: 200; startY: 40 
      PathArc { 
       x: 80; y: 240 
       radiusX: 110; radiusY: 110 
       useLargeArc: false 
      } 
      PathArc { 
       x: 200; y: 40 
       radiusX: 110; radiusY: 110 
       useLargeArc: false 
      } 
     } 
    } 

    PathView {   // minutes path 
     id: inner 
     property bool pressed: false 
     model: 6 
     interactive: false 
     highlightRangeMode: PathView.NoHighlightRange 
     property bool choiceActive: false 

     highlight: Rectangle { 
      width: 30 * 1.5 
      height: width 
      radius: width/2 
      border.color: "darkgray" 
      color: "lightgreen" 
      visible: inner.choiceActive 
     } 

     delegate: Item { 
      width: 30 
      height: 30 
      property bool currentItem: PathView.view.currentIndex == index 
      property alias text : textMin.text 
      Text { 
       id: textMin 
       anchors.centerIn: parent 
       font.pixelSize: 24 
       font.bold: currentItem 
       text: index * 10 
       color: currentItem ? "black" : "gray" 
      } 

      MouseArea { 
       anchors.fill: parent 
       enabled: inner.choiceActive 
       onClicked: inner.choiceActive = false 
       hoverEnabled: true 
       onEntered: inner.currentIndex = index 
      } 
     } 

     path: Path { 
      startX: 140; startY: 60 
      PathArc { 
       x: 140; y: 220 
       radiusX: 40; radiusY: 40 
       useLargeArc: false 
      } 
      PathArc { 
       x: 140; y: 60 
       radiusX: 40; radiusY: 40 
       useLargeArc: false 
      } 
     } 
    } 

    // to set current time! 
    onVisibleChanged: { 
     var d = new Date(); 
     outer.currentIndex = d.getUTCHours() % 12 
     inner.currentIndex = d.getMinutes()/10 
    } 
} 
+2

Dobra odpowiedź :-) –

+0

Dziękuję bardzo za kompleksową odpowiedź. Jak tylko będę mógł to zweryfikować, zaakceptuję to. –

+0

Nie martw się. :) Starałem się być w zasięgu z odpowiedzią i przedstawiłem kilka zaleceń bardziej niż gotowe do użycia rozwiązanie. Jeśli masz ochotę na integrację z treścią, poproś o nią. – BaCaRoZzo