0

私が書いたこの小さなプログラムがあります。その中には、メソッドのクラスと、ウィンドウを作成するクラス (1 つだけ) があります。

from Tkinter import *
from tkMessageBox import *
import socket
import platform ,sys
import subprocess
from multiprocessing.pool import ThreadPool
import Queue
import threading

class Methods(object):
    def __init__(self):
         #TODO : implement
        pass

    def getHostName(self):
        try:
            return socket.gethostname()
        except:
            return "ERROR :Could'nt get Hostname"

    def getOperatingSystem(self):
        try:
            return platform.system() + " " + platform.release() + " " + platform.version() + " " + sys.getwindowsversion()[4]
        except:
            return "ERROR :Could'nt get Operating System"

    def getHotFixes(self,queue):
        try:
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            myProcess = subprocess.Popen(
                "wmic qfe get HotFixID, InstalledOn",
                stdout = subprocess.PIPE,
                stderr = subprocess.PIPE,
                startupinfo = startupinfo)
            out, error = myProcess.communicate()
            full_list = out.splitlines()
            result = ""
            for item in full_list:
                if item != "" and item != " ":
                    result += "%s \n" % item

            out_number = len(result.splitlines()) - 1
            a =  "There Are %s Microsoft HotFixes Updates \n\n%s" % (out_number , result)
            queue.put(a)
        except:
            return "ERROR :Could'nt get HotFixes"


#VISUAL
#This class will have an instance of Methods and call every action by itself.
class MainWindow(object):
    def __init__(self):
        self.root = Tk()
        self.root.title('SAAP')
        self.root.geometry('610x440+100+100')
        #self.root.resizable(0,0)
        self.methods = Methods()

        def openHostName():
            disableAllButtons(self)
            result = self.methods.getHostName()
            print result
            self.textLabelString.set("Host Name")
            self.textBox.config(state=NORMAL)
            self.textBox.delete("1.0",END)
            self.textBox.insert(INSERT,result)
            self.textBox.config(state=DISABLED)
            enableAllButtons(self)

        def openOperatingSystem():
            disableAllButtons(self)
            result = self.methods.getOperatingSystem()
            print result
            self.textLabelString.set("Operating System")
            self.textBox.config(state=NORMAL)
            self.textBox.delete("1.0",END)
            self.textBox.insert(INSERT,result)
            self.textBox.config(state=DISABLED)
            enableAllButtons(self)

        def openHotFixes():
            queue = Queue.Queue()
            thread_ = threading.Thread(
                target = self.methods.getHotFixes,
                name='Thread1',
                args=[queue],
                )
            thread_.start()
            thread_.join()
            result = queue.get()
            disableAllButtons(self)
            self.textLabelString.set("Microsoft Hotfixes")
            self.textBox.config(state=NORMAL)
            self.textBox.delete("1.0",END)
            self.textBox.insert(INSERT,result)
            self.textBox.config(state=DISABLED)
            enableAllButtons(self)



        #items decleration
        self.actionLabel = Label(self.root, text = 'Actions',bg='blue',fg='white')
        self.button1 = Button(self.root, text = 'Host Name' , command=openHostName)
        self.button2 = Button(self.root, text = 'Operating System' , command = openOperatingSystem)
        self.button3 = Button(self.root, text = 'Microsoft HotFixes' , command = openHotFixes)
        self.button4 = Button(self.root, text = 'N4')
        self.button5 = Button(self.root, text = 'Fi5o')
        self.button6 = Button(self.root, text = 'C6y')
        self.button7 = Button(self.root, text = '7')
        self.button8 = Button(self.root, text = '8y')
        self.button9 = Button(self.root, text = 'R9s')
        self.button10 = Button(self.root, text = '10t')
        self.button11 = Button(self.root, text = 'I11s')
        self.textLabelString = StringVar()
        self.textLabel = Label(self.root,bg='black',fg='white',width=60,textvariable=self.textLabelString)
        self.textLabelString.set("Output")
        self.textBox = Text(self.root,width=52)
        self.textBox.insert(INSERT,"Here's the output")
        self.textBox.config(state=DISABLED)
        self.scrollBar = Scrollbar(self.root)
        self.scrollBar.config(command=self.textBox.yview)
        self.textBox.config(yscrollcommand=self.scrollBar.set)

        #items placing
        self.actionLabel.grid(row=0,column=0,sticky=W+E+N+S,pady=5)
        self.button1.grid(row=1,column=0,padx=5,pady=5,sticky=W+E)
        self.button2.grid(row=2,column=0,padx=5,pady=5,sticky=W+E)
        self.button3.grid(row=3,column=0,padx=5,pady=5,sticky=W+E)
        self.button4.grid(row=4,column=0,padx=5,pady=5,sticky=W+E)
        self.button5.grid(row=5,column=0,padx=5,pady=5,sticky=W+E)
        self.button6.grid(row=6,column=0,padx=5,pady=5,sticky=W+E)
        self.button7.grid(row=7,column=0,padx=5,pady=5,sticky=W+E)
        self.button8.grid(row=8,column=0,padx=5,pady=5,sticky=W+E)
        self.button9.grid(row=9,column=0,padx=5,pady=5,sticky=W+E)
        self.button10.grid(row=10,column=0,padx=5,pady=5,sticky=W+E)
        self.button11.grid(row=11,column=0,padx=5,pady=5,sticky=W+E)
        self.textLabel.grid(row=0,column=1,padx=10,pady=5)
        self.textBox.grid(row=1,column=1,rowspan=11,pady=5)
        self.scrollBar.grid(row=1,column=2,rowspan=11,sticky=N+S)

        def disableAllButtons(self):
            self.button1['state'] = DISABLED
            self.button2['state'] = DISABLED
            self.button3['state'] = DISABLED
            self.button4['state'] = DISABLED
            self.button5['state'] = DISABLED
            self.button6['state'] = DISABLED
            self.button7['state'] = DISABLED
            self.button8['state'] = DISABLED
            self.button9['state'] = DISABLED
            self.button10['state'] = DISABLED
            self.button11['state'] = DISABLED

        def enableAllButtons(self):
            self.button1['state'] = NORMAL
            self.button2['state'] = NORMAL
            self.button3['state'] = NORMAL
            self.button4['state'] = NORMAL
            self.button5['state'] = NORMAL
            self.button6['state'] = NORMAL
            self.button7['state'] = NORMAL
            self.button8['state'] = NORMAL
            self.button9['state'] = NORMAL
            self.button10['state'] = NORMAL
            self.button11['state'] = NORMAL


