Countdown-Skript ohne sleep()

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
scrawl
User
Beiträge: 40
Registriert: Mittwoch 20. August 2008, 17:04
Kontaktdaten:

Hi,

ich würde in mein Programm gerne eine Countdown-Funktion integrieren, also dass ab einer bestimmten Zahl runtergezählt wird bis 0. Habe bisher aber nur Lösungen gefunden die time.sleep() benutzen, was dann dazu führt, dass die GUI sich aufhängt.
Weiß da jemand ne Lösung? Wäre euch sehr dankbar.

MfG scrawl
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Threads! ([wiki]Threading Beispiel1)[/wiki]
scrawl
User
Beiträge: 40
Registriert: Mittwoch 20. August 2008, 17:04
Kontaktdaten:

Puh, ist das kompliziert. Da gehts ja mit Javascript noch einfacher.
Hat niemand zufällig nen fertiges Script für mich? :?
epsilon
User
Beiträge: 71
Registriert: Freitag 20. Juni 2008, 19:48

Soll die verbleibende Zeit angezeigt werden oder soll nur eine bestimmte Funktion ausgeführt werden, wenn die Zeit vorbei ist.

Bei Letzterem dürfte Timer nützlich sein.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

scrawl hat geschrieben:Da gehts ja mit Javascript noch einfacher.
Natürlich geht es einfacher, da der Browser den Interpreter in einem eigenen Thread hat und man Callbacks nach bestimmeter Zeit aufrufen kann.

In PyGTK ist soetwas auch einfach möglich, man nutzt einfach ``gobject.timeout_add()``, welches eine Funktion alle n Millisekunden aufruft ohne dass die GUI blockiert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
scrawl
User
Beiträge: 40
Registriert: Mittwoch 20. August 2008, 17:04
Kontaktdaten:

@epsilon: Ersteres, leider.
@Leonidas: Danke, ich guck mir das mal an.
epsilon
User
Beiträge: 71
Registriert: Freitag 20. Juni 2008, 19:48

@epsilon: Ersteres, leider.
Ach so.

Welches GUI toolkit verwendest du überhaupt? 'ne timer Funktion wird es doch wohl überall geben.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

@Hyperion: Threads sind nicht unbedingt immer die Universalantwort. Ich denke mal, dass dafür jedes Toolkit eine Funktion zur Verfügung stellt. Für PyGtk hat die Leonidas schon genannt, für wxPython ist es wohl `wx.CallLater` und alle anderen Toolkits dürften das wohl auch haben.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
scrawl
User
Beiträge: 40
Registriert: Mittwoch 20. August 2008, 17:04
Kontaktdaten:

@epsilon: Benutze PyGTK

@Leonidas: Danke, so funktionierts jetzt, bist mein Held :D
scrawl
User
Beiträge: 40
Registriert: Mittwoch 20. August 2008, 17:04
Kontaktdaten:

Hier mal mein Programm falls es noch wen interessiert (eines meiner ersten, nicht meckern^^)

Code: Alles auswählen

#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gtk
import gobject
import time

class Lukas:
	time = 20
	clicks = 0
	
	def close_window(self, widget, event, data=None):
		gtk.main_quit()
		return False
		
	def increase_clicks(self, widget, event, data=None):
		self.clicks = self.clicks + 1
		self.str_clicks = str(self.clicks)
		self.score_display.set_text(self.str_clicks + ' Klicks')
		
	def countdown_time(self):
		self.time = self.time - 1
		self.str_time = str(self.time)
		print self.str_time
		self.time_display.set_text('Noch ' + self.str_time + ' Sekunden')
		if self.time == 0: # if time is up
			self.click_button.disconnect(self.clicker) # stop click count
			self.notify = gtk.Dialog('Zeit vorbei!')
			self.pointlabel = gtk.Label('Deine Punktzahl: ' + str(self.clicks))
			self.pointlabel.show()
			self.notify.add_action_widget(self.pointlabel, 1)
			self.notify.add_button('Nochmal', 2)
			self.notify.add_button('Beenden', 3)
			signal = self.notify.run()
			print signal
			if signal == 2: # restart
				self.restart_game()
				return False
			if signal == 3: # quit
				gtk.main_quit()
				return False
			return False
		return True
		
	def restart_game(self):
		print "Restarting"
		self.time = 20
		self.clicks = 0
		self.clicker = self.click_button.connect("clicked", self.increase_clicks, None)
		self.timer = self.click_button.connect("clicked", self.start_timer, None)
		self.score_display.set_text('0 Klicks')
		self.time_display.set_text('Noch 20 Sekunden')
		
	def start_timer(self, widget, event, data=None):
		print "Starting timer"
		gobject.timeout_add(1000, self.countdown_time)
		self.click_button.disconnect(self.timer)
	
	def __init__(self):
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_title('Klick den Lukas')
		self.window.set_border_width(5)
		self.window.resize(300, 200)
		
		self.content_box = gtk.VBox(False, 0)
		self.click_button = gtk.Button('Klick mich')
		self.score_display = gtk.Label('0 Klicks')
		self.time_display = gtk.Label('Noch 20 Sekunden')
		
		self.content_box.pack_start(self.click_button, True, True, 0)
		self.content_box.pack_start(self.score_display, True, True, 0)
		self.content_box.pack_start(self.time_display, True, True, 0)
		
		self.window.add(self.content_box)
		
		self.window.connect("delete_event", self.close_window)
		self.clicker = self.click_button.connect("clicked", self.increase_clicks, None)
		self.timer = self.click_button.connect("clicked", self.start_timer, None)
		
		self.click_button.show()
		self.score_display.show()
		self.time_display.show()
		self.content_box.show()
		self.window.show()
		
def main():
	gtk.main()

if __name__ == '__main__':
	app = Lukas()
	main()

Nur eine Sache will noch nicht, nämlich wenn man auf 'Nochmal' klickt soll der auch den Dialog schließen. Weiß jemand wie das geht? In der Referenz hab ich nichts brauchbares gefunden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Der Dialog müsste mit ``self.notify.destroy()`` verschwinden.

Achja, ich habe den Thread nun in das GTK-Forum verschoben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

Eine Alternative für Linux wäre noch "signal.alarm()" in Verbindung mit einem Handler für SIGALRM.
scrawl
User
Beiträge: 40
Registriert: Mittwoch 20. August 2008, 17:04
Kontaktdaten:

Danke, funktioniert :D
Super Support hier
Antworten