Problem mit GUI und endlosschleife.

Fragen zu Tkinter.
Antworten
Psus82
User
Beiträge: 128
Registriert: Dienstag 6. April 2004, 16:15

Tach,

Meine GUI lässt sich nicht mehr bedienen sobald mein Script läuft.
Ich habe eine Endlosschleife eingebaut.
Aber die habe ich momentan mit einer while auf 4 durchgänge gestellt.
Sobald die Schleife zu ende ist kann ich die GUI wieder bedienen.
Kann ich das ändern?
Ich will auch während der Schleife drauf zugreifen können.

Psus82
Drei Dinge die Programmierer hassen:
1.)Sonnenlicht
2.)Frische Luft
3.)Das ätzende Geräusch zwitschernder Vögel
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Schmeiss die Schleife einfach in einen eigenen Thread:

Code: Alles auswählen

from Tkinter import *
import time
import thread

def go():
    thread.start_new_thread(endless,())

def endless():
    i = 0
    while 1:
        l.configure(text=i)
        time.sleep(1)
        i += 1

def print_it():
    print "hello"

root = Tk()
l = Label()
l.pack()
Button(text="Go", command=go).pack()
Button(text="Print", command=print_it).pack()
root.mainloop()
Gruß, mawe
Psus82
User
Beiträge: 128
Registriert: Dienstag 6. April 2004, 16:15

Erst einmal danke.

Jetzt kann ich auf die Gui zugreifen.
Gibt es eine Möglichkeit den Thread oder die Endlosschleife durch einen Button auf der GUI zu stoppen?

Psus82
Drei Dinge die Programmierer hassen:
1.)Sonnenlicht
2.)Frische Luft
3.)Das ätzende Geräusch zwitschernder Vögel
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Code: Alles auswählen

from Tkinter import *
import time
import thread


class TimerTest:
    def __init__(self):
        self.status = 1
        root = Tk()
        self.l = Label()
        self.l.pack()
        Button(text="Go", command=self.go).pack()
        Button(text="Stop", command=self.stop_it).pack()
        Button(text="Print", command=self.print_it).pack()
        root.mainloop()
        
    def go(self):
        self.status = 1
        thread.start_new_thread(self.endless,())

    def endless(self):
        i = 0
        while self.status:
            self.l.configure(text=i)
            time.sleep(1)
            i += 1

    def stop_it(self):
        self.status = 0

    def print_it(self):
        print "hello"

TimerTest()
Gruß, mawe
Psus82
User
Beiträge: 128
Registriert: Dienstag 6. April 2004, 16:15

