2012-10-25 11 views
5

मैं वर्तमान में एक रंग योजना संपादक लिख रहा हूं। इस योजना के पूर्वावलोकन के लिए, मैं एक टेक्स्ट विजेट का उपयोग करता हूं, जहां मैं संबंधित रंग टैग (जिसे मैं प्रोग्रामेटिक रूप से उत्पन्न करता हूं) के साथ टेक्स्ट सम्मिलित करता हूं। पाठ विजेट पर कहीं भीपायथन टिंकर: टेक्स्ट विगेट्स टैग्स में ईवेंट प्रसार रोकना

  • क्लिक जहां कोई पाठ है:: परिवर्तन पृष्ठभूमि रंग पाठ पर
  • क्लिक एक टैग के साथ डाला: परिवर्तन टैग अग्रभूमि रंग
  • इसी

    क्या मैं चाहता हूँ निम्नलिखित व्यवहार है

अब यहाँ मेरी समस्या है:

जब मैं एक टैग किए गए पाठ पर क्लिक करें, टैग का कॉलबैक कहा जाता है। अब तक सब ठीक है। लेकिन फिर, टेक्स्ट विजेट का कॉलबैक भी कहा जाता है, हालांकि मैं टैग कॉलबैक विधि में "ब्रेक" देता हूं (जो आगे ईवेंट हैंडलिंग को रोकना चाहिए)। मैं इसे कैसे रोक सकता हूं?

इस विशिष्ट समस्या का वर्णन करने के लिए, मैं (अजगर 2 & 3 के लिए) इस काम कर उदाहरण लिखा है:

#!/usr/bin/env python 

try: 
    from Tkinter import * 
    from tkMessageBox import showinfo 
except ImportError: 
    from tkinter import * 
    from tkinter.messagebox import showinfo 

def on_click(event, widget_origin='?'): 
    showinfo('Click', '"{}"" clicked'.format(widget_origin)) 
    return 'break' 

root = Tk() 
text = Text(root) 
text.pack() 
text.insert(CURRENT, 'Some untagged text...\n') 
text.bind('<Button-1>', lambda e, w='textwidget': on_click(e, w)) 
for i in range(5): 
    tag_name = 'tag_{}'.format(i) 
    text.tag_config(tag_name) 
    text.tag_bind(tag_name, '<Button-1>', 
     lambda e, w=tag_name: on_click(e, w)) 
    text.insert(CURRENT, tag_name + ' ', tag_name) 
root.mainloop() 

किसी भी मदद की सराहना की है!

संपादित करें: पाइथन 2 का भी प्रयास किया।

उत्तर

2

ठीक है, के बाद tkint थोड़ा चारों ओर फेर, मैं एक काम कर समाधान यह पता लगाने में सक्षम था। मुझे लगता है कि समस्या यह है कि टैग शायद बेसविड्ज से उपclassed नहीं हैं।

मेरे वैकल्पिक हल:

  • टैग के लिए एक अलग कॉलबैक करो; एक चर वहाँ जो ट्रैक जिनमें से टैग क्लिक किया गया था
  • पाठ विजेट के ईवेंट हैंडलर तय क्या करना है चलो रहता सेट इस चर

कोड में समाधान की सामग्री के आधार (यहाँ global का उपयोग कर के लिए खेद है , लेकिन मैं तो बस मेरे सवालों का सरल उदाहरण संशोधित ...):

#!/usr/bin/env python 

try: 
    from Tkinter import * 
    from tkMessageBox import showinfo 
except ImportError: 
    from tkinter import * 
    from tkinter.messagebox import showinfo 

tag_to_handle = '' 

def on_click(event, widget_origin='?'): 
    global tag_to_handle 
    if tag_to_handle: 
     showinfo('Click', '"{}" clicked'.format(tag_to_handle)) 
     tag_to_handle = '' 
    else: 
     showinfo('Click', '"{} " clicked'.format(widget_origin)) 

def on_tag_click(event, tag): 
    global tag_to_handle 
    tag_to_handle = tag 

root = Tk() 
text = Text(root) 
text.pack() 
text.insert(CURRENT, 'Some untagged text...\n') 
text.bind('<Button-1>', lambda e, w='textwidget': on_click(e, w)) 
for i in range(5): 
    tag_name = 'tag_{}'.format(i) 
    text.tag_config(tag_name) 
    text.tag_bind(tag_name, '<Button-1>', 
     lambda e, w=tag_name: on_tag_click(e, w)) 
    text.insert(CURRENT, tag_name + ' ', tag_name) 
root.mainloop() 

मुझे आशा है कि यह एक ही समस्या हो रही लोगों के लिए उपयोगी है।

मैं अभी भी पाठ्यक्रम के अच्छे समाधान के लिए खुला हूं!

+1

टैग टेक्स्ट-विशिष्ट आइटम हैं और कोई टैग क्लास नहीं है। वे निश्चित रूप से बेसविड्ज से उपclassed नहीं हैं। उदाहरण के लिए, कैटवास-विशिष्ट वस्तुओं जैसे कि आर्क और लाइनों के लिए डिट्टो। अच्छा कामकाज –

