PyGTK: рдзрд╛рд░рд╛рдУрдВ рдФрд░ рдЖрд╡рд░рдг рдЬрд╛рджреВ

рдЬреАрдЯреАрдХреЗ + рд╕рднреА рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдПрдХ рдмрдбрд╝реА рд╕рдорд╕реНрдпрд╛ рд╣реИред GTK рд╕реНрд╡рдпрдВ рдереНрд░реЗрдб-рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдПрдХ рдордЬрдмреВрд░ рдмреНрд▓реЙрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рджреВрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реЙрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рд▓реЙрдХ рдХреЛ рдПрдХ рдмрд╛рд░ рд╕рдЦреНрддреА рд╕реЗ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЕрдиреНрдпрдерд╛ рдЖрдкрдХрд╛ рдХреЛрдб рд▓рд┐рдирдХреНрд╕ рдкрд░ рд▓рдЯрдХрд╛ рд╣реЛрдЧрд╛, рдЦрд┐рдбрд╝рдХрд┐рдпреЛрдВ рдкрд░ рдареАрдХ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред

рдЕрдиреБрднрд╡ рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдПрдХреНрд╕реЗрд╕ рд╡рд┐рдзрд┐ "рдХреЛрдИ рднреА рдзрд╛рдЧрд╛ рдЬреАрдпреВрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдореБрдЦреНрдп рдмрд╛рдд рддрд╛рд▓реЗ рдХрд╛ рдХрд╛рд░рдг рд╣реИ" рдПрдХ рд╡рд┐рдлрд▓рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рдХрд▓рд╛: рдереЛрдбрд╝реА рджреЗрд░ рдХреЗ рдмрд╛рдж, рдЖрдк рдЬреАрдЯреАрдХреЗ рдХреА рдЧрд╣рд░рд╛рдИ рдореЗрдВ рдХреЛрд░ рдбрдВрдк рдХреЛ рдХрдИ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдкрдХрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрдХрд╛рд░ рд╣реИред

