tkinter-TinUI-xml实战(8)轻型浏览器

本文档介绍了使用TinUI和tkwebview2构建一个轻型浏览器的过程,包括XML布局设计、核心代码实现、程序启动和页面加载。尽管存在一些问题,如输入框焦点问题和新窗口功能,但基本功能已经实现,适合作为示例项目参考。
摘要由CSDN通过智能技术生成

引言

在此之前,我将pywebview中的WebView2(ChromeEdge)分离出来,用来给tkinter做网页控件,诞生了tkwebview2。此外,TinUI也拥有了标签栏视图(选项卡)notebook元素控件。所以突发奇想,用TinUI给tkwebview2写一个小小的、十分简易、又漏洞百出的轻型浏览器。

有人问我tkwebview2是不是只能在win使用。其实是但又不是,只要在其它系统能够运行类似 .Net 的环境,并且能够运行pywebview的chormeedge模式,再加上webview2 runtime,然后该系统能够允许窗口嵌套(不能用user32,需要自己找找有什么办法,然后在源码更改),就可以使用tkwebview2了。

途中遇到一些莫名其妙的问题,我还没办法解决,不过可以凑合着用了。


声明

本项目属于作者原创。借鉴了GitHub/TinUI上的tuxml.py,翻版必究,但可以自行添加功能代码。

本项目使用的TinUI为我开源并维护在GitHub上的主文件——TinUI.py。当然,使用PYPI中下载安装的tinui也可以。


文件结构

在这里插入图片描述

  • main.xml - 整体窗口布局

  • page.xml - 每个页面的布局

  • tinui.py - TinUI核心支持

  • tinuiweb.py - 逻辑代码


核心代码

窗口布局

main.xml

<!--TinUIXml编辑器-->
<tinui>
    <line x='5'>
        <notebook width='1270' height='710'>ntb</notebook>
    </line>
</tinui>

其实很简单,就一个标签栏视图,也叫做选项卡(notebook)。

页面

page.xml

<tinui>
    <line>
        <button text='<'>backbutton</button>
        <button text='>'>forebutton</button>
        <button text=''>refbutton</button>
        <entry width='1000'>urlenter</entry>
        <button text='🏠'>homebutton</button>
        <button text=''>colbutton</button>
    </line>
    <line>
    </line>
</tinui>

这个界面也甚为简单,到后面发现其实输入框很废。

程序启动

def main():
    global root,u,ntb,xml,pagexml
    root=Tk()
    root.geometry('1280x720+5+5')
    root.title('TinUI 轻型浏览器')
    root.resizable(0,0)

    u=BasicTinUI(root)
    u.pack(fill='both',expand=True)
    x=TinUIXml(u)

    #in

    #during
    with open('main.xml',mode='r',encoding='utf-8') as f:
        xml=f.read()
    x.loadxml(xml)
    with open('page.xml',mode='r',encoding='utf-8') as f:
        pagexml=f.read()
    #out
    ntb = x.tags["ntb"][-2]

    newpage(url='https://www.baidu.com/')

    ntb.cannew(True,newpage)

    root.mainloop()


def go():
    try:
        main()
    except Exception as err:
        print(err)


t = Thread(ThreadStart(go))
t.ApartmentState = ApartmentState.STA
t.Start()
t.Join()

页面加载

这个函数为newpage,但是考虑到点击新增标签页的功能,就把这个函数写的通用一点。

def newpage(title='新标签页',url='https://bing.com/'):
    npage=ntb.addpage('新标签页')
    ntb.showpage(npage)
    nu,nx,_=ntb.getuis(npage)
    nx.loadxml(pagexml)
    #---
    webview=WebView2(nu,width=1260,height=620)
    nu.create_window((5,40),window=webview,anchor='nw')
    #---
    backbutton = nx.tags["backbutton"][-2]
    backbutton[0](lambda event:backone(webview))
    forebutton = nx.tags["forebutton"][-2]
    forebutton[0](lambda event:foreone(webview))
    refbutton = nx.tags["refbutton"][-2]
    refbutton[0](lambda event:refreshone(webview))
    urlenter,uid = nx.tags["urlenter"]
    urlenter.bind('<Return>',lambda event:newurl(webview,urlenter))
    homebutton = nx.tags["homebutton"][-2]
    homebutton[0](lambda event:homeone(webview))
    colbutton = nx.tags["colbutton"][-2]
    colbutton[0](lambda event:collect_it(webview))
    #---
    def loadit(sender,arg):
        core=sender.CoreWebView2
        core.NewWindowRequested+=newwindow
        core.DocumentTitleChanged+=lambda s,a:titlechanged(s,a,urlenter,npage)
        core.AreDevToolsEnabled=True
    webview.web.CoreWebView2InitializationCompleted+=loadit
    webview.web.ContentLoading+=lambda sender,args:newtitle(sender,args,urlenter,npage)
    if url!='':
        webview.load_url(url)
        urlenter.insert(0,url)
    nu.focus(uid)
    return webview

