Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python3中如何在编译器睡眠时消磨时间.sleep()_Python_Tkinter - Fatal编程技术网

在Python3中如何在编译器睡眠时消磨时间.sleep()

在Python3中如何在编译器睡眠时消磨时间.sleep(),python,tkinter,Python,Tkinter,我想在按下停止按钮后立即退出循环。但有了这段代码,我只能在执行当前迭代和下一次迭代之后才能出来 这对我的应用非常重要,因为我将使用它来自动化仪器,在按下停止按钮后操作必须立即停止 # -*- coding: utf-8 -*- """ Created on Sun Jun 17 17:01:12 2018 @author: Lachu """ import time from tkinter import * from tkinter import ttk root=Tk() def s

我想在按下停止按钮后立即退出循环。但有了这段代码,我只能在执行当前迭代和下一次迭代之后才能出来

这对我的应用非常重要,因为我将使用它来自动化仪器,在按下停止按钮后操作必须立即停止

# -*- coding: utf-8 -*-
"""
Created on Sun Jun 17 17:01:12 2018

@author: Lachu
"""

import time
from tkinter import *
from tkinter import ttk

root=Tk()

def start():

    global stop_button_state

    for i in range(1,20):
        if (stop_button_state==True):
            break
        else:
            print('Iteration started')
            print('Iteration number: ', i)

            root.update()
            time.sleep(10)
            print('Iteration completed \n')          

def stop_fun():
    global stop_button_state
    stop_button_state=True


start=ttk.Button(root, text="Start", command=start).grid(row=0,column=0,padx=10,pady=10)

p=ttk.Button(root, text="Stop", command=stop_fun).grid(row=1,column=0)

stop_button_state=False

root.mainloop()

如果不使用单独的线程,您可以始终迭代sleep命令,这将使代码更具响应性。
e、 g.这会将单击停止和循环退出之间的等待时间减少到十分之一秒,同时在循环之间保留10秒的间隔

# -*- coding: utf-8 -*-
"""
Created on Sun Jun 17 17:01:12 2018

@author: Lachu
"""

import time
from tkinter import *
from tkinter import ttk

root=Tk()
stop_button_state=False

def start():

    global stop_button_state
    for i in range(1,20):
        if (stop_button_state==True):
           break
        print('Iteration started')
        print('Iteration number: ', i)
        for i in range(100):
            root.update()
            time.sleep(0.1)
            if (stop_button_state==True):
                break
        print('Iteration completed \n')

def stop_fun():
    global stop_button_state
    stop_button_state=True

ttk.Button(root, text="Start", command=start).grid(row=0,column=0,padx=10,pady=10)
ttk.Button(root, text="Stop", command=stop_fun).grid(row=1,column=0)
root.mainloop()

在GUI程序中使用
time.sleep
通常不是一个好主意,因为它会使所有内容都处于睡眠状态,因此GUI无法自我更新或响应事件。此外,当你想中断睡眠时,它会变得混乱

我已将您的代码改编为使用模块中的
计时器。我们可以很容易地立即中断这个
计时器
,而且它不会阻塞GUI

为了实现这一点,我将
循环的计数
移动到一个生成器中

如果您在计数过程中按下开始按钮,它将告诉您已经在计数。当一个计数周期结束时,无论是按停止键,还是按到数字的末尾,您都可以再次按开始键开始新的计数

import tkinter as tk
from tkinter import ttk
from threading import Timer

root = tk.Tk()

delay = 2.0    
my_timer = None

# Count up to `hi`, one number at a time
def counter_gen(hi):
    for i in range(1, hi):
        print('Iteration started')
        print('Iteration number: ', i)
        yield
        print('Iteration completed\n')

# Sleep loop using a threading Timer
# The next `counter` step is performed, then we sleep for `delay`
# When we wake up, we call `sleeper` to repeat the cycle
def sleeper(counter):
    global my_timer
    try:
        next(counter)
    except StopIteration:
        print('Finished\n')
        my_timer = None
        return
    my_timer = Timer(delay, sleeper, (counter,))
    my_timer.start()

def start_fun():
    if my_timer is None:
        counter = counter_gen(10)
        sleeper(counter)
    else:
        print('Already counting')

def stop_fun():
    global my_timer
    if my_timer is not None:
        my_timer.cancel()
        print('Stopped\n')
        my_timer = None

