Hi,

I am trying to use threads and PyGTK together (under M$ Windows) with no
success. I have attached the small program to this e-mail.

Am I doing something wrong ? Or is the pygtk not working with threads on
M$Win ?

I have python 2.3.2, pytgk 2.0.0 and gtk 2.2.4.1.

TIA,

Ionutz
import pygtk
pygtk.require ('2.0')
import gtk
import threading

class Stack(list):
    def __init__(self):
        list.__init__(self)

    def peek(self):
        return self[-1]

    def empty(self):
        return len(self) == 0

    def push(self, item):
        self.append(item)

    def clear(self):
        while len(self) != 0:
            self.pop()

class IconView(gtk.HBox):
    def __init__(self):
        gtk.HBox.__init__(self, gtk.FALSE, 0)
        self.__area = gtk.DrawingArea()
        self.pack_start(self.__area, gtk.TRUE, gtk.TRUE, 0)
        self.__area.show()

        self.__scrollbar = gtk.VScrollbar(adjustment=None)
        self.pack_start(self.__scrollbar, gtk.FALSE, gtk.FALSE, 0)
        self.__scrollbar.show()
        
        self.__selected = None # nothing selected

        self.__items = 0 # number of items
        self.__rows = 1 # number of rows
        self.__cols = 1 # number of columns
        self.__item_width = 1 # item width
        self.__item_height = 1 # item height
        self.__border = 0
        self.__show_labels = True

        # threading
        self.__label_lock = threading.Lock()
        self.__label_event = threading.Event()
        self.__label_event.clear()
        self.__label_stack = Stack()
        self.__label_thread = threading.Thread(None,
                                               self.item_thread,
                                               'label',
                                               (self.__label_stack,
                                                self.__label_event,
                                                self.__label_lock,
                                                self.get_label,
                                                self.display_label,
                                                'label'))
        self.__label_thread.start()
        
        self.__adjustment = self.__scrollbar.get_adjustment()
        self.__area.connect("configure_event", self.on_configure)
        self.__area.connect("expose-event", self.on_expose)

    def item_thread(self, stack, event, lock, get_item, display_item, name):
        while True:
            lock.acquire()
            while stack.empty():
                lock.release()
                event.wait()
                lock.acquire()
            event.clear()
            index = stack.peek()
            lock.release()
            if index == -1:
                return # we've been signalized to exit the thread
            item = get_item(index)
            lock.acquire()
            if not stack.empty():
                if index == stack.peek():
                    display_item(index, item)
                    stack.pop()
            lock.release()

    def get_label(self, index):
        return ('Item %d' % index)

    def display_label(self, index, label):
        row = index / self.__cols
        col = index % self.__cols
        x = col * self.__item_width
        y = row * self.__item_height + self.__border
        gtk.threads_enter()
        self.__pangolayout.set_text(label)
        self.__window.draw_layout(self.__gc, x, y, self.__pangolayout)
        gtk.threads_leave()

    def on_expose(self, area, event):
        rect = event.area
        self.__pangolayout = area.create_pango_layout("")
        self.__style = area.get_style()
        self.__window = area.window
        self.__gc = self.__style.fg_gc[gtk.STATE_NORMAL]

        # determin the area that needs to be drawn
        col1 = rect.x / self.__item_width
        col2 = min((rect.x + rect.width) / self.__item_width + 1, self.__cols)
        row1 = rect.y / self.__item_height
        row2 = min((rect.y + rect.height) / self.__item_height + 1, self.__rows) # we 
don't let row2 be more than the total number of rows

        self.__label_lock.acquire()
        self.__label_stack.clear()
        if col1 == 0 and col2 == 0:
            for row in range(row1, row2):
                if row < self.__items: # the col is always 0
                    self.__label_stack.push(row)
        else:
            for row in range(row1, row2):
                for col in range(col1, col2):
                    index = row * self.__cols + col
                    if index < self.__items:
                        self.__label_stack.push(index)

        self.__label_lock.release()
        self.__label_event.set()

        return gtk.TRUE

    def on_configure(self, widget, event, data=None):
        width = event.width
        height = event.height
        self.__cols = width / self.__item_width
        if self.__cols <= 0:
            self.__cols = 1 # we can't have less than 1 column !
        self.__rows = self.__items / self.__cols
        if self.__rows * self.__cols < self.__items:
            self.__rows += 1

    def set_all(self, items, width, height, border, show_labels = True):
        # set all properties of the icon view with one call
        # items - number of items fromthe view
        # width - width of one item
        # height - height of one item
        # border - the border arround the image / text
        # show_labels - if true, print some labels under the item
        if items < 0:
            items = 0
        if width < 1:
            width = 1
        if height < 1:
            height = 1
        if border < 0:
            border = 0

        self.__items = items
        self.__item_width = width
        self.__item_height = height
        self.__border = border
        self.__show_labels = show_labels

        # redraw all items now ...

    def get_selected(self):
        return self.__selected

    def set_selected(self, value):
        self.__selected = value

    def get_rows(self):
        return self.__rows

    def get_cols(self):
        return self.__cols

    selected = property(get_selected, set_selected, None, 'selected item')
    rows = property(get_rows, None, None, 'number of rows')
    cols = property(get_cols, None, None, 'number of rows')
    
class Test:
    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)

        # You should always remember to connect the delete_event signal
        # to the main window. This is very important for proper intuitive
        # behavior
        self.window.connect("delete_event", self.delete_event)

        # Create an icon-view and adds it to the window
        icon_view = IconView()
        icon_view.set_all(7, 128, 128, 5)
        # icon_view.set_size_request(400, 300) # make the icon view a bit bigger
        self.window.add(icon_view)
        icon_view.show()
        
        # the last thing we do is showing the window
        self.window.show()

    def main(self):
        gtk.main()

    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return gtk.FALSE

if __name__ == "__main__":
    test = Test()
    test.main()
-------------------------------------------------------
Xnet scaneaza automat toate mesajele impotriva virusilor folosind RAV AntiVirus.
Xnet automatically scans all messages for viruses using RAV AntiVirus.

Nota: RAV AntiVirus poate sa nu detecteze toti virusii noi sau toate variantele lor.
Va rugam sa luati in considerare ca exista un risc de fiecare data cand deschideti
fisiere atasate si ca MobiFon nu este responsabila pentru nici un prejudiciu cauzat
de virusi.

Disclaimer: RAV AntiVirus may not be able to detect all new viruses and variants.
Please be aware that there is a risk involved whenever opening e-mail attachments
to your computer and that MobiFon is not responsible for any damages caused by
viruses.
_______________________________________________
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to