2011-11-03 13 views
11

यह प्रश्न उन लोगों के लिए स्पष्ट प्रतीत होगा जो स्वयं समस्या का सामना नहीं कर चुके हैं।वर्चुअल ट्री व्यू: सही ढंग से हैंडलिंग चयन परिवर्तन

मुझे वीटीवी में चयन परिवर्तनों को संभालने की आवश्यकता है। मेरे पास नोड्स की एक फ्लैट सूची है। मुझे वर्तमान में चयनित सभी नोड्स के साथ सामान करने की आवश्यकता है जब भी

  1. उपयोगकर्ता नोड पर क्लिक करता है;
  2. उपयोगकर्ता शिफ्ट/Ctrl-node को नोड करता है;
  3. उपयोगकर्ता सूची को नेविगेट करने के लिए तीर कुंजियों का उपयोग करता है;
  4. उपयोगकर्ता खाली जगह या केवल चयनित नोड

आदि यह सबसे आम और अपेक्षित व्यवहार, बस Windows Explorer की तरह है Ctrl-क्लिक करने पर क्लिक करके माउस

  • उपयोगकर्ता चयन को हटा खींचकर चयन बनाता है: जब आप माउस और/या कीबोर्ड के साथ फ़ाइलों का चयन करते हैं, तो सूचना पैनल उनके गुण दिखाता है। मुझे इससे ज्यादा कुछ नहीं चाहिए। और यह वह जगह है जहां मैं अटक गया।

    मेरे कुछ शोध निम्नानुसार हैं।


    पहले मैंने ऑनचेंज का उपयोग किया था। यह अच्छी तरह से काम करने के लिए लग रहा था, लेकिन मैं कुछ अजीब अस्थिर देखा और मैंने पाया है कि सबसे आम परिदृश्य में (एक नोड चयन किया जाता है, तो उपयोगकर्ता एक और एक पर क्लिक करना) OnChange दो बार निकाल दिया जाता है:

    1. जब वर्ष नोड सही का निशान हटाने । इस समय चयन खाली है। मैं सभी गुणों के स्थान पर "कुछ भी नहीं चुना गया" लेबल दिखाने के लिए अपने जीयूआई को रीफ्रेश करता हूं।
    2. जब नया नोड चुना जाता है। मैं नए नोड के गुण दिखाने के लिए फिर से अपना जीयूआई रीफ्रेश करता हूं। इसलिए झटकेदार।

    यह समस्या googleable थी, इसलिए मैंने पाया कि लोग OnChange के बजाय OnFocusChange और OnFocusChanging का उपयोग करते हैं। लेकिन इस तरह से केवल एक चयन के लिए काम करता है। एकाधिक चयन के साथ, ड्रैग-चयन और नेविगेशन कुंजी यह काम नहीं करती है। कुछ मामलों में फोकस घटनाएं बिल्कुल भी आग लगती नहीं हैं (उदाहरण के लिए जब रिक्त स्थान पर क्लिक करके चयन हटा दिया जाता है)।

    मैंने कुछ परिदृश्यों में इन हैंडलरों को कैसे निकाल दिया है, यह जानने के लिए मैंने कुछ डीबग आउटपुट अध्ययन किया था। जो मैंने पाया वह बिना किसी दृश्य या पैटर्न के कुल गड़बड़ है।

    C OnChange 
    FC OnFocusChange 
    FCg OnFocusChanging 
    - nil parameter 
    * non-nil parameter 
    ! valid selection 
    
    
    Nodes  User action     Handlers fired (in order) 
    selected     
    0  Click node     FCg-* C*!  
    1  Click same     FCg**   
    1  Click another     C- FCg** C*! FC* 
    1  Ctlr + Click same   FCg** C*!  
    1  Ctrl + Click another   FCg** C*! FC* 
    1  Shift + Click same   FCg** C*!  
    1  Shift + Click another   FCg** C-! FC* 
    N  Click focused selected  C-! FCg**  
    N  Click unfocused selected  C-! FCg** FC* 
    N  Click unselected    C- FCg** C*! FC* 
    N  Ctrl + Click unselected  FCg** C*! FC* 
    N  Ctrl + Click focused   FCg** C*!   
    N  Shift + Click unselected  FCg** C-! FC* 
    N  Shift + Click focused   FCg** C-!   
    1  Arrow       FCg** FC* C- C*! 
    1  Shift + Arrow     FCg** FC* C*! 
    N  Arrow       FCg** FC* C- C*! 
    N  Shift + Arrow (less)   C*! FCg** FC* 
    N  Shift + Arrow (more)   FCg** FC* C*! 
    Any Ctrl/Shift + Drag (more)  C*! C-!  
    0  Click empty     -   
    1/N Click Empty     C-!   
    N  Ctrl/Shift + Drag (less)  C-!   
    1  Ctrl/Shift + Drag (less)  C-!   
    0  Arrow       FCg** FC* C*! 
    

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

    लेकिन अगला कार्य यह है: ऑनचेंज के अंदर मुझे नहीं पता कि मुझे इस कॉल का उपयोग करना चाहिए या अगले के लिए इंतजार करना चाहिए। कभी-कभी चयनित नोड्स का सेट मध्यवर्ती और गैर-उपयोगी होता है, और इसे प्रोसेस करने से जीयूआई झिलमिलाहट और/या अवांछित भारी गणना होगी।

    मुझे केवल उन कॉलों की आवश्यकता है जो "!" के साथ चिह्नित हैं उपरोक्त तालिका में। लेकिन उन्हें अंदर से अलग करने का कोई तरीका नहीं है। उदाहरण: यदि मैं "सी-" (ऑनचेंज, नोड = शून्य, चयनित गणना = 0) में हूं तो इसका अर्थ यह हो सकता है कि उपयोगकर्ता ने चयन हटा दिया (फिर मुझे इसे संभालने की आवश्यकता है) या उन्होंने एक और नोड क्लिक किया (फिर मुझे प्रतीक्षा करने की आवश्यकता है जब नया चयन बनता है तो अगला OnChange कॉल)।


    वैसे भी, मुझे आशा है कि मेरा शोध अनावश्यक था। मुझे आशा है कि मुझे ऐसा कुछ याद आ रहा है जो समाधान को सरल और स्पष्ट कर देगा, और आप, लोग, मेरे लिए इसे इंगित करने जा रहे हैं। मेरे पास जो कुछ भी है, उसका उपयोग करके इस पहेली को हल करना कुछ बेहद अविश्वसनीय और जटिल तर्क उत्पन्न करेगा।

    अग्रिम धन्यवाद!

  • उत्तर

    12

    ChangeDelay संपत्ति को उचित, शून्य मान से अधिक मिलीसेकंड में सेट करें, उदा। 100। यह एक शॉट टाइमर लागू करता है रॉब केनेडी अपने जवाब में सुझाव देता है।

    +0

    धन्यवाद, @Tondrej! मैंने पहले कभी इस संपत्ति को नहीं देखा। और मैं ईमानदार होने के लिए ऐसी चीज मौजूद होने की उम्मीद नहीं करूंगा। लेकिन यह मेरी समस्या को हल करने का 'आधिकारिक' तरीका प्रतीत होता है। मैंने कोशिश की और यह काम करता है, लेकिन थोड़ा अजीब लगता है ... टाइमर के साथ ऐसी समस्याओं को हल करना मेरे लिए वास्तव में एक बुरा विचार है। लेकिन अगर समय के साथ कोई बेहतर समाधान नहीं आता है, तो मुझे इसे चिपकना होगा। – 13x666

    +0

    @ 13x666 यदि आप इसके बारे में सोचते हैं, तो इस मामले में झिलमिलाहट से बचने का मतलब है कि यदि वे चीजों (उपयोगकर्ता इनपुट) "शांत हो जाएं" के बाद एक का पालन करते हैं तो स्क्रीन अपडेट को दबाकर इसका मतलब है। –

    +1

    +1। @ 13x666, एक टाइमर वास्तव में एक * बहुत * हल्का वजन समाधान है जो उपयोगकर्ता इनपुट को "शांत" करने की प्रतीक्षा करता है, क्योंकि टोंड्रेज इसे रखता है। यह अनिवार्य रूप से SetTimer API पर एक कॉल है। मैंने सफलतापूर्वक ग्रेट सफलता के साथ कई बार इस उद्देश्य के लिए टाइमर का उपयोग किया है।उपयोगकर्ता उप-200-एमएस देरी को नोटिस नहीं करेगा, लेकिन उपयोगकर्ता जीयूआई को अनावश्यक रूप से चित्रित करने के कारण बाद के आदेशों को संसाधित करने में झिलमिलाहट और देरी नोटिस करेगा। –

    3

    एक-शॉट टाइमर का उपयोग करें। जब टाइमर आग लगती है, तो जांच करें कि चयन अलग है या नहीं, अपना प्रदर्शन अपडेट करें, और टाइमर को अक्षम करें। प्रत्येक बार जब आप एक संभावित चयन-परिवर्तनकारी घटना प्राप्त करते हैं (जो मुझे लगता है कि हमेशा चालू होता है), टाइमर को रीसेट करें।

    यह आपको उस घटना की प्रतीक्षा करने का एक तरीका देता है जो आप वास्तव में चाहते हैं और झटके से बचें। लागत थोड़ा देरी यूआई है।

    +0

    उत्तर के लिए धन्यवाद, रॉब। मैंने इस समाधान पर किसी बिंदु पर विचार किया था, लेकिन कीमत बहुत अधिक है। असल में, यदि कोई साफ समाधान स्वयं दिखाई नहीं दे रहा है, तो बस हर ऑन चेंज का उपयोग कम होगा: फ्लिकर देरी से सहन करना आसान है। फिर भी, दोनों व्यापार-बंद बदसूरत हैं। – 13x666

    +0

    चेंजडेले संपत्ति के बिना नियंत्रण के लिए, यह जाने का तरीका है। –

    0

    मुझे लगता है कि तुम यहाँ दिए गए उत्तर का इस्तेमाल किया है हो सकता है या यहां तक ​​कि एक और समाधान पाया, लेकिन मैं थोड़ा यहाँ योगदान करना चाहते हैं ...

    एक गैर-एकाधिक चयन करें वातावरण में (मैं एक में यह परीक्षण नहीं किया बहु-चयन पर्यावरण) मुझे देरी के बिना एक बहुत ही सरल समाधान मिला है:

    वैश्विक PVirtualNode सूचक (इसे इसे FSelectedTreeNode कहते हैं) रखें। स्टार्टअप पर स्पष्ट रूप से आप इसे शून्य सौंप देंगे।

    अब अगली नोड का चयन करने के लिए आप अपने तीर कुंजीपटल कुंजियों का उपयोग करते हैं तो ऑनट्री चेंज दो बार होगा। एक बार नोड के लिए जिसे अचयनित किया जाएगा और एक बार नए चयनित नोड के लिए।

    If Node <> FSelectedTreeNode then 
        begin 
         FSelectedTreeNode := Node; 
         If Node = nil then 
         {Do some "Node Deselected" code} 
         else 
         {Do whatever you want to do when a new node is selected} 
        end; 
    

    यह मेरा कोड के साथ बहुत अच्छी तरह से काम करता है और यह कोई झिलमिलाहट है और कम से कम कोई देरी: अपने OnTreeChange स्थिति में आप निम्न कार्य करें।

    चाल यह है कि नव चयनित नोड वैश्विक सूचक को सौंपा जाएगा और यह आखिरी होगा। तो जब आप एक और नोड का चयन करते हैं तो यह पहले OnTreeChange पर कुछ भी नहीं करेगा क्योंकि तब वैश्विक सूचक नोड को अचयनित करने जैसा ही होगा।

    संबंधित मुद्दे