рдпреВрдкреА : рдХреЛрдб рдЧрд┐рдердм рдХреЛ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ "рдореБрдЦреНрдп" рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдХреЛрдб рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдХреЙрд╕реНрдореЗрдЯрд┐рдХ рдкрд░рд┐рд╡рд░реНрддрди (рдЕрд╡рдзрд┐ рдХреЗ рдмрдЬрд╛рдп рд╕реЗрдХрдВрдб, рдФрд░ рд╕рдорд╕реНрдпрд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд▓рдд рдзрд╛рд░рд╛ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓реЙрдЧрд┐рдВрдЧ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред

рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ, рдореЗрд░реА рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдореИрдВ рд╕реНрдЯреНрд░реАрдо рдХреЗ рд╕рд╛рде рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдорд╕реНрдпрд╛-рдореБрдХреНрдд рдХрд╛рд░реНрдп рдХреЗ рдЖрдпреЛрдЬрди рдХреА рдирд┐рдореНрди рд╡рд┐рдзрд┐ рдкрд░ рдЖрдпрд╛:
  1. GTK рдХреЗ рд▓рд┐рдП рдХреЛрдИ рднреА рдХреЙрд▓ рдХреЗрд╡рд▓ рдПрдХ рдзрд╛рдЧрд╛ рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИред рдЬреАрдпреВрдЖрдИ рдореЗрдВ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрди рд╕рдорд░реНрдкрд┐рдд рд░рд╛рдЬреНрдп рдЕрджреНрдпрддрди рдХрд╛рд░реНрдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
  2. рд╕рднреА рддрд╛рд▓реЗ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд░реЗрд╕реНрдЯреНрд░реЗрдВрдЯ рдмреНрд▓реЙрдХрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрдЪрд╛рд▓рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
  3. рдЕрд╡рд░реЛрдзрдХ "рдЧрд▓рдд" рд╕реНрдЯреНрд░реАрдо рд╕реЗ GUI рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реЗ рд▓реЙрдЧ рдХрд░рддрд╛ рд╣реИред

GUI рднрд╛рдЧ рдХреА рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрд░рдЪрдирд╛


рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ gui.py рдореЙрдбреНрдпреВрд▓ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд "рдЕрдЪреНрдЫрд╛" рдирд┐рд░реНрдпрд╛рдд рдХрд░рддрд╛ рд╣реИ:
GtkLocker = CGtkLocker() #  def GtkLocked(f): #    gui,        def IdleUpdater(f): #    ,      gui def SecondUpdater(f): #    ,       def GUIstop(): #       GUI def GuiCall(Func): #    GUI ""  def GuiIdleCall(Func): #    GUI       def GuiSecondCall(Func): #       def GUI(): #     


рдФрд░ рдЖрд╡реЗрджрди рдЗрд╕ рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
 import gui, gtk def InitApp(): """       """ with GtkLocker: window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.set_title(u"  ") window.connect("destroy", gui.GUIstop) window.realize() vbox = gtk.VBox() window.add(vbox) label = gtk.Label("Text label") vbox.add(label) window.show_all() def __main__(): gui.GuiCall( InitApp ) gui.GUI() if __name__ == '__main__': __main__() sys.exit(0) 


рдпрд╣ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд╛рда "рд▓реЗрдмрд▓" рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рдВрдбреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреБрдЫ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЖрдЗрдП рдЗрд╕реЗ рдорд╛рдирд╡реАрдп рд░реВрдк рд╕реЗ рдХрд░реЗрдВ: рд╕рднреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛрдб рдХреЛ рдПрдХ рдХрдХреНрд╖рд╛ рдореЗрдВ рдбрд╛рд▓реЗрдВ рдФрд░ рдПрдХ рдмрдЯрди рдЬреЛрдбрд╝реЗрдВред

 class CMyApp(object): def __init__(self): self.label = None self.times = 0 def CreateGui(self): with gui.GtkLocker: window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.set_title(u"  ") window.connect("destroy", gui.GUIstop) window.realize() vbox = gtk.VBox() window.add(vbox) label = gtk.Label("Welcome to our coool app!") vbox.pack_start(label) label = gtk.Label("Here will be counter") self.label = label vbox.pack_start(label) button = gtk.Button("Press me!") button.connect("clicked", self.Click) vbox.pack_start(button) window.show_all() @gui.GtkLocked def Click(self, widget): self.times += 1 self.label.set_text("You pressed button %d times" % self.times) MyApp = CMyApp() def InitApp(): """       """ MyApp.CreateGui() 


рддреЛ рд╣рдордиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛ рд╣реИ? рд╣рдордиреЗ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛, __init__ рд╡рд┐рдзрд┐, рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рднрд╡рд┐рд╖реНрдп рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рд╕рднреА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдирд┐рд░реНрдорд╛рдг CreateGui рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдХрд┐рдП CreateGui рд╣реИрдВ, рдЬрд┐рд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рд╛рдорд╛рдиреНрдп рдИрд╡реЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рд▓реВрдк рд╕реЗ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред

рдЕрдм рдЬрд╛рджреВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрд┐ Click рд╡рд┐рдзрд┐ рдирд┐рдореНрди рд╣реИ: рдзреНрдпрд╛рди рджреЗрдВ, рдпрд╣ рдПрдХ рдЖрд╡рд░рдг gui.GtkLocked рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рд╣реИред gui.GtkLocked ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдпрд╣ рд╡рд┐рдзрд┐ рдПрдХ GUI рдЗрд╡реЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рд╡рд┐рдзрд┐ рд╣реИ, рдФрд░ рдХрдиреЗрдХреНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрдбрд╝рд╛рдИ рд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЬрд┐рд╕ рд╕рдордп рд╡рд┐рдзрд┐ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрд╕рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА GTK рд▓реЙрдХ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдЖрд╡рд░рдг "рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрд╡рд░реЛрдзрд┐рдд" рдЕрд╡рд░реЛрдзрдХ GUI рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рд▓реЙрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред

рдПрдХ рджреВрд╕рд░рд╛ рдмрдЯрди рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рд╕рдореБрджреНрд░ рдХреЛ рдЙрдкрдпреЛрдЧреА рдмрдирд╛рддрд╛ рд╣реИ:
 class CMyApp(object): def CreateGui(self): with gui.GtkLocker: .... button = gtk.Button("Or me!") button.connect("clicked", gui.GtkLocked(self.Count)) vbox.pack_start(button) .... @gui.GtkLocked def Click(self, widget): self.Count() gui.GuiSecondCall( self.Count ) def Count(self, *args, **kwargs): with gui.GtkLocker: self.times += 1 self.label.set_text("You pressed button %d times" % self.times) 


рдЗрд╕рд▓рд┐рдП, рд╣рдордиреЗ рдкрд┐рдЫрд▓реЗ рдмрдЯрди рдХреЗ Click рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп Count рдкрджреНрдзрддрд┐ рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛, рдФрд░ рдПрдХ рд╕реЗрдХрдВрдб рддрдХ рдХреА рджреЗрд░реА рдХреЗ рд╕рд╛рде рдЗрд╕реЗ рджреЗрд░реА рд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛, рдЬреЛ рдордВрдЧрд▓ рдкрд░ рдореМрд╕рдо рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдХреЛрдб рдХреЛ рдЧрд┐рдирддрд╛ рдФрд░ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╕реАрдзреЗ рджреВрд╕рд░реЗ рдмрдЯрди рдкрд░ Count рд▓рдЯрдХрд╛ рджреЗрдВред
рдЪреВрдВрдХрд┐ Count рдкрджреНрдзрддрд┐ рдореЗрдВ рдЗрд╕реЗ рди рдХреЗрд╡рд▓ connect рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЙрд▓ рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ, рд╣рдо рдЗрд╕ рдкрд░ @gui.GtkLocked рдХреЛ рд▓рдЯрдХрд╛ рдирд╣реАрдВ рд╕рдХрддреЗ рд╣реИрдВ - рд╡рд┐рдзрд┐ рдХреЛ рдЕрдирдмреНрд▓реЙрдХ рд╕рдВрджрд░реНрдн (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреЗрд╡рд▓ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдИрд╡реЗрдВрдЯ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ) рд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╕реАрдзреЗ gui.GtkLocked рдХреЛ gui.GtkLocked рд╣реИрдВред connect рдХреНрд╖рдгред рдирддреАрдЬрддрди, Count рд╡рд┐рдзрд┐ рдХреЛ рдПрдХ рдЕрдирд╡рд░реЛрдзрд┐рдд рд╕рдВрджрд░реНрдн рд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдпрд╣ рд▓реЙрдХ рдХреЛ рд╕реНрд╡рдпрдВ рдХреИрдкреНрдЪрд░ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рд╕рд╛рде рд╣реА рдпрд╣ рдПрдХ рдИрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рд╣реИ рдФрд░ рдЗрд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред GtkLocker рдФрд░ GtkLocked рдХреЗ рдЬрд╛рджреВ рдХреЗ рдХрд╛рд░рдг GtkLocked рдХреЛрдИ рдЧрддрд┐рд░реЛрдз рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЕрдм рдЙрд╕рдХреА рдорд╣рд╛рдордВрджреА рдХреЛ рдкреНрд░рдЧрддрд┐ рдкрдЯреНрдЯреА рдФрд░ рдПрдХ рдЬрдЯрд┐рд▓ рдкреГрд╖реНрдарднреВрдорд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЬреЛ рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдЕрдкрдиреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреА рд╣реИ:

 class CMyApp(object): def CreateGui(self): with gui.GtkLocker: .... progress = gtk.ProgressBar() self.progress = progress vbox.pack_start(progress) T = threading.Thread(name="Background work", target=self.Generate) T.setDaemon(1) T.start() @gui.GtkLocked def UpdateProgress(self): self.progress.pulse() def Generate(self): while(True): time.sleep(0.3) gui.GuiIdleCall( self.UpdateProgress ) 


рддреЛ, рдпрд╣рд╛рдБ Generate рдореЗрдердб рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб рдХреЗ рд╡рд┐рд░реБрджреНрдз рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рд░ 0.3 рд╕реЗрдХреЗрдВрдб рдореЗрдВ рдкреНрд░рдЧрддрд┐ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдпрд╣ UpdateProgress рдХреЛ рдирд┐рд╖реНрдкрд╛рджрди UpdateProgress рдореЗрдВ рд░рдЦрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ UpdateProgress GUI рдереНрд░реЗрдб рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЪрд▓рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рдЗрд╕реЗ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рдордп рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ? рд╣рд░ рдЫреАрдВрдХ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ? 0.3 рдХреЛ 0.001 рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ - рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреА рдкреНрд░рд╢рдВрд╕рд╛ рдХрд░реЗрдВред рдирд╣реАрдВ, рдпрд╣ рдХреЛрдИ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИред рд╕рдордп рдорд╛рдк рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдХреГрддреНрд░рд┐рдо рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдзреАрдорд╛ рдХрд░реЗрдВ? рдЖрдо рддреМрд░ рдкрд░ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИред рд╢рд╛рдпрдж GuiIdleCall рдмрдЬрд╛рдп GuiIdleCall рдмрдирд╛рддреЗ рд╣реИрдВ? рдЪрд▓реЛ рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ ... рд╣рдореНрдордоред рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрдХрдВрдб рдореЗрдВ рдЗрд╕ рд╕реЗрдХрдВрдб рдХреЗ рджреМрд░рд╛рди рдкреВрд░реА рдХреА рдЧрдИ рд╕рднреА рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдПрдХ рддреЗрдЬрд╝ рдЕрдкрдбреЗрдЯ рд╣реЛрддрд╛ рд╣реИред рд╣реЙрд░рд░ред

рдЖрдЗрдП рдПрдХ рдФрд░ рдкреГрд╖реНрдарднреВрдорд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЬреЛрдбрд╝реЗрдВ, рдФрд░ рдЗрд╕рдореЗрдВ "рд╕реНрдорд╛рд░реНрдЯ" рдЕрдкрдбреЗрдЯ рд╡рд┐рдзрд┐:
 class CMyApp(object): def CreateGui(self): with gui.GtkLocker: .... fastprogress = gtk.ProgressBar() self.fastprogress = fastprogress vbox.pack_start(fastprogress) T = threading.Thread(name="Heavy background work", target=self.GenerateFast) T.setDaemon(1) T.start() @gui.SecondUpdater def SingleUpdateProgress(self): self.fastprogress.pulse() def GenerateFast(self): while(True): time.sleep(0.001) self.SingleUpdateProgress() 


рдЬрд╛рджреВ, рдЦреБрд╢реА! рд╣рдо рдХреЗрд╡рд▓ рд░рд╛рдЬреНрдп рдЕрджреНрдпрддрди рдлрд╝рдВрдХреНрд╢рди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕ рдкрд░ рдЖрд╡рд╢реНрдпрдХ рдЖрд╡рд░рдг @gui.SecondUpdater : @gui.SecondUpdater рдпрд╛ @gui.IdleUpdater , рдФрд░ рд╡рд┐рдзрд┐ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ GUI рдереНрд░реЗрдб рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдпрд╛ рдЦрд╛рд▓реА рд╕рдордп рдореЗрдВ рдПрдХ рдмрд╛рд░ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ @gui.IdleUpdater ред рдЖрд╡рд░рдгреЛрдВ рдХреЗ рдХрд╛рд░рдг, рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╡рд┐рдзрд┐ рдХреА рджреЛрд╣рд░реА рд╢реБрд░реБрдЖрдд рдХреЛ рдмрд╛рд╣рд░ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд▓реЗрдЦрд╛рдВрдХрди рдХреЛрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЪрд╛рд╣реЗ рдЗрд╕реЗ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реЛ, рдФрд░ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрди рдХрддрд╛рд░ рдореЗрдВ рд░рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

рд╣реБрдб рдХреЗ рдиреАрдЪреЗ


рддреЛ, рдЪрд▓рд┐рдП gui.py рдХреЗ рдЕрдВрджрд░ рдЬреЛ рдмрд╛рдд рд╕рд╛рдордиреЗ рдЖрдИ рд╣реИ, рдЙрд╕ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред

рд╕рд╛рдорд╛рдиреНрдп рдХреЛрдб рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИ, рдмрд╕ рдЖрд░рдВрднреАрдХрд░рдг:
 from __future__ import with_statement import logging, traceback logging.basicConfig(level=logging.DEBUG, filename='debug.log', filemode='a', format='%(asctime)s %(levelname)-8s %(module)s %(funcName)s %(lineno)d %(threadName)s %(message)s') import pygtk pygtk.require('2.0') import gtk gtk.gdk.threads_init() import gobject, gtk.glade, Queue, sys, configobj, threading, thread from functools import wraps import time, os.path gtk.gdk.threads_enter() IGuiCaller = Queue.Queue() IGuiIdleCaller = Queue.Queue() IGuiSecondsCaller = Queue.Queue() IdleCaller = [ None ] IdleCallerLock = threading.Lock() gtk.gdk.threads_leave() class CGtkLocker: .... #    GtkLocker = CGtkLocker() #   GUI  --   main_quit,   GUI  @IdleUpdater def GUIstop(*args, **kwargs): gtk.main_quit() # ,     . #    (gobject)  , #  threading.Queue,     . def GuiCall(Func): IGuiCaller.put(Func) with IdleCallerLock: if IdleCaller[0] == False: gobject.idle_add(GUIrun) IdleCaller[0] = True def GuiIdleCall(Func): IGuiIdleCaller.put(Func) with IdleCallerLock: if IdleCaller[0] == False: gobject.idle_add(GUIrun) IdleCaller[0] = True def GuiSecondCall(Func): IGuiSecondsCaller.put(Func) #    GUI  def GUIrun(): #     GuiCaller try: Run = IGuiCaller.get(0) #   idle ,  GTK   # ,   ,    #      "with GtkLocker:" ,  @GtkLocked with GtkLocker: Run() except Queue.Empty: #    --  GuiIdleCaller try: Run = IGuiIdleCaller.get(0) with GtkLocker: Run() except Queue.Empty: #     -- ,   with GtkLocker: IdleCaller[0] = False return False return True #   :     #     def GUIrunSeconds(): try: with GtkLocker: while (True): Run = IGuiSecondsCaller.get(0) Run() except Queue.Empty: pass return True #    def GUI(): #   gobject.idle_add(GUIrun) IdleCaller[0] = True gobject.timeout_add(1000, GUIrunSeconds) #     gtk.main gtk.gdk.threads_enter() #    GtkLocker, #   gtk.main    GtkLocker.FREE() #     GUI  gtk.main() #   main_quit,   main    gtk.gdk.threads_leave() 


рдЕрдм рдЖрдЗрдП рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рджреЗрдЦреЗрдВ: рд░реИрдкрд░ред рддреЛ, рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдПрдХ рд░реАрдХреНрд░реЗрдВрдЯ рд▓реЙрдХрд┐рдВрдЧ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:
 class CGtkLocker: def __init__(self): #       self.lock = threading.Lock() self.locked = 1 # ,      self.thread = thread.get_ident() #   ,     GUI    self.mainthread = self.thread self.warn = True #   ,   N  # ,     with  def __enter__(self): #       with self.lock: DoLock = (thread.get_ident()!=self.thread) #   ,   -       if self.warn and self.mainthread != thread.get_ident(): logging.error("GUI accessed from wrong thread! Traceback: "+"".join(traceback.format_stack())) #        with  ,      if DoLock: #        gtk.gdk.threads_enter() #             with self.lock: self.thread = thread.get_ident() #  __enter__    self.locked += 1 return None #     with  (  -- ,   ..) def __exit__(self, exc_type, exc_value, traceback): #      ,       with self.lock: self.locked -= 1 if self.thread!=thread.get_ident(): print "!ERROR! Thread free not locked lock!" logging.error("Thread free not locked lock!") sys.exit(0) else: if self.locked == 0: self.thread = None gtk.gdk.threads_leave() return None #    :      . def FREE(self): self.locked -= 1 self.thread = None if self.locked != 0: print "!ERROR! Main free not before MAIN!" logging.error("Main free not before MAIN!") sys.exit(0) GtkLocker = CGtkLocker() 


рдпрд╣ рд╕рдордЭрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ " with GtkLocker " GUI рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рднреА рдЯреБрдХрдбрд╝реЗ рдХреЛ рд▓рдкреЗрдЯрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдФрд░ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рднрд▓реЗ рд╣реА рд╕рднреА рдХреЙрд▓ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдереНрд░реЗрдбреНрд╕ рд╕реЗ рдЬрд╛рдПрдВ, рдЗрд╕рд▓рд┐рдП threads_enter / threads_leave рдмрдирд╛рдП threads_leave ред рдмрд╕ рдХрднреА-рдХрднреА рд╕рдм рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЕрдЪрд╛рдирдХ рдЬреАрдЯреАрдХреЗ рдХреА рдЧрд╣рд░рд╛рдИ рдореЗрдВ рдХрд╣реАрдВ рдЧрд┐рд░ рдЬрд╛рддрд╛ рд╣реИред

GtkLocker рд╕рд╛рде GtkLocker рд░реИрдкрд░ GtkLocker рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдЙрд╕ рдШрдЯрдирд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ GTK рдХрд░реНрдиреЗрд▓ рджреНрд╡рд╛рд░рд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓реЙрдХ рдХреЗ рдЕрдВрджрд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕реНрддрд░ рд╢реВрдиреНрдп рдкрд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╣ рд▓реЙрдХрд┐рдВрдЧ рд╕реНрддрд░ рдХреЗ рд╕реНрддрд░ рдХреЛ рдмрдврд╝рд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЦреБрдж рдХреЛ threads_enter / threads_leave / threads_leave рдирд╣реАрдВ рдХрд╣рддреЗ рд╣реИрдВред
 def GtkLocked(f): @wraps(f) def wrapper(*args, **kwds): with GtkLocker.lock: if GtkLocker.thread == None or GtkLocker.thread==thread.get_ident(): GtkLocker.thread = thread.get_ident() GtkLocker.locked += 1 WeHold = True else: print "!ERROR! GtkLocked for non-owned thread!" logging.error("GtkLocked for non-owned thread!") WeHold = False ret = None try: return f(*args, **kwds) finally: if WeHold: with GtkLocker.lock: GtkLocker.locked -= 1 if GtkLocker.locked == 0: GtkLocker.thread = None return wrapper 


рдЦреИрд░, рдЖрдЦрд┐рд░реА рдореИрдЬрд┐рдХ рдкрд╛рд╕: IdleUpdater / SecondUpdater :
 def IdleUpdater(f): @wraps(f) def wrapper(*args, **kwds): self = len(args)>0 and isinstance(args[0], object) and args[0] or f if '_idle_wrapper' not in self.__dict__: self._idle_wrapper = {} def runner(): if self._idle_wrapper[f]: try: return f(*args, **kwds) finally: self._idle_wrapper[f] = False return None if f not in self._idle_wrapper or not self._idle_wrapper[f]: self._idle_wrapper[f] = True #  SecondUpdater   GuiSecondCall GuiIdleCall( runner ) return wrapper 


рдЙрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬрд┐рд╕рдХрд╛ рд╡рд┐рдзрд┐ рд╣рдо рдХреЙрд▓ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, _idle_wrapper рдбрд┐рдХреНрд╢рдирд░реА _idle_wrapper , рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдореЙрдирд┐рдЯрд░рд┐рдВрдЧ рд╣реИ рдХрд┐ рджреА рдЧрдИ рд╡рд┐рдзрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдХрддрд╛рд░ рдореЗрдВ рд▓рдЧрд╛рдИ рдЧрдИ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рдФрд░ рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рд╣рдореЗрдВ рдпрд╛рдж рд╣реИ рдХрд┐ рд╣рдо рдПрдХ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рд░реИрдкрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ рдФрд░ рдпрд╛рдж рдХрд┐рдП рдЧрдП рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдЭрдВрдбреЗ рдХреЛ рд╕рд╛рдл рдХрд░реЗрдЧрд╛ред ред рдирддреАрдЬрддрди, рд╡рд┐рдзрд┐ рдХрд╛ рдкрд╣рд▓рд╛ рдХреЙрд▓ рдЕрдкрдиреЗ рд▓реЙрдиреНрдЪ рдХреЛ GuiIdleCall (рдпрд╛ *Seconds* ) рдХрддрд╛рд░ рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрдЧрд╛, рдФрд░ рдЬрдм рддрдХ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрдм рддрдХ рдмрд╛рд░-рдмрд╛рд░ рдХреЙрд▓ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдХреЛрдб рдФрд░ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ


рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рднреА рд╕реНрд░реЛрдд рдЙрдкрд▓рдмреНрдз рд╣реИрдВ: pygtk-Demo.tar.bz2 ред
PyGTK рдкрд░ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ FAQ рдореЗрдВ рдЬреНрдЮрд╛рдд рд╕рдорд╕реНрдпрд╛рдПрдБред
PyGTK рдХреЗ рддрд╣рдд рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдФрд░ рдореИрдиреБрдЕрд▓ рдХреА рдУрд░ рд░реБрдЦ рдХрд░рддрд╛ рд╣реВрдВред

Source: https://habr.com/ru/post/In120668/


All Articles