IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> tkinter使用WebView2网页组件(续篇) -> 正文阅读

[移动开发]tkinter使用WebView2网页组件(续篇)

引言

在“很久”之前的一篇文章(tkinter使用WebView2网页组件_Smart-Space的博客-CSDN博客_tkinter webview)中,我介绍了如何在tkinter中通过pywebview创建一个与tkinter相契合的WebView2控件。但是,那一种控件,有如下缺点:

  1. 使用pywebview提供的窗口进行嵌入,会出现延时、嵌入失败等问题
  2. 因为pywebview窗口使用高分辨率,导致tkinter窗口(自动)必须高gdi
  3. 点击控件后,tkinter窗口将失去焦点
  4. 需要额外的进程支持pywebview窗口

这些问题都是有读者反馈的,我也“深受其害”😑。

这次准备把它重改。因为思路基本变了,所以重新写一篇续篇。

提前声明

最新的tkwebview2与tkinterie一样,需要在STA线程模式下创建。因为我们不再使用窗口,而网页渲染本身涉及到多线程,因此需要使用STA线程模式。


重写tkwebview2

前提概括

本次,我们不再直接使用pywebview提供的窗口,而是直接使用其提供的EdgeChrome抽象类,创建基于WinFroms的WebView2组件。我已经写过了一些在tkinter中嵌入WinForms控件的文章,包括tkinterie使用的WebBrowser。

from tkinter import Frame,Tk
import ctypes
from uuid import uuid4
import clr
from webview.window import Window
from webview.platforms.edgechromium import EdgeChrome
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Threading')
from System.Windows.Forms import Control
from System.Threading import Thread,ApartmentState,ThreadStart

user32=ctypes.windll.user32

创建类

这个基本没变:

class WebView2(Frame):
    '''tkinter的WebView2绑定,基于pywebview & pythonnet'''

    def __init__(self,parent,width:int,height:int,url:str='',**kw):    
        Frame.__init__(self,parent,width=width,height=height,**kw)
        #...

操作WinFroms

首先我们需要创建一个WinFroms的Control类,一是为了承载WebView2,二是提供一个可用的控件句柄。

其次,我们需要通过pywebview提供的WindowEdgeChrome类创建一个WebView2控件,并加入到Control中,再获取EdgeChrome所对应的WebView2控件。

这里的线程uid名称借用了pywebview的思路:使用一个列表windows,通过它判断Window类所需要的uid名称。

        control=Control()
        uid = 'master' if len(windows) == 0 else 'child_' + uuid4().hex[:8]
        window=Window(uid,str(id(self)), url=None, html=None, js_api=None, width=width, height=height, x=None, y=None,
                      resizable=True, fullscreen=False, min_size=(200, 100), hidden=False,
                      frameless=False, easy_drag=True,
                      minimized=False, on_top=False, confirm_close=False, background_color='#FFFFFF',
                      transparent=False, text_select=False, localization=None)
        self.web_view=EdgeChrome(control,window)
        self.control=control
        self.web=self.web_view.web_view#EdgeChrome.web_view
        windows.append(window)

接下来的操作就和以前一样了,待会直接给完整代码。

虽然是创建逻辑完全不一样,但是需要改的量很少。不过我倒是研究了pywebview的platforms.edgechromium很久,最后摸索出新的tkwebview2。同时,也希望喜欢玩tkinter的朋友也能静心研究。

完整类代码

class WebView2(Frame):
    '''tkinter的WebView2绑定,基于pywebview & pythonnet'''

    def __init__(self,parent,width:int,height:int,url:str='',**kw):
        Frame.__init__(self,parent,width=width,height=height,**kw)
        control=Control()
        uid = 'master' if len(windows) == 0 else 'child_' + uuid4().hex[:8]
        window=Window(uid,str(id(self)), url=None, html=None, js_api=None, width=width, height=height, x=None, y=None,
                      resizable=True, fullscreen=False, min_size=(200, 100), hidden=False,
                      frameless=False, easy_drag=True,
                      minimized=False, on_top=False, confirm_close=False, background_color='#FFFFFF',
                      transparent=False, text_select=False, localization=None)
        self.web_view=EdgeChrome(control,window)
        self.control=control
        self.web=self.web_view.web_view
        windows.append(window)
        self.width=width
        self.height=height
        self.parent=parent
        self.chwnd=int(str(self.control.Handle))
        user32.SetParent(self.chwnd,self.winfo_id())
        user32.MoveWindow(self.chwnd,0,0,width,height,True)
        self.__go_bind()

    def __go_bind(self):
        self.bind('<Destroy>',lambda event:self.web.Dispose())
        self.bind('<Configure>',self.__resize_webview)
    def __resize_webview(self,event):
        user32.MoveWindow(self.chwnd,0,0,self.winfo_width(),self.winfo_height(),True)

    def get_url(self):
        #返回当前url,若果没有则为空
        return self.web_view.get_current_url()

    def evaluate_js(self,script):
        #执行javascript代码,并返回最终结果
        return self.web_view.evaluate_js(script)

    def load_css(self,css):
        #加载css
        self.web_view.load_css(css)

    def load_html(self,content,base_uri=None):
        #加载HTML代码
        #content=HTML内容
        #base_uri=基本URL,默认为启动程序的目录
        self.web_view.load_html(content,base_uri)

    def load_url(self,url):
        #加载全新的URL
        self.web_view.load_url(url)

    def none(self):
        pass

关于WebView2的更多WinFroms操作,见微软提供的说明文档。


效果

测试代码

def main():
    if not have_runtime():#没有webview2 runtime
        install_runtime()
    root=Tk()
    root.title('pywebview for tkinter test')
    root.geometry('1200x600+5+5')

    frame=WebView2(root,500,500)
    frame.pack(side='left')
    frame.load_html('<h1>hi hi</h1>')

    frame2=WebView2(root,500,500)
    frame2.pack(side='left',padx=20,fill='both',expand=True)
    frame2.load_url('https://smart-space.com.cn/')

    root.mainloop()

if __name__ == "__main__":
    t = Thread(ThreadStart(main))
    t.ApartmentState = ApartmentState.STA
    t.Start()
    t.Join()

最终效果

在这里插入图片描述

  • 减少运行消耗
  • 点击组件后tkinter仍然有焦点(可以对比之前的tkwebview2效果中tkinter窗口标题栏)
  • 可直接使用WebView2
  • 不自动使用高GDI

结语

静下心,放松~~。

一个新的tkwebview2不就出来了吗?(时间抚平了故事的曲折)

?tkinter创新?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-06-14 22:45:08  更:2022-06-14 22:45:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:55:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码