ttk.Button(root, text="Start", command=start_fun).grid(row=0, column=0, padx=10, pady=10)
ttk.Button(root, text="Stop", command=stop_fun).grid(row=1,column=0)

root.mainloop()

您最好使用
根目录。在
之后,使用线程:

正如其他人指出的,在任何情况下,在GUI中使用
time.sleep
都是一个坏主意

您也不应该将按钮命名为与功能相同的名称

这里也不需要调用
root.update

from tkinter import *
from tkinter import ttk


def start_process(n=0, times=10):
    n += 1
    if not stop_button_state and n < times:
        print('Iteration started')
        print(f'Iteration number: {n}')
        print('Iteration completed \n')
        root.after(1000, start_process, n)
    else:
        print('stopping everything')


def stop_fun():
    global stop_button_state
    stop_button_state = True


if __name__ == '__main__':

    root = Tk()

    start = ttk.Button(root, text="Start", command=start_process)
    start.grid(row=0, column=0, padx=10, pady=10)
    p = ttk.Button(root, text="Stop", command=stop_fun)
    p.grid(row=1, column=0)

    stop_button_state = False

    root.mainloop()
从tkinter导入*
从tkinter导入ttk
def启动_过程(n=0,次数=10):
n+=1
如果不停止按钮状态,则n<次:
打印('迭代已开始')
打印(f'迭代编号:{n}')
打印('迭代已完成\n')
root.after(1000,启动\u进程,n)
其他:
打印('停止一切')
def stop_fun():
全局停止按钮状态
停止按钮状态=真
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=Tk()
start=ttk.按钮(root,text=“start”,command=start\u进程)
网格(行=0,列=0,padx=10,pady=10)
p=ttk.按钮(root,text=“Stop”,command=Stop\u fun)
p、 网格(行=1,列=0)
停止按钮状态=错误
root.mainloop()


您必须使用thread
.grid
方法返回
None
,因此使用
start=ttk.Button(root,text=“start”,command=start).grid(row=0,column=0,padx=10,pady=10)
可以将
start
设置为
None
。您不应该尝试使用
start
作为按钮名称和函数名称。这里并没有什么坏处,因为在将函数名传递给按钮构造函数之后,您永远不需要函数名。OTOH,为什么还要麻烦命名按钮,你在任何地方都不使用这个名称?在这段代码中,当
Start
函数运行时,你可以再次按下Start按钮,这样可以同时发生多个迭代。这是有意的吗?研究tkinter
after
方法,它可以让您计划函数在将来运行或按间隔运行。您不应该在GUI程序中使用
sleep
,因为它完全按照它所说的那样:它会使整个程序进入睡眠状态。@BryanOakley我想我应该在
之后使用
,但我认为使用
线程处理
可能会很有趣。)您不应该在GUI线程中调用
sleep
,因为tkinter无法在程序睡眠时处理任何事件。@BryanOakley鉴于OP提出了一个专门使用睡眠的问题,我选择提供一个适合该问题的答案。我不使用tkinter,但我认为
root.update()
会立即将控制权返回主循环。我可能已经在这个网站上发布了100个答案,说明如何在
之后使用
,我在这里可能写不出任何比我的其他答案更好的东西。@BryanOakley那么,发布一个适当的链接到其中一个怎么样?是的,这比我的版本简单一点。但是你用
n+=1
而不是发电机来“作弊”:DSweet。有一点很好,Python3.6中只引入了前缀为“f”的格式化字符串文字。它满足了一半的要求。它不会立即退出循环。它仅在执行当前迭代之后出现。是否可以通过稍微更改代码立即显示出来?是的,您需要为关键字参数
times
提供一个值,以达到此目的。请解释“my_timer=timer(delay,sleeper,(counter,)”在这里是如何工作的。@maheshchaluvadi它创建一个计时器,该计时器睡眠
delay
秒,然后调用
sleeper
函数,将
计数器
生成器作为其参数传递给它。计时器在自己的线程中运行。
.start
调用启动计时器,并立即返回,它不会像
时间那样等待。sleep
会这样做,因此GUI不会冻结。经过您的解释和一段时间的多次更改,我理解了该功能。谢谢。它完全满足了我的要求。@maheshchaluvadi我很高兴你喜欢它。在这种情况下,Reblochon Masque使用
.after
的解决方案稍微简单一些,但了解如何在更复杂的情况下使用Tkinter线程是很有用的。是的,但这种方法的问题是,它不会立即退出循环。它必须完成当前的迭代。只有在那之后才会出来。