使用Tkinter运行Python(有时)无头或替换root.after()

时间:2017-01-08 14:15:40

标签: python-2.7 tkinter headless

我的工作代码如下。

我有一套用Python操作的机器。我在Tkinter中有一个gui,但很多时候这些机器在启动时自动启动python代码无法运行。

我非常喜欢使用root.after()来启动多个任务并让它们继续运行的设计模式。我的问题是,这来自Tkinter库,当无线运行时," root = Tk()"会抛出错误。

我有两个问题

  1. 我可以执行一些技巧让代码忽略没有显示的事实吗?
  2. OR

    1. 是否有一个符合Tkinter" root.after(time_in_ms,function_to_call)"的设计模式的库。
    2. 我确实尝试在Tkinter的底层代码中查看是否只有Tkinter包含的其他库,但我不具备解码该库中正在发生的事情的技能。

      此代码适用于连接的显示器:(它打印hello 11次然后结束)

      from Tkinter import *
      
      #   def __init__(self, screenName=None, baseName=None, className='Tk', useTk=1, sync=0, use=None):
      
      root = Tk()  # error is thrown here if starting this command in headless hardware setup
      
      h = None
      count = 0
      c = None
      
      
      def stop_saying_hello():
          global count
          global h
          global c
          if count > 10:
              root.after_cancel(h)
              print "counting cancelled"
          else:
              c = root.after(200, stop_saying_hello)
      
      
      def hello():
          global h
          global count
          print "hello " + str(count)
          count += 1
          h = root.after(1000, hello)
      
      
      h = root.after(1000, hello)  # time in ms, function
      c = root.after(200, stop_saying_hello)
      
      
      root.mainloop()
      

      如果这是无头运行 - 在远程计算机的ssh会话中,则返回此错误消息

        

      回溯(最近一次呼叫最后一次):文件" tkinter_headless.py",行   5,在       root = Tk()File" /usr/lib/python2.7/lib-tk/Tkinter.py" ;,第1813行, init       self.tk = _tkinter.create(screenName,baseName,className,interactive,wantobjects,useTk,sync,use)   _tkinter.TclError:没有显示名称,没有$ DISPLAY环境变量

1 个答案:

答案 0 :(得分:0)

您可以使用

或使用自己的after()mainloop()

创建自己的主管经理

简单示例

import time

class TaskManager():

    def __init__(self):
        self.tasks = dict()
        self.index = 0
        self.running = True

    def after(self, delay, callback):
        # calcuate time using delay
        current_time = time.time()*1000
        run_time = current_time + delay

        # add to tasks
        self.index += 1
        self.tasks[self.index] = (run_time, callback)

        # return index
        return self.index

    def after_cancel(self, index):
        if index in self.tasks:
            del self.tasks[index]

    def mainloop(self):

        self.running = True

        while self.running:

            current_time = time.time()*1000

            # check all tasks
            # Python 3 needs `list(self.tasks.keys())` 
            # because `del` changes `self.tasks.keys()`
            for key in self.tasks.keys():
                if key in self.tasks:
                    run_time, callback = self.tasks[key]
                    if current_time >= run_time:
                        # execute task  
                        callback()
                        # remove from list
                        del self.tasks[key]

            # to not use all CPU
            time.sleep(0.1)

    def quit(self):
        self.running = False

    def destroy(self):
        self.running = False

# --- function ---

def stop_saying_hello():
    global count
    global h
    global c

    if count > 10:
        root.after_cancel(h)
        print "counting cancelled"
    else:
        c = root.after(200, stop_saying_hello)

def hello():
    global count
    global h

    print "hello", count
    count += 1

    h = root.after(1000, hello)

# --- main ---

count = 0
h = None
c = None

root = TaskManager()

h = root.after(1000, hello)  # time in ms, function
c = root.after(200, stop_saying_hello)

d = root.after(12000, root.destroy)

root.mainloop()