рдЬреАрдЯреАрдХреЗ + рд╕рднреА рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдПрдХ рдмрдбрд╝реА рд╕рдорд╕реНрдпрд╛ рд╣реИред GTK рд╕реНрд╡рдпрдВ рдереНрд░реЗрдб-рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдПрдХ рдордЬрдмреВрд░ рдмреНрд▓реЙрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рджреВрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реЙрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рд▓реЙрдХ рдХреЛ рдПрдХ рдмрд╛рд░ рд╕рдЦреНрддреА рд╕реЗ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЕрдиреНрдпрдерд╛ рдЖрдкрдХрд╛ рдХреЛрдб рд▓рд┐рдирдХреНрд╕ рдкрд░ рд▓рдЯрдХрд╛ рд╣реЛрдЧрд╛, рдЦрд┐рдбрд╝рдХрд┐рдпреЛрдВ рдкрд░ рдареАрдХ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред
рдЕрдиреБрднрд╡ рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдПрдХреНрд╕реЗрд╕ рд╡рд┐рдзрд┐ "рдХреЛрдИ рднреА рдзрд╛рдЧрд╛ рдЬреАрдпреВрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдореБрдЦреНрдп рдмрд╛рдд рддрд╛рд▓реЗ рдХрд╛ рдХрд╛рд░рдг рд╣реИ" рдПрдХ рд╡рд┐рдлрд▓рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рдХрд▓рд╛: рдереЛрдбрд╝реА рджреЗрд░ рдХреЗ рдмрд╛рдж, рдЖрдк рдЬреАрдЯреАрдХреЗ рдХреА рдЧрд╣рд░рд╛рдИ рдореЗрдВ рдХреЛрд░ рдбрдВрдк рдХреЛ рдХрдИ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдкрдХрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрдХрд╛рд░ рд╣реИред
рдпреВрдкреА : рдХреЛрдб
рдЧрд┐рдердм рдХреЛ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ "рдореБрдЦреНрдп" рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдХреЛрдб рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдХреЙрд╕реНрдореЗрдЯрд┐рдХ рдкрд░рд┐рд╡рд░реНрддрди (рдЕрд╡рдзрд┐ рдХреЗ рдмрдЬрд╛рдп рд╕реЗрдХрдВрдб, рдФрд░ рд╕рдорд╕реНрдпрд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд▓рдд рдзрд╛рд░рд╛ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓реЙрдЧрд┐рдВрдЧ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред
рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ, рдореЗрд░реА рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдореИрдВ рд╕реНрдЯреНрд░реАрдо рдХреЗ рд╕рд╛рде рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдорд╕реНрдпрд╛-рдореБрдХреНрдд рдХрд╛рд░реНрдп рдХреЗ рдЖрдпреЛрдЬрди рдХреА рдирд┐рдореНрди рд╡рд┐рдзрд┐ рдкрд░ рдЖрдпрд╛:
- GTK рдХреЗ рд▓рд┐рдП рдХреЛрдИ рднреА рдХреЙрд▓ рдХреЗрд╡рд▓ рдПрдХ рдзрд╛рдЧрд╛ рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИред рдЬреАрдпреВрдЖрдИ рдореЗрдВ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрди рд╕рдорд░реНрдкрд┐рдд рд░рд╛рдЬреНрдп рдЕрджреНрдпрддрди рдХрд╛рд░реНрдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
- рд╕рднреА рддрд╛рд▓реЗ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд░реЗрд╕реНрдЯреНрд░реЗрдВрдЯ рдмреНрд▓реЙрдХрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрдЪрд╛рд▓рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
- рдЕрд╡рд░реЛрдзрдХ "рдЧрд▓рдд" рд╕реНрдЯреНрд░реАрдо рд╕реЗ GUI рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реЗ рд▓реЙрдЧ рдХрд░рддрд╛ рд╣реИред
GUI рднрд╛рдЧ рдХреА рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрд░рдЪрдирд╛
рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ gui.py рдореЙрдбреНрдпреВрд▓ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд "рдЕрдЪреНрдЫрд╛" рдирд┐рд░реНрдпрд╛рдд рдХрд░рддрд╛ рд╣реИ:
GtkLocker = CGtkLocker()
рдФрд░ рдЖрд╡реЗрджрди рдЗрд╕ рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
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: ....
рдЕрдм рдЖрдЗрдП рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рджреЗрдЦреЗрдВ: рд░реИрдкрд░ред рддреЛ, рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдПрдХ рд░реАрдХреНрд░реЗрдВрдЯ рд▓реЙрдХрд┐рдВрдЧ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:
class CGtkLocker: def __init__(self):
рдпрд╣ рд╕рдордЭрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ "
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
рдЙрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬрд┐рд╕рдХрд╛ рд╡рд┐рдзрд┐ рд╣рдо рдХреЙрд▓ рдХрд░ рд░рд╣реЗ рд╣реИрдВ,
_idle_wrapper
рдбрд┐рдХреНрд╢рдирд░реА
_idle_wrapper
, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдореЙрдирд┐рдЯрд░рд┐рдВрдЧ рд╣реИ рдХрд┐ рджреА рдЧрдИ рд╡рд┐рдзрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдХрддрд╛рд░ рдореЗрдВ рд▓рдЧрд╛рдИ рдЧрдИ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рдФрд░ рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рд╣рдореЗрдВ рдпрд╛рдж рд╣реИ рдХрд┐ рд╣рдо рдПрдХ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рд░реИрдкрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ рдФрд░ рдпрд╛рдж рдХрд┐рдП рдЧрдП рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдЭрдВрдбреЗ рдХреЛ рд╕рд╛рдл рдХрд░реЗрдЧрд╛ред ред рдирддреАрдЬрддрди, рд╡рд┐рдзрд┐ рдХрд╛ рдкрд╣рд▓рд╛ рдХреЙрд▓ рдЕрдкрдиреЗ рд▓реЙрдиреНрдЪ рдХреЛ
GuiIdleCall
(рдпрд╛
*Seconds*
) рдХрддрд╛рд░ рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрдЧрд╛, рдФрд░ рдЬрдм рддрдХ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрдм рддрдХ рдмрд╛рд░-рдмрд╛рд░ рдХреЙрд▓ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдХреЛрдб рдФрд░ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рднреА рд╕реНрд░реЛрдд рдЙрдкрд▓рдмреНрдз рд╣реИрдВ:
pygtk-Demo.tar.bz2 ред
PyGTK рдкрд░ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ
FAQ рдореЗрдВ рдЬреНрдЮрд╛рдд рд╕рдорд╕реНрдпрд╛рдПрдБред
PyGTK рдХреЗ рддрд╣рдд рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░
рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдФрд░
рдореИрдиреБрдЕрд▓ рдХреА рдУрд░ рд░реБрдЦ рдХрд░рддрд╛ рд╣реВрдВред