为什么不能 运行 tkinter mainloop 和 cefpython3 messageloop?
Why can't run both tkinter mainloop and cefpython3 messageloop?
我在 Python3 的一个项目中工作,在该项目中,我同时拥有 tkinter 和带有 cef 浏览器的 tkinter 框架。
这是代码。
from tkinter import messagebox
#import threading
from cefpython3 import cefpython as cef
import platform
import sys
from tkinter import *
import time
def on_closing ():
print('closing')
r.destroy()
cef.Shutdown()
r = Tk()
r.geometry('800x600')
r.protocol('WM_DELETE_WINDOW', on_closing)
f = Frame(r, bg = 'blue', height = 200)
f.pack(side = TOP, fill = 'x')
g=Frame(r,bg = 'white',height = 200)
g.pack(side = TOP, fill = 'x')
b1 = Button (g,text='Exit',command = on_closing)
b1.pack (side = LEFT)
b2 = Button (g,text='Show something',command = lambda:messagebox.showinfo('TITLE', 'Shown something'))
b2.pack (side = RIGHT)
sys.excepthook = cef.ExceptHook
rect = [0, 0, 800, 200]
print('browser: ', rect[2],'x',rect[3])
window_info=cef.WindowInfo(f.winfo_id())
window_info.SetAsChild(f.winfo_id(),rect)
cef.Initialize()
browser = cef.CreateBrowserSync(window_info, url='http://www.google.com')
r.update()
cef.MessageLoop()
##_thread = threading.Thread(target=cef.MessageLoop)
##
##_thread.start()
##
##_thread.join()
r.mainloop()
print('end')
问题是:
- 我离开 cef.MessageLoop() 并且浏览器工作但按钮不工作。
- 我注释掉 cef.MessageLoop() 并且浏览器不工作但是
tkinter window 可以。
我在想也许线程模块会有所帮助,但我试过了(你可以看到注释行)但不起作用(我没有发现异常,但浏览器不起作用)。
我该如何解决这个问题?
Tkinter 在单线程中运行,因此当您在其中编写基本上是无限循环的内容时,您将阻止 Tkinter 工作。屏幕出现的唯一原因是因为你使用了 update()
但这并不能解决这里的问题。
解决方案是使用线程在单独的线程中管理 MessageLoop,同时还将框架传递给函数以允许 Tkinter 和 cef 之间进行一些交互。
注意:我还稍微清理了您的代码以更好地遵循 PEP8 标准。
import tkinter as tk
from tkinter import messagebox
from cefpython3 import cefpython as cef
import threading
import sys
def test_thread(frame):
sys.excepthook = cef.ExceptHook
window_info = cef.WindowInfo(frame.winfo_id())
window_info.SetAsChild(frame.winfo_id(), rect)
cef.Initialize()
browser = cef.CreateBrowserSync(window_info, url='http://www.google.com')
cef.MessageLoop()
def on_closing():
print('closing')
root.destroy()
root = tk.Tk()
root.geometry('800x600')
root.protocol('WM_DELETE_WINDOW', on_closing)
frame = tk.Frame(root, bg='blue', height=200)
frame2 = tk.Frame(root, bg='white', height=200)
frame.pack(side='top', fill='x')
frame2.pack(side='top', fill='x')
tk.Button(frame2, text='Exit', command=on_closing).pack(side='left')
tk.Button(frame2, text='Show something',
command=lambda: messagebox.showinfo('TITLE', 'Shown something')).pack(side='right')
rect = [0, 0, 800, 200]
print('browser: ', rect[2], 'x', rect[3])
thread = threading.Thread(target=test_thread, args=(frame,))
thread.start()
root.mainloop()
结果:
我在 Python3 的一个项目中工作,在该项目中,我同时拥有 tkinter 和带有 cef 浏览器的 tkinter 框架。 这是代码。
from tkinter import messagebox
#import threading
from cefpython3 import cefpython as cef
import platform
import sys
from tkinter import *
import time
def on_closing ():
print('closing')
r.destroy()
cef.Shutdown()
r = Tk()
r.geometry('800x600')
r.protocol('WM_DELETE_WINDOW', on_closing)
f = Frame(r, bg = 'blue', height = 200)
f.pack(side = TOP, fill = 'x')
g=Frame(r,bg = 'white',height = 200)
g.pack(side = TOP, fill = 'x')
b1 = Button (g,text='Exit',command = on_closing)
b1.pack (side = LEFT)
b2 = Button (g,text='Show something',command = lambda:messagebox.showinfo('TITLE', 'Shown something'))
b2.pack (side = RIGHT)
sys.excepthook = cef.ExceptHook
rect = [0, 0, 800, 200]
print('browser: ', rect[2],'x',rect[3])
window_info=cef.WindowInfo(f.winfo_id())
window_info.SetAsChild(f.winfo_id(),rect)
cef.Initialize()
browser = cef.CreateBrowserSync(window_info, url='http://www.google.com')
r.update()
cef.MessageLoop()
##_thread = threading.Thread(target=cef.MessageLoop)
##
##_thread.start()
##
##_thread.join()
r.mainloop()
print('end')
问题是:
- 我离开 cef.MessageLoop() 并且浏览器工作但按钮不工作。
- 我注释掉 cef.MessageLoop() 并且浏览器不工作但是 tkinter window 可以。
我在想也许线程模块会有所帮助,但我试过了(你可以看到注释行)但不起作用(我没有发现异常,但浏览器不起作用)。 我该如何解决这个问题?
Tkinter 在单线程中运行,因此当您在其中编写基本上是无限循环的内容时,您将阻止 Tkinter 工作。屏幕出现的唯一原因是因为你使用了 update()
但这并不能解决这里的问题。
解决方案是使用线程在单独的线程中管理 MessageLoop,同时还将框架传递给函数以允许 Tkinter 和 cef 之间进行一些交互。
注意:我还稍微清理了您的代码以更好地遵循 PEP8 标准。
import tkinter as tk
from tkinter import messagebox
from cefpython3 import cefpython as cef
import threading
import sys
def test_thread(frame):
sys.excepthook = cef.ExceptHook
window_info = cef.WindowInfo(frame.winfo_id())
window_info.SetAsChild(frame.winfo_id(), rect)
cef.Initialize()
browser = cef.CreateBrowserSync(window_info, url='http://www.google.com')
cef.MessageLoop()
def on_closing():
print('closing')
root.destroy()
root = tk.Tk()
root.geometry('800x600')
root.protocol('WM_DELETE_WINDOW', on_closing)
frame = tk.Frame(root, bg='blue', height=200)
frame2 = tk.Frame(root, bg='white', height=200)
frame.pack(side='top', fill='x')
frame2.pack(side='top', fill='x')
tk.Button(frame2, text='Exit', command=on_closing).pack(side='left')
tk.Button(frame2, text='Show something',
command=lambda: messagebox.showinfo('TITLE', 'Shown something')).pack(side='right')
rect = [0, 0, 800, 200]
print('browser: ', rect[2], 'x', rect[3])
thread = threading.Thread(target=test_thread, args=(frame,))
thread.start()
root.mainloop()
结果: