python - 我正在创建一个 tkinter gui,我需要让它成为一个线程。但是线程不起作用
问题描述
我正在创建一个中国跳棋 AI。我想做板子,同时检查鼠标位置。我决定使用多线程:
from tkinter import *
from pyautogui import *
from threading import *
def create_board():
#a lot of tkinter stuff
def check_mouse:
if position()[0] > 390 & position()[0] < 455:
print("mouse detected")
board = Thread(target=create_board)
board.start()
但是当我在终端中运行它时,我得到:
2018-11-11 16:50:55.129 python[27074:8053445] WARNING: NSWindow drag regions should only be invalidated on the Main Thread! This will throw an exception in the future. Called from (
0 AppKit 0x00007fff44af22e3 -[NSWindow(NSWindow_Theme) _postWindowNeedsToResetDragMarginsUnlessPostingDisabled] + 386
1 AppKit 0x00007fff44aef68c -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1488
2 AppKit 0x00007fff44aef0b6 -[NSWindow initWithContentRect:styleMask:backing:defer:] + 45
3 libtk8.6.dylib 0x0000000101319426 TkMacOSXMakeRealWindowExist + 742
4 libtk8.6.dylib 0x0000000101318ffc TkWmMapWindow + 60
5 libtk8.6.dylib 0x0000000101261930 Tk_MapWindow + 192
6 libtk8.6.dylib 0x000000010126b541 MapFrame + 65
7 libtcl8.6.dylib 0x000000010119cc71 TclServiceIdle + 161
8 libtcl8.6.dylib 0x000000010117a39d Tcl_DoOneEvent + 397
9 _tkinter.cpython-37m-darwin.so 0x000000010108a88e _tkinter_tkapp_mainloop + 286
10 python 0x000000010098eba6 _PyMethodDef_RawFastCallKeywords + 230
11 python 0x000000010099bae4 _PyMethodDescr_FastCallKeywords + 84
12 python 0x0000000100acf32e call_function + 382
13 python 0x0000000100accd19 _PyEval_EvalFrameDefault + 45065
14 python 0x0000000100ac0a42 _PyEval_EvalCodeWithName + 418
15 python 0x000000010098ea73 _PyFunction_FastCallKeywords + 195
16 python 0x0000000100acf265 call_function + 181
17 python 0x0000000100accdaf _PyEval_EvalFrameDefault + 45215
18 python 0x000000010098e368 function_code_fastcall + 120
19 python 0x0000000100acd1c6 _PyEval_EvalFrameDefault + 46262
20 python 0x000000010098e368 function_code_fastcall + 120
21 python 0x0000000100acf265 call_function + 181
22 python 0x0000000100accd19 _PyEval_EvalFrameDefault + 45065
23 python 0x000000010098e368 function_code_fastcall + 120
24 python 0x0000000100acf265 call_function + 181
25 python 0x0000000100accd19 _PyEval_EvalFrameDefault + 45065
26 python 0x000000010098e368 function_code_fastcall + 120
27 python 0x0000000100991782 method_call + 130
28 python 0x000000010098f1e2 PyObject_Call + 130
29 python 0x0000000100baf5cb t_bootstrap + 123
30 libsystem_pthread.dylib 0x00007fff747a133d _pthread_body + 126
31 libsystem_pthread.dylib 0x00007fff747a42a7 _pthread_start + 70
32 libsystem_pthread.dylib 0x00007fff747a0425 thread_start + 13
)
发生了什么?tkinter 窗口有问题吗?
解决方案
Tkinter(就像我知道的几乎所有 GUI 框架一样)要求对 GUI 状态的修改发生在特定线程上。有关原因的更多讨论,请参阅此问题。这并不意味着您的应用程序中不能有任何其他线程——只是您不能从其他线程修改 GUI 的状态。
如果您必须使用其他线程来防止长时间运行的任务占用用于 GUI 的线程,您可以让工作线程通过 a 与主线程交互,如此处Queue
所述。
我不能警告多线程将使您的应用程序的复杂性增加 10 倍(尤其是如果您不熟悉Queue
s 等概念)。但是,如果您不熟悉Queue
s 及其在并发编程中的典型用法并且仍想开始,那么从生产者/消费者模式开始是一个不错的起点。要更基本地了解“队列”概念在 comp-sci 中的含义,您可以查看描述队列并让您实现自己的简单版本的队列的此页面。
推荐阅读
- javascript - js拆分函数行为怪异
- r - 根据“样条”多项式旋转数据有问题吗?
- python - 如何在应用程序崩溃时将回溯重定向到文件中?
- gcc - 从源代码编译 glibc 在 avx 标头中失败:“无法将 x 类型的值转换为具有不同大小的向量类型 y”
- python - 在 tkinter 上清除和绘制 mathplot 图形
- css - 为什么我的 css 动画不在同一个地方?
- javascript - NETXJS:使用钩子将数据从页面传输到组件
- php - shell_exec 的问题,在某些 bash 命令中不能正常工作
- python - 处理 Pandas 中的异常值
- r - 选择有光泽和情节的点