كيف يمكنك تشغيل التعليمات البرمجية الخاصة بك جنبا إلى جنب مع حلقة الحدث Tkinter على ذلك؟

StackOverflow https://stackoverflow.com/questions/459083

  •  19-08-2019
  •  | 
  •  

سؤال

وأخي الصغير هو مجرد الدخول في البرمجة، ومشروعه معرض العلوم، يفعل محاكاة لسرب من الطيور في السماء. انه حصلت أكثر من التعليمات البرمجية المكتوب، وأنها تعمل بشكل جيد، ولكن تحتاج الطيور إلى التحرك <م> كل لحظة .

وTkinter، ومع ذلك، الخنازير الوقت لحلقة الحدث الخاصة بها، وهكذا سوف كود له لا تعمل. القيام أشواط root.mainloop()، ويدير، ويبقي على التوالي، والشيء الوحيد الذي يعمل هو معالجات الأحداث.

هل هناك وسيلة لديك التعليمات البرمجية له تشغيل جنبا إلى جنب مع mainloop (بدون خاصية تعدد، انها مربكة وهذا يجب أن تبقى بسيطة)، وإذا كان الأمر كذلك، ما هو؟

والآن، وقال انه جاء مع الإختراق القبيح، وربط وظيفته move() إلى <b1-motion>، بحيث طالما انه يحمل على زر أسفل ويهتز الماوس، وأنها تعمل. ولكن هناك يجب أن تكون هناك طريقة أفضل.

هل كانت مفيدة؟

المحلول

استخدم طريقة after على الكائن Tk:

from tkinter import *

root = Tk()

def task():
    print("hello")
    root.after(2000, task)  # reschedule event in 2 seconds

root.after(2000, task)
root.mainloop()

وهنا إعلان وثائق للأسلوب after:

def after(self, ms, func=None, *args):
    """Call function once after given time.

    MS specifies the time in milliseconds. FUNC gives the
    function which shall be called. Additional parameters
    are given as parameters to the function call.  Return
    identifier to cancel scheduling with after_cancel."""

نصائح أخرى

المرسلة بواسطة النتائج بيورن في "RuntimeError: دعوة تى سى ال من مختلف شقة" رسالة على جهاز الكمبيوتر الخاص بي (ريدهات المؤسسة 5، بيثون 2.6.1). بيورن لا قد حصلت هذه الرسالة، لأنه، وفقا ل مكان واحد I فحص أو سوء خيوط مع Tkinter لا يمكن التنبؤ بها والتي تعتمد على المنصة.

والمشكلة يبدو أن أن التهم app.start() كمرجع لتاكا، منذ التطبيق يحتوي على عناصر تاكا. أنا ثابت ذلك من خلال استبدال app.start() مع self.start() داخل __init__. كما أنني جعلت حتى يتسنى لجميع المراجع تاكا إما داخل <م> وظيفة أن يدعو mainloop() أو في الداخل <م> الوظائف التي دعا اليها الدالة التي تدعو mainloop() (وهذا أمر بالغ الأهمية على ما يبدو ل تجنب الخطأ "شقة مختلفة").

وأخيرا، وأضفت معالج بروتوكول مع الاستدعاء، لأنه بدون هذا البرنامج يخرج مع وجود خطأ عند إغلاق نافذة تاكا من قبل المستخدم.

ووالقانون المعدل كما يلي:

# Run tkinter code in another thread

import tkinter as tk
import threading