def main():
    mainw = MainWindow()
    mainw.root.mainloop()

if __name__ == "__main__":
    main()

さて、私の問題は、何かをする必要があるボタンを押すと、出力が画面に表示されることです。しかし、ここに来るのはしかし - アクションに少し時間がかかると、アクションが完了するまでプログラムがフリーズします。プログラムがフリーズしないように、アクションを別のスレッドとして扱うようにしたいと考えています。いろいろ試してみましたが、残念ながらうまくいきませんでした...

ヘルプはありますか?感謝!

4

1 に答える 1

1

アクションを別々のスレッドで実行しても問題ありませんが、アクションが終了したときにメイン スレッド (Tk のループが実行されている場所) に通知し、結果を取得するためのメカニズムを実装する必要があります。

1 つのアプローチは、適切な Action クラスを用意して、スレッド オブジェクトを作成することです。実行するメソッドとその引数を渡し、スレッドを開始します。事前に、アクションが終了したときに Tk ループで呼び出されるコールバックを登録します。スレッドからコールバックに結果を渡すために、キューを使用できます。

import functools

class Action(threading.Thread):
    def __init__(self, method, *args):
        threading.Thread.__init__(self)
        self.daemon = True
        self.method=method
        self.args=args
        self.queue=Queue.Queue()
    def run(self):
        self.queue.put(self.method(*self.args))
    def register_callback(self, tkroot, callback):
        # to be called by Tk's main thread,
        # will execute the callback in the Tk main loop
        try:
            result = self.queue.get_nowait()
        except:
            # set a timer, to check again for results within 100 milliseconds
            tkroot.after(100, functools.partial(self.register_callback,
                                                tkroot, callback))
        else:
            return callback(result)

編集:getHotFixesこれを メソッドに適用する方法を示す元の例の変更

getHotFixes例として、それに応じて変更する方法を次に示します。

class Methods(object):
    ...
    def getHotFixes(self):
        try:
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            myProcess = subprocess.Popen("wmic qfe get HotFixID, InstalledOn",
                stdout = subprocess.PIPE,
                stderr = subprocess.PIPE,
                startupinfo = startupinfo)
            out, error = myProcess.communicate()
            full_list = out.splitlines()
            result = ""
            for item in full_list:
                if item != "" and item != " ":
                result += "%s \n" % item

            out_number = len(result.splitlines()) - 1
            return "There Are %s Microsoft HotFixes Updates \n\n%s" % (out_number , result)
        except:
            return "ERROR :Could'nt get HotFixes"

最後に、メソッドMainWindowを呼び出す必要があるだけですgetHotFixes。コールバックを登録して、使用が終了したときに結果で何か役立つことを行い register_callback、呼び出しstart()てアクション スレッドを開始します。

class MainWindow(object):
    def __init__(self):
        self.root = Tk()
        ...
        def openHotFixes():
            disableAllButtons(self)
            action = Action(self.methods.getHotFixes)
            action.register_callback(self.root, openHotFixesDone)
            action.start()

        def openHotFixesDone(result):
            self.textLabelString.set("Microsoft Hotfixes")
            self.textBox.config(state=NORMAL)
            self.textBox.delete("1.0",END)
            self.textBox.insert(INSERT,result)
            self.textBox.config(state=DISABLED)
            enableAllButtons(self)

お役に立てれば。

于 2013-10-01T22:36:16.070 に答える