Hier ist mein Quellcode Mawe.
Kannste mal drüber schauen.
Irgendwie kriege ich das nicht hin. :(

Code: Alles auswählen

from Tkinter import * 
import sys 
import tkFileDialog 
import tkSimpleDialog 
import os,time 
import smtplib
import pickle
import thread

class FolderScanner:

    def _init_(self):
        self.Status = 1
        Mainwindow = Tk() 
        Mainwindow.geometry("400x250+0+0") 

        RunScriptButton = Button(Mainwindow, text = "Run script", bg = "green", width = 25, height = 2, command = Thread) 
        RunScriptButton.place(x = 25, y = 30) 

        StopScriptButton = Button(Mainwindow, text = "Stop script",bg = "red", width = 25, height = 2, command = Stopscript) 
        StopScriptButton.place(x = 215, y = 30) 

        ChangeFolderButton = Button(Mainwindow, text = "Choose folder to scan", width = 25, command = ChangeFolder) 
        ChangeFolderButton.place(x = 25, y = 100) 

        ChangeMailAdressButton = Button(Mainwindow, text = "Choose mailadress", width = 25, command = EmailAdress) 
        ChangeMailAdressButton.place(x = 215, y = 100) 

        ChangeLogButton = Button(Mainwindow, text = "Choose destination of logfile", width = 25, command = DefineLogFolder) 
        ChangeLogButton.place(x = 215, y = 150) 

        ChangeTimeButton = Button(Mainwindow, text = "Choose repeattime of script(sek.)", width = 25, command = Repeattime)  
        ChangeTimeButton.place(x = 25, y = 150) 

        ChangeLogButton = Button(Mainwindow, text = "Create Log Files",bg = "yellow", width = 25, command = CreateLogFiles) 
        ChangeLogButton.place(x = 117.5 ,y = 200) 

        mainloop()
        
        def ChangeFolder(self): 
            global FolderToScan
            FolderToScan = tkFileDialog.askdirectory() 


        def EmailAdress(self): 
            global EmailAdress
            EmailAdress = tkSimpleDialog.askstring("E-Mail","E-Mailadress:")

        def CreateLogFiles(self):
            global FolderToSaveLog
            FolderToSaveLog = tkFileDialog.askdirectory()
            FakeToStart = [('Fake.pdf', 1111111111), ('Fake.txt', 1111111111)] 
            os.chdir(FolderToSaveLog)
            open('log.txt','w').close()
            Txt = open('log2.txt','w')
            pickle.dump(FakeToStart,Txt)
            Txt.close()

        def DefineLogFolder(self):
            global FolderToSaveLog
            FolderToSaveLog = tkFileDialog.askdirectory()

                             
        def Repeattime(self):
            global Time
            Time = tkSimpleDialog.askinteger("Repeattime","Repeattime(sek.):") 

        def Stopscript(self):
            self.Status = 0
    
        def Thread(self):
            self.Status = 1
            thread.start_new_thread(self.Scanning,())
 
        def Scanning (self):
           global AccessTimeNew
           global AccessTimeOld
           i = 0
    
           while self.Status:
                 i += 1
                 FilesNew = os.listdir(FolderToScan)
                 F = file(FolderToSaveLog + "/log.txt", "r")
                 Tempdata1 = F.read()
                 F.close()
                 FilesOld = Tempdata1.split("/n")
                 AccessTimeNew = [(f, os.path.getmtime(FolderToScan+ "/"+f)) for f in os.listdir(FolderToScan) if os.path.isfile(FolderToScan+"/"+f)]
                 F2 = file(FolderToSaveLog + "/log2.txt","r")
                 AccessTimeOld = pickle.load(F2)
                 F2.close()

                 if FilesNew == FilesOld and AccessTimeNew == AccessTimeOld:
                    time.sleep(Time)
                    continue
                                        
                 else:
                    FilesNew = os.listdir(FolderToScan)
                    AccessTimeNew = [(f, os.path.getmtime(FolderToScan+ "/"+f)) for f in os.listdir(FolderToScan) if os.path.isfile(FolderToScan+"/"+f)] 
                    FilesChange = [i for i in FilesNew if not i in FilesOld]
                    FilesRemoved =[i for i in FilesOld if not i in FilesNew]
                    FilesAccessChanged =[i for i in AccessTimeNew if not i in AccessTimeOld]
                    Mailtext = "New Files:"+str(FilesChange)+"\n\n"+"Removed Files:"+str(FilesRemoved)+"\n\n"+"Changed Files:"+str(FilesAccessChanged)
                    Host = smtplib.SMTP('AMOR-02')
                    Host.sendmail(EmailAdress,EmailAdress,Mailtext)
                    {}
                    Host.quit()
                    FilesOld = FilesNew
                    Tempdata2 = "/n".join(FilesOld)
                    F = file(FolderToSaveLog + "/log.txt", "w")
                    F.write(Tempdata2) 
                    F.close()
                    AccessTimeOld = AccessTimeNew
                    F2 = file(FolderToSaveLog + "/log2.txt","w")
                    Tempdata4 = pickle.dump(AccessTimeOld,F2)
                    F2.close()
                    time.sleep(Time)
                    continue
                   
FolderScanner()

      


Psus82
Drei Dinge die Programmierer hassen:
1.)Sonnenlicht
2.)Frische Luft
3.)Das ätzende Geräusch zwitschernder Vögel
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Wo soll ich anfangen ... :wink:
1) __init__ hat 2 _ vorne und hinten
2) Pass auf die Einrückung auf! In Deiner Klasse sollten alle defs gleich weit eingerückt sein, also genau untereinander stehen.
3) Methoden der Klasse ruft man (aus der Klasse heraus) mit self.methodenname auf.

