們在開發(fā)的過程中難免會(huì)遇到需要?jiǎng)?chuàng)建一個(gè)子窗口(子進(jìn)程),但是在這個(gè)子進(jìn)程中所有值都是初始化的,而我們肯定是需要一些值才能進(jìn)行下一步操作,比如:token; 那么我們怎么去傳遞值呢?
我先給伙伴們說一些,基本原理(下面很多東西會(huì)建立在vue的基礎(chǔ)上生命周期,如果是其他框架就自行修改就行),然后再給大家根據(jù)代碼一步一步操作。
大家看到這兒可能覺得很麻煩,但是如果我們在創(chuàng)建新窗口的時(shí)候就傳遞值的話,可能子進(jìn)程的渲染進(jìn)程拿不到值;主要原因有:
所以我們當(dāng)時(shí)搞了這種方法,目前運(yùn)行半年以上基本上都沒得問題;如果你有更好的方法也可以告訴我們,一起聊聊;哈哈哈
在主進(jìn)程中配置窗口信息,具體內(nèi)容可以看文檔[1],以下是我的配置;配置中的參數(shù)都是可以根據(jù)自己的需求變化的;
注意: 在開發(fā)環(huán)境時(shí),root_path的地址必須是你的ip地址,而不是localhost一類的
let modal;
// 接收彈出模態(tài)框
ipcMain.on('open-modal',(event,path,title='提示')=>{
console.log(path);
let root_path;
if (process.env.WEBPACK_DEV_SERVER_URL) {
root_path="http://192.168.110.95:8080/";
// root_path="http://192.168.124.4:8080/";
} else {
// root_path="app://./index.html/";
root_path=`file://${__dirname}/index.html/`;
};
const minWidth=1176;
const minHeight=600;
const width=1200;
const height=700;
modal=new BrowserWindow({
parent: BrowserWindow.getFocusedWindow() || undefined,
modal: true,
// frame: false,
width: width,
height: height,
minWidth: minWidth,
minHeight: minHeight,
// autoHideMenuBar: true, // 是否顯示菜單欄
// backgroundColor:'#000', // 背景
hasShadow: true, // 陰影
resizable: true, // 窗口是否可以放大
webPreferences: {
webviewTag: true,
contextIsolation: false,
nodeIntegration: true,
enableRemoteModule: true,
webSecurity: false,
},
});
modal.loadURL(root_path + "#/" + path);
});
{
path:'/modal',
name:'modal',
component:()=> import('@/views/db-file/text.vue'),
},
在渲染進(jìn)程中發(fā)送命令,參數(shù)需要和路由path一致即可打開窗口
ipcRenderer.send('open-modal','modal')
Snipaste_2023-02-14_11-45-19.png
當(dāng)我們做到這的時(shí)候,我們的新窗口基本上就算是可以打開了;打開了以后呢!我們需要向他傳遞一些值,這個(gè)時(shí)候?yàn)榱朔奖銋^(qū)分;如下:
主程序
渲染進(jìn)程:A渲染進(jìn)程 主進(jìn)程:A主進(jìn)程
子程序(模態(tài)框) 渲染進(jìn)程:B渲染進(jìn)程 主進(jìn)程:B主進(jìn)程
在B渲染進(jìn)程渲染完成以后(vue中的話是nextTick),發(fā)送命令通知B主進(jìn)程
ipcRenderer.send('modal-accomplish')
當(dāng)在B主進(jìn)程中接收到消息以后,發(fā)送給A渲染進(jìn)程;
// 通知模態(tài)框渲染完成
ipcMain.on('modal-accomplish',(event,msg)=>{
// 發(fā)送給渲染進(jìn)程
win.webContents.send("modal-accomplish-state");
})
在A渲染進(jìn)程中接收
onMounted(()=>{
ipcRenderer.on('modal-accomplish-state',()=>{
console.log('偉大時(shí)代');
})
})
A渲染進(jìn)程接收到值以后在發(fā)送給A主進(jìn)程
onMounted(()=>{
ipcRenderer.on('modal-accomplish-state',()=>{
console.log('偉大時(shí)代');
ipcRenderer.send('modal-accomplish-end','傳值');
})
})
A主進(jìn)程接收到值以后發(fā)送給B渲染進(jìn)程
ipcMain.on('modal-accomplish-end',(event,token)=>{
modal.webContents.send('modal-accomplish-child-end',token);
})
B渲染進(jìn)程接收值
ipcRenderer.on('modal-accomplish-child-end',(event,msg)=>{
console.log(msg); // 傳值
})
以上五/六步就可以將值獲取到了;你學(xué)會(huì)了嗎?
image.png
以上看起來可以能些許復(fù)雜,你多練習(xí)兩次就覺得還好了!這也是為了避免一些問題想出來的;大家可以參考;有更好的方法也可以留言討論
注意 如果你在寫了代碼以后沒有接收到值的話,可以重啟一下;可能是你寫了主進(jìn)程代碼更新不及時(shí)導(dǎo)致的
戰(zhàn)wxPython系列-044
本文介紹如何在Python的GUI工具中嵌入HTML頁面。
wxPython的wx.html和wx.html2模塊支持解析和顯示HTML文件內(nèi)容。wx.html.HtmlWindow對(duì)象是一個(gè)通用的HTML瀏覽器,但不是一個(gè)全功能的瀏覽器,所以支持的功能有限。wx.html.HtmlWindow只支持HTML標(biāo)準(zhǔn)的一個(gè)子集,不支持Javascript或者CSS。如果要支持全特性的HTML渲染組件,請使用wx.html2.WebView。
一、wx.html.HtmlWindow簡介
wx.html.HtmlWindow控件的目的是顯示基于HTML標(biāo)準(zhǔn)字跡的富內(nèi)容頁面(本地文件或者通過HTTP下載的網(wǎng)頁文件),一定創(chuàng)建了該窗口控件,可以通過調(diào)用SetPage和LoadPage來設(shè)置它的內(nèi)容。
wx.html.HtmlWindow支持的窗口樣式:
wx.html.HtmlWindow發(fā)出的事件:
wx.html.HtmlWindow常用方法:
圖1:wx.html.HtmlWindow類繼承關(guān)系
二、wx.html.HtmlWindow演示
Htmlwin.py文件
#html窗口(wx.html.HtmlWindow)
import wx
import wx.html
class SampleHtmlWindow(wx.Frame):
def __init__(self, *args, **kw):
super(SampleHtmlWindow, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
self.SetTitle("實(shí)戰(zhàn)wxPython: HtmlWindow演示")
self.SetSize(400, 300)
panel=wx.Panel(self)
vbox=wx.BoxSizer(wx.VERTICAL)
hbox=wx.BoxSizer(wx.HORIZONTAL)
htmlwin=wx.html.HtmlWindow(panel, wx.ID_ANY, style=wx.NO_BORDER)
htmlwin.SetStandardFonts()
htmlwin.LoadPage("page.html")
"""
htmlwin.SetPage('''
<html>
<body bgcolor="#fdd22f">
<h1>這是標(biāo)題</h1>
<b style="color:blue">實(shí)戰(zhàn)wxPython</b>
<p>通過RGB值設(shè)置背景顏色</p>
<br/>
<p>
這是一個(gè)段落
</p>
<i>這是斜體文本</i>
</body>
</html>
''')
"""
vbox.Add((-1, 10), 0)
vbox.Add(htmlwin, 1, wx.EXPAND | wx.ALL, 9)
bitmap=wx.StaticBitmap(panel, wx.ID_ANY, wx.Bitmap("newt.png"))
hbox.Add(bitmap, 0, wx.LEFT | wx.BOTTOM | wx.TOP, 10)
btnOk=wx.Button(panel, wx.ID_ANY, "確定")
self.Bind(wx.EVT_BUTTON, self.OnClose, id=btnOk.GetId())
hbox.Add((100, -1), 1, wx.LEFT)
hbox.Add(btnOk, flag=wx.TOP | wx.BOTTOM | wx.RIGHT, border=10)
vbox.Add(hbox, 0, wx.EXPAND)
panel.SetSizer(vbox)
self.Centre()
def OnClose(self, e):
self.Close()
def main():
app=wx.App()
sample=SampleHtmlWindow(None)
sample.Show()
app.MainLoop()
if __name__=="__main__":
main()
page.html文件
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
</head>
<html>
<table cellspacing="5" border="0" width="250">
<tr width="200" align="left">
<td bgcolor="#e7e7e7"> Maximum</td>
<td bgcolor="#aaaaaa"> <b>9000</b></td>
</tr>
<tr align="left">
<td bgcolor="#e7e7e7"> Mean</td>
<td bgcolor="#aaaaaa"> <b>6076</b></td>
</tr>
<tr align="left">
<td bgcolor="#e7e7e7"> Minimum</td>
<td bgcolor="#aaaaaa"> <b>3800</b></td>
</tr>
<tr align="left">
<td bgcolor="#e7e7e7"> Median</td>
<td bgcolor="#aaaaaa"> <b>6000</b></td>
</tr>
<tr align="left">
<td bgcolor="#e7e7e7"> Standard Deviation</td>
<td bgcolor="#aaaaaa"> <b>6076</b></td>
</tr>
</table>
</html>
上面的示例演示了如何使用wx.html.HtmlWindow來加載一個(gè)html文件并顯示它。
htmlwin=wx.html.HtmlWindow(panel, wx.ID_ANY, style=wx.NO_BORDER)
htmlwin.SetStandardFonts()
htmlwin.LoadPage("page.html")
創(chuàng)建wx.html.HtmlWindow對(duì)象,然后使用LoadPage方法加載文件。
圖2:wx.html.HtmWindow演示
三、本文知識(shí)點(diǎn)
前一篇:wxPython - 高級(jí)控件之表格Grid
請關(guān)注,評(píng)論,收藏,點(diǎn)贊,和轉(zhuǎn)發(fā)。
很早之前就有寫過一個(gè)wcPop.js彈窗插件,并且在h5酒店預(yù)訂、h5聊天室項(xiàng)目中都有使用過,效果還不錯(cuò)。當(dāng)初想著有時(shí)間整合一個(gè)Vue版本,剛好趁著國慶節(jié)空閑時(shí)間搗鼓了個(gè)vue.js版自定義模態(tài)彈出框組件VPopup。
v-popup 一款聚合Msg、Dialog、Popup、ActionSheet、Toast等功能的輕量級(jí)移動(dòng)端Vue彈窗組件。
整合了有贊Vant及NutUI等熱門Vue組件庫中Popup彈出層、Toast輕提示、Notify消息提示、Dialog對(duì)話框及ActionSheet動(dòng)作面板等功能。
// 在main.js中全局引入
import Vue from 'vue'
import Popup from './components/popup'
Vue.use(Popup)
支持如下兩種方式調(diào)用組件。
<v-popup
v-model="showPopup"
title="標(biāo)題內(nèi)容"
content="彈窗內(nèi)容,告知當(dāng)前狀態(tài)、信息和解決方法,描述文字盡量控制在三行內(nèi)"
type="android"
shadeClose="false"
xclose
z-index="2000"
:btns="[
{...},
{...},
]"
/>
this.$vpopup({...}),傳入?yún)?shù)即可使用,該函數(shù)會(huì)返回彈窗組件實(shí)例。
let $el=this.$vpopup({
title: '標(biāo)題內(nèi)容',
content: '彈窗內(nèi)容,描述文字盡量控制在三行內(nèi)',
type: 'android',
shadeClose: false,
xclose: true,
zIndex: 2000,
btns: [
{text: '取消'},
{
text: '確認(rèn)',
style: 'color:#f60;',
click: ()=> {
$el.close()
}
},
]
});
你可根據(jù)喜好或項(xiàng)目需要任意選擇一種調(diào)用方式即可。下面就開始講解下組件的實(shí)現(xiàn)。
在components目錄下新建popup.vue頁面。
組件參數(shù)配置
<!-- Popup 彈出層模板 -->
<template>
<div v-show="opened" class="nuxt__popup" :class="{'nuxt__popup-closed': closeCls}" :id="id">
<div v-if="JSON.parse(shade)" class="nuxt__overlay" @click="shadeClicked" :style="{opacity}"></div>
<div class="nuxt__wrap">
<div class="nuxt__wrap-section">
<div class="nuxt__wrap-child" :class="['anim-'+anim, type&&'popui__'+type, round&&'round', position]" :style="popupStyle">
<div v-if="title" class="nuxt__wrap-tit" v-html="title"></div>
<div v-if="type=='toast'&&icon" class="nuxt__toast-icon" :class="['nuxt__toast-'+icon]" v-html="toastIcon[icon]"></div>
<template v-if="$slots.content">
<div class="nuxt__wrap-cnt"><slot name="content" /></div>
</template>
<template v-else>
<div v-if="content" class="nuxt__wrap-cnt" v-html="content"></div>
</template>
<slot />
<div v-if="btns" class="nuxt__wrap-btns">
<span v-for="(btn,index) in btns" :key="index" class="btn" :class="{'btn-disabled': btn.disabled}" :style="btn.style" @click="btnClicked($event,index)" v-html="btn.text"></span>
</div>
<span v-if="xclose" class="nuxt__xclose" :class="xposition" :style="{'color': xcolor}" @click="close"></span>
</div>
</div>
</div>
</div>
</template>
<script>
// 彈窗索引,遮罩次數(shù),定時(shí)器
let $index=0, $lockCount=0, $timer={};
export default {
props: {
...
},
data() {
return {
opened: false,
closeCls: '',
toastIcon: {
loading: '<svg viewBox="25 25 50 50"><circle fill="none" cx="50" cy="50" r="20"></circle></svg>',
success: '<svg viewBox="0 0 1024 1024"><path fill="none" d="M75.712 445.712l240.176 185.52s13.248 6.624 29.808 0l591.36-493.872s84.272-17.968 68.64 71.488c-57.04 57.968-638.464 617.856-638.464 617.856s-38.096 21.536-74.544 0C256.272 790.256 12.816 523.568 12.816 523.568s-6.672-64.592 62.896-77.856z"/></svg>',
fail: '<svg viewBox="0 0 1024 1024"><path fill="none" d="M450.602 665.598a62.464 62.464 0 0 0 122.88 0l40.96-563.198A102.615 102.615 0 0 0 512.042 0a105.256 105.256 0 0 0-102.4 112.64l40.96 552.958zm61.44 153.6a102.4 102.4 0 1 0 102.4 102.4 96.74 96.74 0 0 0-102.4-102.4z"/></svg>',
}
}
},
watch: {
value(val) {
const type=val ? 'open' : 'close';
this[type]();
},
},
methods: {
// 打開彈窗
open() {
if(this.opened) return;
this.opened=true;
this.$emit('open');
typeof this.onOpen==='function' && this.onOpen();
this.$el.style.zIndex=this.getZIndex() + 1;
if(JSON.parse(this.shade)) {
if(!$lockCount) {
document.body.classList.add('nt-overflow-hidden');
}
$lockCount++;
}
// 倒計(jì)時(shí)關(guān)閉
if(this.time) {
$index++;
// 防止重復(fù)點(diǎn)擊
if($timer[$index] !==null) clearTimeout($timer[$index])
$timer[$index]=setTimeout(()=> {
this.close();
}, parseInt(this.time) * 1000);
}
// 長按/右鍵彈窗
if(this.follow) {
// 避免獲取不到彈窗寬高
this.$nextTick(()=> {
let obj=this.$el.querySelector('.nuxt__wrap-child');
let oW, oH, winW, winH, pos;
oW=obj.clientWidth;
oH=obj.clientHeight;
winW=window.innerWidth;
winH=window.innerHeight;
pos=this.getPos(this.follow[0], this.follow[1], oW, oH, winW, winH);
obj.style.left=pos[0] + 'px';
obj.style.top=pos[1] + 'px';
});
}
},
// 關(guān)閉彈窗
close() {
if(!this.opened) return;
this.closeCls=true;
setTimeout(()=> {
this.opened=false;
this.closeCls=false;
if(JSON.parse(this.shade)) {
$lockCount--;
if(!$lockCount) {
document.body.classList.remove('nt-overflow-hidden');
}
}
if(this.time) {
$index--;
}
this.$emit('input', false);
this.$emit('close');
typeof this.onClose==='function' && this.onClose();
}, 200);
},
// 點(diǎn)擊遮罩層
shadeClicked() {
if(JSON.parse(this.shadeClose)) {
this.close();
}
},
// 按鈕事件
btnClicked(e, index) {
let btn=this.btns[index];
if(!btn.disabled) {
typeof btn.click==='function' && btn.click(e)
}
},
// 獲取彈窗層級(jí)
getZIndex() {
for(var $idx=parseInt(this.zIndex), $el=document.getElementsByTagName('*'), i=0, len=$el.length; i < len; i++)
$idx=Math.max($idx, $el[i].style.zIndex)
return $idx;
},
// 獲取彈窗坐標(biāo)點(diǎn)
getPos(x, y, ow, oh, winW, winH) {
let l=(x + ow) > winW ? x - ow : x;
let t=(y + oh) > winH ? y - oh : y;
return [l, t];
}
},
}
</script>
通過監(jiān)聽v-model值調(diào)用open和close方法。
watch: {
value(val) {
const type=val ? 'open' : 'close';
this[type]();
},
},
如果想要實(shí)現(xiàn)函數(shù)式調(diào)用this.$vpopup({...}),則需要使用到Vue.extend擴(kuò)展實(shí)例構(gòu)造器。
import Vue from 'vue';
import VuePopup from './popup.vue';
let PopupConstructor=Vue.extend(VuePopup);
let $instance;
let VPopup=function(options={}) {
// 同一個(gè)頁面中,id相同的Popup的DOM只會(huì)存在一個(gè)
options.id=options.id || 'nuxt-popup-id';
$instance=new PopupConstructor({
propsData: options
});
$instance.vm=$instance.$mount();
let popupDom=document.querySelector('#' + options.id);
if(options.id && popupDom) {
popupDom.parentNode.replaceChild($instance.$el, popupDom);
} else {
document.body.appendChild($instance.$el);
}
Vue.nextTick(()=> {
$instance.value=true;
})
return $instance;
}
VPopup.install=()=> {
Vue.prototype['$vpopup']=VPopup;
Vue.component('v-popup', VuePopup);
}
export default VPopup;
這樣就實(shí)現(xiàn)了引入 Popup 組件后,會(huì)自動(dòng)在 Vue 的 prototype 上掛載 $vpopup 方法和注冊 v-popup 組件。
下面就可以愉快的使用標(biāo)簽式及函數(shù)式調(diào)用組件了。
<v-popup v-model="showActionPicker" anim="footer" type="actionsheetPicker" round title="標(biāo)題內(nèi)容"
:btns="[
{text: '取消', click: ()=> showActionPicker=false},
{text: '確定', style: 'color:#00e0a1;', click: ()=> null},
]"
>
<ul class="goods-list" style="padding:50px;text-align:center;">
<li>雙肩包</li>
<li>鞋子</li>
<li>運(yùn)動(dòng)褲</li>
</ul>
</v-popup>
<v-popup v-model="showBottom" position="bottom" round xclose title="標(biāo)題內(nèi)容">
<ul class="goods-list" style="padding:50px;text-align:center;">
<li>雙肩包</li>
<li>鞋子</li>
<li>運(yùn)動(dòng)褲</li>
</ul>
</v-popup>
按鈕設(shè)置disabled: true即可禁用按鈕事件。
<v-popup v-model="showActionSheet" anim="footer" type="actionsheet" :z-index="2020"
content="彈窗內(nèi)容,描述文字盡量控制在三行內(nèi)"
:btns="[
{text: '拍照', style: 'color:#09f;', disabled: true, click: handleInfo},
{text: '從手機(jī)相冊選擇', style: 'color:#00e0a1;', click: handleInfo},
{text: '保存圖片', style: 'color:#e63d23;', click: ()=> null},
{text: '取消', click: ()=> showActionSheet=false},
]"
/>
另外還支持自定義slot插槽內(nèi)容,當(dāng) content 和 自定義插槽 內(nèi)容同時(shí)存在,只顯示插槽內(nèi)容。
<v-popup v-model="showComponent" xclose xposition="bottom" content="這里是內(nèi)容信息"
:btns="[
{text: '確認(rèn)', style: 'color:#f60;', click: ()=> showComponent=false},
]"
@open="handleOpen" @close="handleClose"
>
<template #content>當(dāng) content 和 自定義插槽 內(nèi)容同時(shí)存在,只顯示插槽內(nèi)容!</template>
<div style="padding:30px 15px;">
<img src="assets/apple3.jpg" style="width:100%;" @click="handleContextPopup" />
</div>
</v-popup>
好了,就分享到這里。希望對(duì)大家有所幫助。目前該組件正在項(xiàng)目中實(shí)戰(zhàn)測試,后續(xù)會(huì)分享相關(guān)使用情況。
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。