python:pyqt5 + cef 模仿 mdict 界面

PyQt5 安装参见:python:PyQt5 简单示例

cefpython 入门 参考: Python GUI: cefpython3的简单分析和应用

pip install cefpython3
cefpython3-66.1-py2.py3-none-win_amd64.whl (69.0 MB)
Successfully installed cefpython3-66.1

cd \Python37\Lib\site-packages\cefpython3\examples
copy qt.py  qt_cef.py
用的图片在 \Python37\Lib\site-packages\cefpython3\examples\resources\
编写 qt_cef.py  如下

# -*- coding: utf-8 -*-
# Example of embedding CEF browser using PyQt5 libraries.
# This example has two widgets: a navigation bar and a browser.
#
# Tested configurations:
# - PyQt 5.8.2 (qt 5.8.0) on Windows/Linux/Mac
# - CEF Python v55.4+
#
import ctypes
import os
import platform
import sys
from cefpython3 import cefpython as cef
import win32com.client  # TTS
sapi = win32com.client.Dispatch("SAPI.SpVoice")# GLOBALS
PYQT4 = False
PYSIDE = False
PYSIDE2 = False
PYQT5 = True
Baseurl = "http://localhost:8888/"# 不检查 PyUnresolvedReferences
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *if len(sys.argv) ==1:print("usage: python qt_cef.py pyqt5")sys.exit(1)# Fix for PyCharm hints warnings when using static methods
WindowUtils = cef.WindowUtils()# Platforms
WINDOWS = (platform.system() == "Windows")
LINUX = (platform.system() == "Linux")
MAC = (platform.system() == "Darwin")# Configuration
WIDTH =  900
HEIGHT = 600# OS differences
CefWidgetParent = QWidgetdef main():check_versions()# To shutdown all CEF processes on errorsys.excepthook = cef.ExceptHooksettings = {"debug": True,"log_severity": cef.LOGSEVERITY_INFO,"log_file": "debug.log" }#cef.DpiAware.EnableHighDpiSupport()cef.Initialize({})app = CefApplication(sys.argv)main_window = MainWindow()main_window.show()main_window.activateWindow()main_window.raise_()app.exec_()if not cef.GetAppSetting("external_message_pump"):app.stopTimer()del main_window  # Just to be safe, similarly to "del app"del app  # Must destroy app object before calling Shutdowncef.Shutdown()def check_versions():print("[qt_cef.py] CEF Python {ver}".format(ver=cef.__version__))print("[qt_cef.py] Python {ver} {arch}".format(ver=platform.python_version(), arch=platform.architecture()[0]))if PYQT4 or PYQT5:print("[qt_cef.py] PyQt {v1} (qt {v2})".format(v1=PYQT_VERSION_STR, v2=qVersion()))# CEF Python version requirementassert cef.__version__ >= "55.4", "CEF Python v55.4+ required to run this"class MainWindow(QMainWindow):def __init__(self):# 不检查 PyArgumentListsuper(MainWindow, self).__init__(None)# Avoids crash when shutting down CEF (issue #360)if PYSIDE:self.setAttribute(Qt.WA_DeleteOnClose, True)self.cef_widget = Noneself.navigation_bar = Noneif PYQT4:self.setWindowTitle("PyQt4 example")elif PYQT5:self.setWindowTitle("PyQt5 + cef")elif PYSIDE:self.setWindowTitle("PySide example")elif PYSIDE2:self.setWindowTitle("PySide2 example")self.setFocusPolicy(Qt.StrongFocus)self.setupLayout()def setupLayout(self):self.resize(WIDTH, HEIGHT)self.cef_widget = CefWidget(self)self.navigation_bar = NavigationBar(self.cef_widget)layout = QGridLayout()# 不检查 PyArgumentListlayout.addWidget(self.navigation_bar, 0, 0)# 不检查 PyArgumentListlayout.addWidget(self.cef_widget, 1, 0)layout.setContentsMargins(0, 0, 0, 0)layout.setSpacing(0)layout.setRowStretch(0, 0)layout.setRowStretch(1, 1)# 不检查 PyArgumentListframe = QFrame()frame.setLayout(layout)self.setCentralWidget(frame)if (PYSIDE2 or PYQT5) and WINDOWS:# On Windows with PyQt5 main window must be shown first# before CEF browser is embedded, otherwise window is# not resized and application hangs during resize.self.show()# Browser can be embedded only after layout was set upself.cef_widget.embedBrowser()if (PYSIDE2 or PYQT5) and LINUX:# On Linux with PyQt5 the QX11EmbedContainer widget is# no more available. An equivalent in Qt5 is to create# a hidden window, embed CEF browser in it and then# create a container for that hidden window and replace# cef widget in the layout with the container.# 不检查 PyUnresolvedReferences, PyArgumentListself.container = QWidget.createWindowContainer(self.cef_widget.hidden_window, parent=self)# 不检查 PyArgumentListlayout.addWidget(self.container, 1, 0)def closeEvent(self, event):# Close browser (force=True) and free CEF referenceif self.cef_widget.browser:self.cef_widget.browser.CloseBrowser(True)self.clear_browser_references()def clear_browser_references(self):# Clear browser references that you keep anywhere in your# code. All references must be cleared for CEF to shutdown cleanly.self.cef_widget.browser = Noneclass CefWidget(CefWidgetParent):def __init__(self, parent=None):# 不检查 PyArgumentListsuper(CefWidget, self).__init__(parent)self.parent = parentself.browser = Noneself.hidden_window = None  # Required for PyQt5 on Linuxself.show()def focusInEvent(self, event):# This event seems to never get called on Linux, as CEF is# stealing all focus due to Issue #284.if cef.GetAppSetting("debug"):print("[qt_cef.py] CefWidget.focusInEvent")if self.browser:if WINDOWS:WindowUtils.OnSetFocus(self.getHandle(), 0, 0, 0)self.browser.SetFocus(True)def focusOutEvent(self, event):# This event seems to never get called on Linux, as CEF is# stealing all focus due to Issue #284.if cef.GetAppSetting("debug"):print("[qt_cef.py] CefWidget.focusOutEvent")if self.browser:self.browser.SetFocus(False)def embedBrowser(self):if (PYSIDE2 or PYQT5) and LINUX:# 不检查 PyUnresolvedReferencesself.hidden_window = QWindow()window_info = cef.WindowInfo()rect = [0, 0, self.width(), self.height()]window_info.SetAsChild(self.getHandle(), rect)self.browser = cef.CreateBrowserSync(window_info, url=Baseurl)self.browser.SetClientHandler(LoadHandler(self.parent.navigation_bar))self.browser.SetClientHandler(FocusHandler(self))# Javascript 绑定 py functionjsb = cef.JavascriptBindings()jsb.SetFunction("py_speak", self.py_speak)self.browser.SetJavascriptBindings(jsb)def py_speak(self, txt):""" Javascript 调用py TTS发音 """if txt.strip() !='':sapi.Speak(txt)def getHandle(self):if self.hidden_window:# PyQt5 on Linuxreturn int(self.hidden_window.winId())try:# PyQt4 and PyQt5return int(self.winId())except:# PySide:# | QWidget.winId() returns # | Converting it to int using ctypes.if sys.version_info[0] == 2:# Python 2ctypes.pythonapi.PyCObject_AsVoidPtr.restype = (ctypes.c_void_p)ctypes.pythonapi.PyCObject_AsVoidPtr.argtypes = ([ctypes.py_object])return ctypes.pythonapi.PyCObject_AsVoidPtr(self.winId())else:# Python 3ctypes.pythonapi.PyCapsule_GetPointer.restype = (ctypes.c_void_p)ctypes.pythonapi.PyCapsule_GetPointer.argtypes = ([ctypes.py_object])return ctypes.pythonapi.PyCapsule_GetPointer(self.winId(), None)def moveEvent(self, _):self.x = 0self.y = 0if self.browser:if WINDOWS:WindowUtils.OnSize(self.getHandle(), 0, 0, 0)elif LINUX:self.browser.SetBounds(self.x, self.y,self.width(), self.height())self.browser.NotifyMoveOrResizeStarted()def resizeEvent(self, event):size = event.size()if self.browser:if WINDOWS:WindowUtils.OnSize(self.getHandle(), 0, 0, 0)elif LINUX:self.browser.SetBounds(self.x, self.y,size.width(), size.height())self.browser.NotifyMoveOrResizeStarted()#实时刷新界面self.browser.viewport().update()class CefApplication(QApplication):def __init__(self, args):super(CefApplication, self).__init__(args)if not cef.GetAppSetting("external_message_pump"):self.timer = self.createTimer()self.setupIcon()def createTimer(self):timer = QTimer()# 不检查 PyUnresolvedReferencestimer.timeout.connect(self.onTimer)timer.start(10)return timerdef onTimer(self):cef.MessageLoopWork()def stopTimer(self):# Stop the timer after Qt's message loop has endedself.timer.stop()def setupIcon(self):icon_file = os.path.join(os.path.abspath(os.path.dirname(__file__)),"resources", "{0}.png".format(sys.argv[1]))if os.path.exists(icon_file):self.setWindowIcon(QIcon(icon_file))class LoadHandler(object):def __init__(self, navigation_bar):self.initial_app_loading = Trueself.navigation_bar = navigation_bardef OnLoadingStateChange(self, **_):self.navigation_bar.updateState()def OnLoadStart(self, browser, **_):#self.navigation_bar.url.setText(browser.GetUrl())if self.initial_app_loading:self.navigation_bar.cef_widget.setFocus()# Temporary fix no. 2 for focus issue on Linux (Issue #284)if LINUX:print("[qt_cef.py] LoadHandler.OnLoadStart:"" keyboard focus fix no. 2 (Issue #284)")browser.SetFocus(True)self.initial_app_loading = Falseclass FocusHandler(object):def __init__(self, cef_widget):self.cef_widget = cef_widgetdef OnTakeFocus(self, **_):if cef.GetAppSetting("debug"):print("[qt_cef.py] FocusHandler.OnTakeFocus")def OnSetFocus(self, **_):if cef.GetAppSetting("debug"):print("[qt_cef.py] FocusHandler.OnSetFocus")def OnGotFocus(self, browser, **_):if cef.GetAppSetting("debug"):print("[qt_cef.py] FocusHandler.OnGotFocus")self.cef_widget.setFocus()# Temporary fix no. 1 for focus issues on Linux (Issue #284)if LINUX:browser.SetFocus(True)class NavigationBar(QFrame):def createButton(self, name):resources = os.path.join(os.path.abspath(os.path.dirname(__file__)),"resources")pixmap = QPixmap(os.path.join(resources, "{0}.png".format(name)))icon = QIcon(pixmap)button = QPushButton()button.setIcon(icon)button.setIconSize(pixmap.rect().size())return buttondef __init__(self, cef_widget):# 不检查 PyArgumentListsuper(NavigationBar, self).__init__()self.cef_widget = cef_widget# Init layoutlayout = QGridLayout()layout.setContentsMargins(0, 0, 0, 0)layout.setSpacing(0)# Back buttonself.back = self.createButton("back")# 不检查 PyUnresolvedReferencesself.back.clicked.connect(self.onBack)# 不检查 PyArgumentListlayout.addWidget(self.back, 0, 0)# Forward buttonself.forward = self.createButton("forward")# 不检查 PyUnresolvedReferencesself.forward.clicked.connect(self.onForward)# 不检查 PyArgumentListlayout.addWidget(self.forward, 0, 1)# Reload buttonself.reload = self.createButton("reload")# 不检查 PyUnresolvedReferencesself.reload.clicked.connect(self.onReload)# 不检查 PyArgumentListlayout.addWidget(self.reload, 0, 2)# Url inputself.edit = QLineEdit("")self.edit.returnPressed.connect(self.onGoUrl)layout.addWidget(self.edit, 0, 3)self.button4 = QPushButton("go")self.button4.clicked.connect(self.onGo)layout.addWidget(self.button4, 0, 4)self.button5 = QPushButton("前缀匹配")self.button5.clicked.connect(self.onPrefix)layout.addWidget(self.button5, 0, 5)self.button6 = QPushButton("TTS发音")self.button6.clicked.connect(self.onTTS)layout.addWidget(self.button6, 0, 6)# Layoutself.setLayout(layout)self.updateState()def onGo(self):""" 英译汉 """url = self.edit.text()if url.strip() =='':returnelif url.startswith("http://"):passelse:url = Baseurl + "trans?txt=" + url.strip()        if self.cef_widget.browser:self.cef_widget.browser.LoadUrl(url)def onPrefix(self):""" 前缀匹配 """url = self.edit.text()if url.strip() =='':returnelif url.startswith("https://"):if self.cef_widget.browser:self.cef_widget.browser.LoadUrl(url)else:url = Baseurl + "prefix?txt=" + url.strip();if self.cef_widget.browser:self.cef_widget.browser.LoadUrl(url)                def onTTS(self):""" 屏幕取词,TTS发音 """txt = self.edit.text()if txt.startswith("http://"):returnif txt.strip() !='': sapi.Speak(txt)else:js = "var select=window.getSelection(); var txt=select.toString(); py_speak(txt);"self.cef_widget.browser.ExecuteJavascript(js);               def onBack(self):if self.cef_widget.browser:self.cef_widget.browser.GoBack()def onForward(self):if self.cef_widget.browser:self.cef_widget.browser.GoForward()def onReload(self):if self.cef_widget.browser:self.cef_widget.browser.Reload()def onGoUrl(self):url = self.edit.text()if self.cef_widget.browser:self.cef_widget.browser.LoadUrl(url)def updateState(self):browser = self.cef_widget.browserif not browser:self.back.setEnabled(False)self.forward.setEnabled(False)self.reload.setEnabled(False)self.edit.setEnabled(False)returnself.back.setEnabled(browser.CanGoBack())self.forward.setEnabled(browser.CanGoForward())self.reload.setEnabled(True)self.edit.setEnabled(True)#self.edit.setText(browser.GetUrl())if __name__ == '__main__':main()

运行 python qt_cef.py pyqt5 

编写 index3.html 如下



   查询英汉词典 


web 服务程序参见: python:mdict + bottle = web 查询英汉词典


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部