从主程序中停止,重新启动和更改线程中的变量(Python 3.5)

时间:2016-01-02 02:29:59

标签: multithreading oop tkinter python-3.5 tkinter-canvas

我是一个非常新的线程我仍然试图了解如何编写大部分代码。我正在尝试制作一个有效的文本编辑器类型输入框,因此,就像我知道的每个文本编辑器一样,我需要一个光标栏来指示文本输入的位置。因此,我也希望能够闪烁/闪烁光标,我认为这也是线程化的好习惯。

我有一个类光标,它根据我的画布文本的边界框在画布上创建一个矩形,但是当我输入更多字符时,我需要更改它的位置;当用户点击输入框外部时,停止线程并立即隐藏光标矩形;并最后重新启动线程中的线程/循环(再一次,共享一个变量) - 这里的想法是光标闪烁250次然后消失(虽然没有必要,我认为这将是一个很好的学习练习)

假设我已经捕获了触发这些事件所需的事件,那么最好的方法是什么呢?我有一些代码,但我真的认为它不会起作用,而且一直变得更加混乱。我的想法是闪烁方法本身就是线程。将整个班级改为线程会更好吗?请不要被我的代码中的想法所限制,并随时改进它。我不认为停止工作正常,因为每次我将alt + tab从窗口中取出(我已经编程脱离输入框),Python shell和tkinter GUI停止响应。

from tkinter import *
import threading, time

class Cursor:
    def __init__(self, parent, xy):
        self.parent = parent
        #xy is a tuple of 4 integers based on a text object's .bbox()
        coords = [xy[2]] + list(xy[1:])
        self.obj = self.parent.create_rectangle(coords)
        self.parent.itemconfig(self.obj, state='hidden')

    def blink(self):
        blinks = 0
        while not self.stop blinks <= 250:
            self.parent.itemconfig(self.obj, state='normal')
            for i in range(8):
                time.sleep(0.1)
                if self.stop: break
            self.parent.itemconfig(self.obj, state='hidden')
            time.sleep(0.2)
            blinks += 1
        self.parent.itemconfig(self.obj, state='hidden')

    def startThread(self):
        self.stop = False
        self.blinking = threading.Thread(target=self.blink, args=[])
        self.blinking.start()

    def stopThread(self):
        self.stop = True
        self.blinking.join()

    def adjustPos(self, xy):
        #I am not overly sure if this will work because of the thread...
        coords = [xy[2]] + list(xy[1:])
        self.parent.coords(self.obj, coords)

#Below this comment, I have extracted relevant parts of classes to global
#and therefore, it may not be completely syntactically correct nor
#specifically how I initially wrote the code.
def keyPress(e):
    text = canvas.itemcget(textObj, text)
    if focused:
        if '\\x' not in repr(e.char) and len(e.char)>0:
            text += e.char
        elif e.keysym == 'BackSpace':
            text = text[:-1]
    canvas.itemconfig(textObj, text=text)
    cursor.adjustPos(canvas.bbox(textObj))

def toggle(e):
    if cursor.blinking.isAlive(): #<< I'm not sure if that is right?
        cursor.stopThread()
    else:
        cursor.startThread()

if __name__=="__main__":
    root = Tk()
    canvas = Canvas(root, width=600, height=400, borderwidth=0, hightlightthickness=0)
    canvas.pack()
    textObj = canvas.create_text(50, 50, text='', anchor=NW)
    root.bind('<Key>', keyPress)
    cursor = Cursor(canvas, canvas.bbox(textObj))
    #Using left-click event to toggle thread start and stop
    root.bind('<ButtonPress-1', toggle)
    #Using right-click event to somehow restart thread or set blinks=0
    #root.bind('<ButtonPress-3', cursor.dosomething_butimnotsurewhat)
    root.mainloop()

如果有更好的方法来做上面写的事情,请告诉我。 感谢。

0 个答案:

没有答案