class App(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.start()

    def callback(self):
        self.root.quit()

    def run(self):
        self.root = tk.Tk()
        self.root.protocol("WM_DELETE_WINDOW", self.callback)

        label = tk.Label(self.root, text="Hello World")
        label.pack()

        self.root.mainloop()


app = App()
print('Now we can continue running code while mainloop runs!')

for i in range(100000):
    print(i)

عند كتابة حلقة الخاصة بك، كما هو الحال في المحاكاة (افترض)، تحتاج إلى استدعاء الدالة update الذي يفعل ما يفعل mainloop: بتحديث نافذة مع التغييرات، ولكن يمكنك أن تفعل ذلك في حلقة الخاص بك

def task():
   # do something
   root.update()

while 1:
   task()  

وثمة خيار آخر هو السماح tkinter تنفيذ على موضوع منفصل. طريقة واحدة للقيام بذلك هي من هذا القبيل:

import Tkinter
import threading

class MyTkApp(threading.Thread):
    def __init__(self):
        self.root=Tkinter.Tk()
        self.s = Tkinter.StringVar()
        self.s.set('Foo')
        l = Tkinter.Label(self.root,textvariable=self.s)
        l.pack()
        threading.Thread.__init__(self)

    def run(self):
        self.root.mainloop()


app = MyTkApp()
app.start()

# Now the app should be running and the value shown on the label
# can be changed by changing the member variable s.
# Like this:
# app.s.set('Bar')

كن حذرا على الرغم من مؤشرات البرمجة صعبة وأنه من السهل حقا لاطلاق النار نفسك في القدم. على سبيل المثال عليك أن تكون حذرا عند تغيير المتغيرات عضو من الطبقة عينة أعلاه بحيث لا يقطع مع الحدث حلقة من Tkinter.

وهذا هو الإصدار الأول من العمل ما سوف يكون القارئ GPS ومقدم البيانات. tkinter هو شيء هش للغاية مع رسائل الخطأ قليل جدا من الطريق. فإنه لا يضع الاشياء ولا يقول لماذا الكثير من الوقت. من الصعب جدا قادمة من الجيد شكل WYSIWYG المطور. على أي حال، هذا يدير صغيرة الروتيني 10 مرة في الثانية، ويقدم المعلومات في نموذج. استغرق بعض الوقت لتحقيق ذلك. عندما حاولت قيمة الموقت 0، شكل أبدا خرجت. رأسي يؤلمني الآن! 10 مرات أو أكثر في الثانية الواحدة هي جيدة بما فيه الكفاية بالنسبة لي. وآمل أن يساعد شخص آخر. مايك مورو

import tkinter as tk
import time

def GetDateTime():
  # Get current date and time in ISO8601
  # https://en.wikipedia.org/wiki/ISO_8601 
  # https://xkcd.com/1179/
  return (time.strftime("%Y%m%d", time.gmtime()),
          time.strftime("%H%M%S", time.gmtime()),
          time.strftime("%Y%m%d", time.localtime()),
          time.strftime("%H%M%S", time.localtime()))

class Application(tk.Frame):

  def __init__(self, master):

    fontsize = 12
    textwidth = 9

    tk.Frame.__init__(self, master)
    self.pack()

    tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
             text='Local Time').grid(row=0, column=0)
    self.LocalDate = tk.StringVar()
    self.LocalDate.set('waiting...')
    tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
             textvariable=self.LocalDate).grid(row=0, column=1)

    tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
             text='Local Date').grid(row=1, column=0)
    self.LocalTime = tk.StringVar()
    self.LocalTime.set('waiting...')
    tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
             textvariable=self.LocalTime).grid(row=1, column=1)

    tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
             text='GMT Time').grid(row=2, column=0)
    self.nowGdate = tk.StringVar()
    self.nowGdate.set('waiting...')
    tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
             textvariable=self.nowGdate).grid(row=2, column=1)

    tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
             text='GMT Date').grid(row=3, column=0)
    self.nowGtime = tk.StringVar()
    self.nowGtime.set('waiting...')
    tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
             textvariable=self.nowGtime).grid(row=3, column=1)

    tk.Button(self, text='Exit', width = 10, bg = '#FF8080', command=root.destroy).grid(row=4, columnspan=2)

    self.gettime()
  pass

  def gettime(self):
    gdt, gtm, ldt, ltm = GetDateTime()
    gdt = gdt[0:4] + '/' + gdt[4:6] + '/' + gdt[6:8]
    gtm = gtm[0:2] + ':' + gtm[2:4] + ':' + gtm[4:6] + ' Z'  
    ldt = ldt[0:4] + '/' + ldt[4:6] + '/' + ldt[6:8]
    ltm = ltm[0:2] + ':' + ltm[2:4] + ':' + ltm[4:6]  
    self.nowGtime.set(gdt)
    self.nowGdate.set(gtm)
    self.LocalTime.set(ldt)
    self.LocalDate.set(ltm)

    self.after(100, self.gettime)
   #print (ltm)  # Prove it is running this and the external code, too.
  pass

root = tk.Tk()
root.wm_title('Temp Converter')
app = Application(master=root)

w = 200 # width for the Tk root
h = 125 # height for the Tk root

# get display screen width and height
ws = root.winfo_screenwidth()  # width of the screen
hs = root.winfo_screenheight() # height of the screen

# calculate x and y coordinates for positioning the Tk root window

#centered
#x = (ws/2) - (w/2)
#y = (hs/2) - (h/2)

#right bottom corner (misfires in Win10 putting it too low. OK in Ubuntu)
x = ws - w
y = hs - h - 35  # -35 fixes it, more or less, for Win10

#set the dimensions of the screen and where it is placed
root.geometry('%dx%d+%d+%d' % (w, h, x, y))

root.mainloop()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top