Code: Alles auswählen

StopScriptButton = Button(Mainwindow, text="Stop script", command=self.Stopscript)
4) Was machen denn die global in der Klasse? Schreib bei allen Variablen die Du in der gesamten Klasse verfügbar haben willst (also alle die bei Dir "global" sind) self.Variablenname. z.B.

Code: Alles auswählen

def ChangeFolder(self):
    self.FolderToScan = tkFileDialog.askdirectory()
    # im der gesamten Klasse FolderToScan in self.FolderToScan austauschen!
Naja, ich glaub das war's mal fürs Erste :wink:

Gruß, mawe
Psus82
User
Beiträge: 128
Registriert: Dienstag 6. April 2004, 16:15

Dank dir Mawe.

Geht es irgendwie das sich die Farbe des Run Buttons während die Schleife läuft ändert von Grün in Rot?

Psus82
Drei Dinge die Programmierer hassen:
1.)Sonnenlicht
2.)Frische Luft
3.)Das ätzende Geräusch zwitschernder Vögel
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Die Farbe kannst Du mit configure ändern

Code: Alles auswählen

self.RunScriptButton.configure(bg="red")
Gruß, mawe
Psus82
User
Beiträge: 128
Registriert: Dienstag 6. April 2004, 16:15

Klappt danke.
Habe auch nix anderes erwartet :D .
Drei Dinge die Programmierer hassen:
1.)Sonnenlicht
2.)Frische Luft
3.)Das ätzende Geräusch zwitschernder Vögel
Benutzeravatar
Robin
User
Beiträge: 50
Registriert: Dienstag 26. Juni 2007, 10:47

Die grafische Darstellung und der Aufruf einer Endlos-Schleife interessieren mich auch sehr.
Ich habe mein Programm auch so aufgebaut wie weiter oben. Nur gibt es ein Problem bei Euren und meinem Beispiel-Programm, der Arbeitsspeicher wächst beständig. Mein Programm muss Tag und Nacht laufen, es wird dann immer langsamer. Woran kann das liegen?
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Hallo Robin,

wie BlackJack schon saget, wäre nicht schlecht, wenn du mal deinen Code Zeigst.

Eventuell ist es dann ersichtlicher was man da machen kann.


MfG
pyStyler
Benutzeravatar
Robin
User
Beiträge: 50
Registriert: Dienstag 26. Juni 2007, 10:47

Hallo pyStyler,
hier wäre der Code, man muss etwas warten, aber der Arbeitsspeicher
wächst. Mein Programm soll Tag und Nacht laufen und hat den prinzipiellen
Aufbau wie dieses hier. Wird go() immer wieder neu gestartet während
mainloop()?


Gruß Robin

Code: Alles auswählen


from Tkinter import *
import time
import thread

def go():
    thread.start_new_thread(endless,())

def endless():
    i = 0
    while 1:
        l.configure(text=i)
        # time.sleep(1)
        i += 100

def print_it():
    print "hello"

root = Tk()
l = Label()
l.pack()
go()
root.mainloop() 
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das Hauptproblem dürfte wohl sein, dass Du aus zwei unterschiedlichen Threads auf die GUI zugreifst. Dadurch wird das Verhalten unvorhersehbar.
Desweiteren:

Code: Alles auswählen

l.configure(text=str(i))
und

Code: Alles auswählen

l = Label(root)
Mfg
HWK
Antworten