2

इस प्रश्न को पोस्ट करने और समाधान प्रदान करने के लिए धन्यवाद। मैं इस व्यवहार से बनाए गए लक्षणों को ठीक करने की कोशिश करने में कितने घंटे खो गया है, इस बात की गिनती नहीं कर सकता। अजीब Tk डिजाइन निर्णय tag_bindreturn "break" पर असीमित है।

अपने विचार tag_bind रूप में एक ही घटना क्रम के साथ यह जुड़ कर Text विजेट का अपहरण करने के बाद, मैं समाधान है, जो अब सक्षम बनाता है टी के अन्य बाँध + कॉलबैक जोड़े की उम्मीद return "break" व्यवहार अनुकरण करने के लिए सुधार हुआ है।

  1. callback कामना की, चारों ओर एक आवरण बनाने अर्थात एक प्रतिदेय वर्ग उदाहरण
  2. जब वर्ग उदाहरण कहा जाता है, callback चलाने के लिए और अपने परिणाम की जाँच करें: विचार निम्नलिखित (पूर्ण नीचे स्रोत) है।
    • यदि परिणाम "break" है, अस्थायी रूप से घटना प्रचार का अपहरण: bind, tag_bind करने के लिए बाध्य एक खाली कॉलबैक के साथ एक ही घटना के लिए Text विजेट। फिर, निष्क्रिय समय के बाद, unbind
    • यदि परिणाम नहीं "break" है: कुछ भी नहीं, घटना Text के लिए स्वचालित रूप

यहाँ प्रचार करेंगे एक पूर्ण काम कर उदाहरण है। मेरी विशिष्ट समस्या कुछ प्रकार के हाइपर टेक्स्ट व्यवहार प्राप्त करने के लिए थी: हाइपर-टेक्स्ट पर ctrl-clicking प्रविष्टि बिंदु को क्लिक के स्थान पर नहीं ले जाना चाहिए। नीचे दिया गया उदाहरण दिखाता है कि tag_bind में लिपटे उसी कॉलबैक के भीतर, हम Text विजेट पर ईवेंट को प्रचारित कर सकते हैं या नहीं, बस "break" या अन्य मान लौटकर।

try: 
    # Python2 
    import Tkinter as tk 
except ImportError: 
    # Python3 
    import tkinter as tk 

class TagBindWrapper: 
    def __init__(self, sequence, callback): 
     self.callback=callback 
     self.sequence=sequence 

    def __call__(self, event): 
     if "break" == self.callback(event): 
      global text 
      self.bind_id=text.bind(self.sequence, self.break_tag_bind) 
      return "break" 
     else: 
      return 

    def break_tag_bind(self, event): 
     global text 
     # text.after(100, text.unbind(self.sequence, self.bind_id)) 
     text.after_idle(text.unbind, self.sequence, self.bind_id) 
     return "break" 



def callback_normal(event): 
    print "normal text clicked" 
    return "break" 

def callback_hyper(event): 
    print "hyper text clicked" 
    if event.state & 0x004: # ctrl modifier 
     return "break" # will not be passed on to text widget 
    else: 
     return # will be passed on to text widget 

# setup Text widget 
root=tk.Tk() 
text = tk.Text(root) 
text.pack() 
text.tag_config("normal", foreground="black") 
text.tag_config("hyper", foreground="blue") 
text.tag_bind("hyper", "<Button-1>", TagBindWrapper("<Button-1>", callback_hyper)) 
text.tag_bind("normal", "<Button-1>", callback_normal) 

# write some normal text and some hyper text 
text.insert(tk.END, "normal text, ", "normal") 
text.insert(tk.END, "hyper text (try normal-click and ctrl-click).", "hyper") 

root.mainloop() 

एक सरलीकरण नहीं है मैं कैसे करना नहीं पा सके: बस event वस्तु __call__ के लिए पारित से आवरण कॉल TagBindWrapper("<Button-1>", callback_hyper)TagBindWrapper(callback_hyper) से, यानी घटना के बारे में जानकारी प्राप्त 'अनुक्रम' स्ट्रिंग ("<Button-1>") की जगह । क्या यह संभव है?

+0

उपरोक्त वर्णित सरलीकरण के लिए एक समाधान के रूप में, कोई एक फ़ंक्शन लिख सकता है: 'def tag_bind (textwidget, tagname, event_sequence, callback): textwidget.tag_add (टैगनाम, event_sequence, टैगबिंडवापर (event_sequence, कॉलबैक))' बस लिखने के लिए ' tag_bind (टेक्स्ट, "टैग", "<1>", कॉलबैक) '। सिर्फ तर्कों को डुप्लिकेट करने से बचाता है। यह युक्ति वैश्विक वैरिएबल को भी खत्म कर सकती है यदि टेक्स्ट विजेट को टैगबिंडवापर वर्ग कन्स्ट्रक्टर '__init__' के तर्क के रूप में दिया जाता है। –

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