【问题标题】:Why can't run both tkinter mainloop and cefpython3 messageloop?为什么不能同时运行 tkinter mainloop 和 cefpython3 messageloop?
【发布时间】:2019-09-17 12:46:23
【问题描述】:

我正在 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')

问题是:

  1. 我离开 cef.MessageLoop() 并且浏览器工作但按钮不工作。
  2. 我注释掉 cef.MessageLoop() 并且浏览器不工作但是 tkinter 窗口可以。

我在想也许线程模块 wuold 有帮助,但我尝试了(你可以看到注释行)并且不起作用(我没有例外,但浏览器不起作用)。 我该如何解决这个问题?

【问题讨论】:

  • 嗯,它是一个循环内的循环。你期望会发生什么?我对cefpython3 了解不多,但我怀疑MessageLoop() 永远不会结束,直到有人强制循环结束,如果是这种情况(就像 tkinter 的 mainloop 一样),那么你永远不会让你的 tkinter与MessageLoop 一起工作。您将需要使用线程并在其自己的线程中运行MessageLoop
  • 也许使用MessageLoopWorkroot.updateroot.idle_update 你可以尝试创建自己的循环而不是MessageLooproot.mainloop()
  • 您可以使用g.destroy,而不是在关闭时使用。您还可以将键绑定到命令。因此,不要使用 Lambda 为您的消息框创建一个函数,而是将该函数与 b2.bind('<Button-1>', message) 绑定

标签: python-3.x tkinter cefpython


【解决方案1】:

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()

结果:

【讨论】:

    猜你喜欢
    • 2020-11-17
    • 2014-06-17
    • 2017-03-27
    • 2021-10-08
    • 1970-01-01
    • 2021-11-09
    • 2019-11-14
    • 2020-04-07
    • 2021-07-10
    相关资源
    最近更新 更多