यह पोस्ट "
स्मार्ट फोन फॉर स्मार्ट पोस्ट " प्रतियोगिता में भाग लेती है


तस्वीर में बाईं ओर आप देख सकते हैं कि मानक
Nokia MeeGo हरमाटन अनुप्रयोगों में
TimePicker (समय सेटिंग घटक) कैसा दिखता है। और दाईं ओर
MeeGo Qt Components (Extras) का
टाइमपिकर है, जो डेवलपर्स को उपयोग के लिए दिया जाता है। चेहरे पर अंतर।
निश्चित रूप से, यह स्पष्ट हो जाता है कि एक निश्चित अन्याय है, क्योंकि नोकिया द्वारा उपयोग किया जाने वाला घटक तीसरे पक्ष के एप्लिकेशन डेवलपर्स के लिए उपलब्ध नहीं है, इस तथ्य के बावजूद कि यह अधिक सुंदर और कार्यात्मक है। ईमानदारी से, मेरी राय में, यह सबसे अच्छा
टाइमपिकर विकल्प है जिसे मैंने देखा है।
तो, नीचे मैं दिखाऊंगा कि इस तरह के एक घटक को खुद कैसे लागू किया जाए, और आप देखेंगे कि सब कुछ अपेक्षाकृत सरल है।
QML
हमारे
TimePicker क्या है? वास्तव में, यह प्रबंधन के लिए केवल तीन चित्र, दो टैग और एक सक्रिय क्षेत्र है। आइए,
QML में
इसे तैयार करते हैं ।
Item { id: timePicker width: 400 height: 400 property int hours: 0 property int minutes: 0 property alias backgroundImage: bg.source property alias hourDotImage: hourDot.source property alias minutesDotImage: minuteDot.source Image { id: bg anchors.fill: parent property int centerX: 200 property int centerY: 200 property int minuteRadius: 152 property int hourRadius: 65 property int minuteGradDelta: 6 property int hourGradDelta: 30 property int diameter: 73 Image { id: hourDot x: centerX y: centerY - bg.hourRadius width: bg.diameter height: bg.diameter Text { font.pixelSize: 40 anchors.centerIn: parent text: (timePicker.hours < 10 ? "0" : "") + timePicker.hours } } Image { id: minuteDot x: centerX y: centerY - bg.minuteRadius width: bg.diameter height: bg.diameter Text { font.pixelSize: 40 anchors.centerIn: parent color: "#CCCCCC" text: (timePicker.minutes < 10 ? "0" : "") + timePicker.minutes } } } MouseArea { id: mouseArea anchors.fill: parent } }
यह कुछ इस तरह से निकलता है, यदि आप अब इस घटक का उपयोग करते हैं, तो इसे चित्रों के रूप में पास करते हैं, मूल
टाइमपिक के समान सर्कल हैं, तो हम एक घटक देखेंगे जो हमारे कार्यों का जवाब नहीं देता है, समय 00:00 पर सेट होने के साथ।
अब हमें यह सुनिश्चित करने की आवश्यकता है कि चरों के मान के आधार पर घंटों और मिनटों के साथ मंडलियों का स्थान बदल जाए:
property int hours: 0 property int minutes: 0
ऐसा करने के लिए, निम्न पंक्तियों को क्रमशः
घंटेडॉट और
मिनटडॉट घटकों में जोड़ें:
x: (bg.centerX - bg.diameter / 2) + bg.hourRadius * Math.cos(timePicker.hours * bg.hourGradDelta * (3.14 / 180) - (90 * (3.14 / 180))) y: (bg.centerY - bg.diameter / 2) + bg.hourRadius * Math.sin(timePicker.hours * bg.hourGradDelta * (3.14 / 180) - (90 * (3.14 / 180)))
और
x: (bg.centerX - bg.diameter / 2) + bg.minuteRadius * Math.cos(timePicker.minutes * bg.minuteGradDelta * (3.14 / 180) - (90 * (3.14 / 180))) y: (bg.centerY - bg.diameter / 2) + bg.minuteRadius * Math.sin(timePicker.minutes * bg.minuteGradDelta * (3.14 / 180) - (90 * (3.14 / 180)))
अलौकिक कुछ भी नहीं - बस एक सर्कल पर एक बिंदु का स्थान ढूंढना।
जब हमने सब कुछ तैयार कर लिया है, तो हम घटक के मुख्य भाग को स्थानांतरित करेंगे, अर्थात् उपयोगकर्ता कार्यों और प्रतिक्रियाओं को संसाधित करना।
प्रसंस्करण
हमारा
माउसआयर एक बार दोनों सर्कल के लिए एक साथ काम करेगा, और सभी क्योंकि कोई गोल
माउसएयर नहीं है , लेकिन किसी तरह हमें सर्कल और रिंग में उंगली की स्थिति को संभालने की आवश्यकता है। इस प्रकार, हम इस कार्य को अपने पास स्थानांतरित करते हैं, और
माउसआयर के लिए ऐसी सरल विधि
लिखते हैं :
function chooseHandler(mouseX, mouseY) { if (bg.hourRadius + bg.diameter / 2 > Math.sqrt(Math.pow(bg.centerX - mouseX, 2) + Math.pow(bg.centerY - mouseY, 2))) return 0 else if (bg.minuteRadius + bg.diameter / 2 > Math.sqrt(Math.pow(bg.centerX - mouseX, 2) + Math.pow(bg.centerY - mouseY, 2))) return 1 return -1 }
यह विधि 0 पर लौटती है यदि हम छोटे घेरे (घंटे), एक यदि वलय (मिनट), और -1 से टकराते हैं, तो हम कहीं भी नहीं टकराते हैं ताकि वर्ग के कोनों को संसाधित न करें।
उपयोगकर्ता के इशारों को संसाधित करने के लिए, तीन
माउसआयर घटनाओं की
आवश्यकता होती है :
onPressed: { currentHandler = chooseHandler(mouseX, mouseY) previousAlpha = findAlpha(mouseX, mouseY) }
हम ऊपर वर्णित विधि को कॉल करते हैं और निर्धारित करते हैं कि हम क्या काम कर रहे हैं और "12 घंटे" के सापेक्ष दबाव बिंदु का कोण प्राप्त करें।
onReleased: { currentHandler = -1 previousAlpha = -1 }
बस सब कुछ रीसेट करें।
onPositionChanged: { var newAlpha = 0; if (currentHandler < 0) return newAlpha = findAlpha(mouseX, mouseY) if (currentHandler > 0) { timePicker.minutes = getNewTime(timePicker.minutes, newAlpha, bg.minuteGradDelta, 1) } else timePicker.hours = getNewTime(timePicker.hours, newAlpha, bg.hourGradDelta, 2) }
तब होता है जब उपयोगकर्ता की उंगली अपनी स्थिति बदलती है।
हमें एक नया कोण मिलता है, सब कुछ भी अपेक्षाकृत "12 घंटे" है, और हम कुछ मापदंडों के साथ
getNewTime विधि (हम नीचे इस पर विचार करेंगे) को कॉल करते हैं - इस पर निर्भर करता है कि हम अभी घंटे या मिनट के साथ काम कर रहे हैं।
अब आइए
FindAlpha विधि को देखें, यह सरल है, और स्कूल ज्यामिति से आगे नहीं जाती है:
function findAlpha(x, y) { var alpha = (Math.atan((y - bg.centerY)/(x - bg.centerX)) * 180) / 3.14 + 90 if (x < bg.centerX) alpha += 180 return alpha }
हम कोण को रेडियन में गणना करते हैं और इसे डिग्री में अनुवाद करते हैं और सभी 360 डिग्री (और न केवल पहले 180) के साथ काम करने के लिए एक अतिरिक्त चेक जोड़ते हैं।
getNewTime
यह विधि कंप्यूटिंग का मूल है और इसके निम्नलिखित पैरामीटर हैं:
- स्रोत - काउंटर का प्रारंभिक मूल्य;
- अल्फा वर्तमान कोण है;
- रिज़ॉल्यूशन - डिग्री में एक सेक्टर का आकार (6 मिनट के लिए, 30 सेकंड के लिए);
- बाउंडफैक्टर - काउंटर को रीसेट करने के लिए आपको सर्कल के चारों ओर कितनी बार स्पिन करने की आवश्यकता है - 1 मिनट के लिए, 2 - घंटे के लिए, क्योंकि हमारे पास 24 घंटे हैं लेकिन एक सर्कल में सभी 12 डिवीजन हैं।
वास्तव में विधि:
function getNewTime(source, alpha, resolution, boundFactor) { var delta = alpha - previousAlpha if (Math.abs(delta) < resolution) return source if (Math.abs(delta) > 180) { delta = delta - sign(delta) * 360 } var result = source * resolution var resdel = Math.round(result + delta) if (Math.round(result + delta) > 359 * boundFactor) result += delta - 360 * (source * resolution > 359 ? boundFactor : 1) else if (Math.round(result + delta) < 0 * boundFactor) result += delta + 360 * (source * resolution > 359 ? boundFactor : boundFactor) else result += delta previousAlpha = alpha return result / resolution }
सबसे पहले, हम उंगली की वर्तमान और पिछली सहेजी गई स्थिति के बीच अंतर की गणना करते हैं, अगर अंतर एक क्षेत्र के आकार से कम है, तो हम बस कुछ भी बदले बिना बाहर निकलते हैं।
अगली जांच उस मामले को संभालती है जब 0 डिग्री (12 घंटे) के माध्यम से एक उंगली का मार्ग एक डेल्टा लौटाता है जो बहुत बड़ा है, इसलिए यह इसे सही करता है।
परिणाम चर को बिंदु में प्रारंभिक स्थिति में डिग्री में लिखा जाता है, जिसके बाद डेल्टा को इसमें जोड़ा जाता है।
लेकिन सब कुछ इतना सरल नहीं है, शर्तों का एक समूह सीमावर्ती मामलों को समायोजित करने के लिए कार्य करता है, अगर ये जांच नहीं थीं, तो हम TimePicker पर 25:68 जैसे गलत मान देख सकते हैं।
उसके बाद, हम उंगली की नई स्थिति को याद करते हैं और परिणाम को सही इकाइयों में वापस करते हैं।
निष्कर्ष

वास्तव में, यह सब है बाईं ओर डिवाइस से अंतिम स्क्रीनशॉट है। दिए गए एल्गोरिदम पूर्णता के शीर्ष नहीं हैं, यह सिर्फ एक कार्यशील समाधान है। यदि आप बेहतर कर सकते हैं - कृपया, मुझे बताएं।
घटक कोड
Gitorius पर उपलब्ध हैPS इस समस्या का पहला (
गलत ) समाधान और भी सरल था - मैंने देखा कि किस चक्र में उंगली के चारों ओर चक्र है, और, इसके आंदोलन की चार दिशाओं में से एक पर निर्भर करता है, एक को जोड़ा या घटाया जाता है। शायद किसी उद्देश्य के लिए यह दृष्टिकोण भी समझ में आ सकता है, लेकिन मैंने मौजूदा नोकिया समाधान को यथासंभव निकट से मिलान करने के लिए कार्य निर्धारित किया है।