Seite 1 von 1

Countdown-Skript ohne sleep()

Verfasst: Mittwoch 20. August 2008, 17:09
von scrawl
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

Verfasst: Mittwoch 20. August 2008, 17:17
von Hyperion
Threads! ([wiki]Threading Beispiel1)[/wiki]

Verfasst: Mittwoch 20. August 2008, 17:21
von scrawl
Puh, ist das kompliziert. Da gehts ja mit Javascript noch einfacher.
Hat niemand zufällig nen fertiges Script für mich? :?

Verfasst: Mittwoch 20. August 2008, 17:57
von epsilon
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.

Verfasst: Mittwoch 20. August 2008, 18:13
von Leonidas
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.

Verfasst: Mittwoch 20. August 2008, 18:19
von scrawl
@epsilon: Ersteres, leider.
@Leonidas: Danke, ich guck mir das mal an.

Verfasst: Mittwoch 20. August 2008, 18:23
von epsilon
@epsilon: Ersteres, leider.
Ach so.

Welches GUI toolkit verwendest du überhaupt? 'ne timer Funktion wird es doch wohl überall geben.

Verfasst: Mittwoch 20. August 2008, 19:07
von Trundle
@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.

Verfasst: Mittwoch 20. August 2008, 19:11
von scrawl
@epsilon: Benutze PyGTK

@Leonidas: Danke, so funktionierts jetzt, bist mein Held :D

Verfasst: Mittwoch 20. August 2008, 19:16
von scrawl
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.

Verfasst: Mittwoch 20. August 2008, 19:28
von Leonidas
Der Dialog müsste mit ``self.notify.destroy()`` verschwinden.

Achja, ich habe den Thread nun in das GTK-Forum verschoben.

Verfasst: Mittwoch 20. August 2008, 19:32
von lunar
Eine Alternative für Linux wäre noch "signal.alarm()" in Verbindung mit einem Handler für SIGALRM.

Verfasst: Mittwoch 20. August 2008, 19:33
von scrawl
Danke, funktioniert :D
Super Support hier