其它代码就很简单了。

源文件代码

from tinui import *
from tkinter import Tk
from time import sleep
import threading
import clr
clr.AddReference('System.Threading')
from System.Threading import Thread,ApartmentState,ThreadStart,ParameterizedThreadStart

from tkwebview2.tkwebview2 import WebView2


def backone(wb):
    wb.web.GoBack()
def foreone(wb):
    wb.web.GoForward()
def refreshone(wb):
    wb.web.Reload()
def newurl(wb,entry):
    url=entry.get()
    if url!='':
        wb.load_url(url)
        wb.web.Enabled=True
def newtitle(wb,args,entry,flag):#更新标题
    try:
        url=wb.Source.ToString()
        entry.delete(0,'end')
        entry.insert(0,url)
    except Exception as err:
        print(err)    
def newwindow(sender,args):
    try:
        args.Handle=True
        args.NewWindow=sender
    except Exception as err:
        print(err)
def titlechanged(sender,args,entry,flag):
    title=sender.DocumentTitle
    threading.Thread(target=ntb.newtitle,args=(flag,title)).start()
def homeone(wb):
    wb.load_url('https://blog.csdn.net/tinga_kilin')
def collect_it(wb):#收藏,暂不用
    ...

def newpage(title='新标签页',url='https://bing.com/'):
    npage=ntb.addpage('新标签页')
    ntb.showpage(npage)
    nu,nx,_=ntb.getuis(npage)
    nx.loadxml(pagexml)
    #---
    webview=WebView2(nu,width=1260,height=620)
    nu.create_window((5,40),window=webview,anchor='nw')
    #---
    backbutton = nx.tags["backbutton"][-2]
    backbutton[0](lambda event:backone(webview))
    forebutton = nx.tags["forebutton"][-2]
    forebutton[0](lambda event:foreone(webview))
    refbutton = nx.tags["refbutton"][-2]
    refbutton[0](lambda event:refreshone(webview))
    urlenter,uid = nx.tags["urlenter"]
    urlenter.bind('<Return>',lambda event:newurl(webview,urlenter))
    homebutton = nx.tags["homebutton"][-2]
    homebutton[0](lambda event:homeone(webview))
    colbutton = nx.tags["colbutton"][-2]
    colbutton[0](lambda event:collect_it(webview))
    #---
    def loadit(sender,arg):
        core=sender.CoreWebView2
        core.NewWindowRequested+=newwindow
        core.DocumentTitleChanged+=lambda s,a:titlechanged(s,a,urlenter,npage)
        core.AreDevToolsEnabled=True
    webview.web.CoreWebView2InitializationCompleted+=loadit
    webview.web.ContentLoading+=lambda sender,args:newtitle(sender,args,urlenter,npage)
    if url!='':
        webview.load_url(url)
        urlenter.insert(0,url)
    nu.focus(uid)
    return webview


def main():
    global root,u,ntb,xml,pagexml
    root=Tk()
    root.geometry('1280x720+5+5')
    root.title('TinUI 轻型浏览器')
    root.resizable(0,0)

    u=BasicTinUI(root)
    u.pack(fill='both',expand=True)
    x=TinUIXml(u)

    #in

    #during
    with open('main.xml',mode='r',encoding='utf-8') as f:
        xml=f.read()
    x.loadxml(xml)
    with open('page.xml',mode='r',encoding='utf-8') as f:
        pagexml=f.read()
    #out
    ntb = x.tags["ntb"][-2]

    newpage(url='https://www.baidu.com/')

    ntb.cannew(True,newpage)

    root.mainloop()


def go():
    try:
        main()
    except Exception as err:
        print(err)


t = Thread(ThreadStart(go))
t.ApartmentState = ApartmentState.STA
t.Start()
t.Join()

最终效果

在这里插入图片描述

现在的问题

现在的问题主要有以下几个方面:

  1. 输入框在webview2获得焦点后就失效了,需要本窗口失去焦点,再次点击输入框才行

  2. 目前还没有想到直接打开新窗口的好方法,只能在本窗口打开

  3. 将新窗口的内容在本页面打开后,历史记录清零

  4. 菜单调不出来


结语

虽然真的是有点漏洞百出,但是至少是可以正常使用的。网址输入可以直接使用搜索界面,浏览器历史的话,应该不是很重要。。。总之,凑合着用用,当个示例还是够的。

虽然tkwebview2说是维护中,但是我几乎没怎么碰tkwebview2,也是希望需要的人对其完善。

🔆tkinter创新🔆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值