एक gobject.timeout_add कॉलबैक फ़ंक्शन के माध्यम से कैरो के साथ एक बिंदु खींचना

मेरे पास कोड का लगभग काम करने वाला टुकड़ा है (मुझे उम्मीद है)। इस वर्ग की अद्यतन विधि में, खिड़की की चौड़ाई और ऊंचाई से घिरे स्थानों पर यादृच्छिक काले बिंदु तैयार किए जाने चाहिए - समस्या यह है कि अंक खींचे नहीं जाते हैं। पृष्ठभूमि छवि वाली एक gtk विंडो जिसमें कैरो छवि लोड किया गया है ImageSurface.create_from_png (BG_IMG) प्रदर्शित होता है और मैंने यह भी सत्यापित किया है कि अद्यतन फ़ंक्शन को कॉल किया जाता है (प्रत्येक 17ms gobject.timeout_add कॉलबैक फ़ंक्शन के साथ)। मैंने यहां और कहीं और खोज की है, लेकिन मैं नहीं देख सकता कि इस कोड के साथ क्या गलत है ..

class Screen(gtk.DrawingArea):

    __gsignals__ = {"expose-event": "override"}

    def do_expose_event(self, event):
        self.cr = self.window.cairo_create()

        self.cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
        self.cr.clip()
        self.draw(*self.window.get_size())

    def draw(self, width, height):
        x = y = 0
        self.bg = c.ImageSurface.create_from_png(BG_IMG)
        self.cr.set_source_surface(self.bg, x, y)
        self.cr.paint()

    def update(self):
        x = randint(0, DOCK_W)
        y = randint(0, DOCK_H)
        self.cr.rectangle(x, y, 1, 1)
        self.cr.set_source_rgba(0, 0, 0, 1)
        self.cr.fill()
        self.cr.paint()

किसी के पास कुछ अंतर्दृष्टि है कि यह कोड क्यों विफल रहा है? अग्रिम में बड़ा धन्यवाद!

हल किया

मुझे पता नहीं था कि प्रत्येक ड्रॉ ऑपरेशन में एक नया कैरो संदर्भ इस्तेमाल किया जा सकता है। यह मुख्य समस्या साबित हुई।

1

1 उत्तर

आम तौर पर बोलते हुए, आपको सीधे एक एक्सपोज़ घटना के बाहर खिड़की पर नहीं खींचा जाना चाहिए। और बाद में उपयोग के लिए कैरो संदर्भ न रखें: प्रत्येक ईवेंट चलाने के लिए एक बनाएं।

जब आप अपने अंक आकर्षित करना चाहते हैं, तो बस करें: widget.queue_draw() , और एक नया एक्सपोज़ ईवेंट आपको ASAP पर पहुंचा दिया जाएगा। लेकिन ध्यान दें कि खुलासा कार्यक्रम में आपको सभी बिंदुओं को पेंट करना होगा, न केवल नए।

आपके कोड के प्रकार के लिए एक उपयोगी अनुकूलन: टाइमर से queue_draw को कॉल न करें क्योंकि यह काफी अक्षम है। इसके बजाय बस नया बिंदु खींचें। हालांकि यह आपको do_expose_event में सभी बिंदुओं को आकर्षित करने के लिए क्षमा नहीं करता है, क्योंकि किसी भी समय एक एक्सपोज़ घटना हो सकती है और आप पहले से चित्रित बिंदुओं को खोना नहीं चाहते हैं।

एक-बिंदु ड्रा करने के लिए आपको एक नया कैरो संदर्भ बनाना होगा, लेकिन आपको इसे सहेजने की आवश्यकता नहीं है:

def update(self):
    cr = self.window.cairo_create()
    x = randint(0, DOCK_W)
    y = randint(0, DOCK_H)
    self.points.append((x,y)) #for the expose event ;-)
    cr.rectangle(x, y, 1, 1)
    cr.set_source_rgba(0, 0, 0, 1)
    cr.fill()
    cr.paint()

एक और आम अनुकूलन, विशेष रूप से यदि आपके पास बहुत सारे अंक हैं, तो पेंट की गई छवि को बिटमैप में रखना है, इसलिए जब एक्सपोज़ ईवेंट होता है, तो आप बिंदुओं की सूची के साथ सभी को पुन: स्थापित करने के बजाय बस बिटमैप को दबाते हैं।

1
जोड़ा
आपकी युक्तियों को वास्तव में कुछ काला खींचा गया है! अब मुझे यह समझना है कि आयताकार 1 पिक्सेल क्यों नहीं है बल्कि एक बड़ा क्षेत्र है (कम से कम यह ऐसा दिखता है)। लेकिन मुझे पूरा भरोसा है कि मैं खुद को बाहर निकाल दूंगा। आपका बहुत बहुत धन्यवाद! और मैं मस्तिष्क को ध्यान में रखूंगा। मैं तुम्हें उखाड़ फेंक दूंगा, लेकिन स्पष्ट रूप से मेरे पास अभी तक पर्याप्त प्रतिष्ठा नहीं है; -पी
जोड़ा लेखक astr1sk, स्रोत
हा, स्वीकार्य-टिकमार्क मिला। एक बार फिर धन्यवाद!
जोड़ा लेखक astr1sk, स्रोत
अनुलेख सब कुछ अब पूरी तरह से काम करता है!
जोड़ा लेखक astr1sk, स्रोत
@trsk: हो सकता है कि आप ऊपर नहीं जा सकते, लेकिन आप निश्चित रूप से जवाब स्वीकार कर सकते हैं।
जोड़ा लेखक rodrigo, स्रोत