一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

桌面軟件GUI開(kāi)發(fā)框架

 hewii 2022-10-13 發(fā)布于上海

本文基于??低曌烂娑思夹g(shù)專(zhuān)家劉曉倫在「RTC Dev Meetup?杭州站丨大前端時(shí)代的業(yè)務(wù)架構(gòu)和跨端實(shí)踐」活動(dòng)中分享內(nèi)容二次整理。

以下正文:

今天要與大家分享 19 款桌面軟件開(kāi)發(fā)框架,我將它們分了四類(lèi),然后分別就每個(gè)類(lèi)別做相應(yīng)的介紹,希望通過(guò)今天的分享,幫助大家在開(kāi)發(fā)的過(guò)程當(dāng)中少走一些彎路。

01 傳統(tǒng)桌面軟件開(kāi)發(fā)框架

首先我們來(lái)聊一聊傳統(tǒng)的桌面軟件開(kāi)發(fā)框架。這個(gè)類(lèi)別中包含大家常見(jiàn)的 Qt、wxWidgets、GTK、FLTK、Swing 和 JavaFX。這六個(gè)框架有一些共同點(diǎn):它們的歷史都很悠久,使用的開(kāi)發(fā)者也很多,并且相應(yīng)的社區(qū)也很成熟,其中包含了豐富的資料。此外,它們的功能都很強(qiáng)大,有大量成熟的案例,框架也很穩(wěn)定。

但是它們用到的都是相對(duì)來(lái)說(shuō)都是比較成熟的技術(shù),所以跟新興技術(shù)之間還是有所差距,所以使用起來(lái)比較困難。

1、Qt

Qt 的優(yōu)點(diǎn)大家都可以在官網(wǎng)上看到,這里不再贅述,其中有一點(diǎn)是 Qt 對(duì)各操作系統(tǒng)都做了很完善的封裝,比如網(wǎng)絡(luò)、文件剪切板等,如果要用系統(tǒng)級(jí)的 API,Qt 可以提供的非常豐富的 API。

對(duì)于 Qt 的問(wèn)題這里介紹一下我的感受,我認(rèn)為 Qt 目前的問(wèn)題是發(fā)展方向不太專(zhuān)一,無(wú)法提供某些較大的模塊,在開(kāi)發(fā)過(guò)程中可能會(huì)逐漸發(fā)現(xiàn)使用的模塊不太合適,進(jìn)而廢棄這個(gè)模塊,包括很多 API 也是這樣,我之前用過(guò)的 Qt script 現(xiàn)在就已經(jīng)被標(biāo)記為廢棄了。

另外,Qt 的商業(yè)授權(quán)是不太友好的。如果要開(kāi)發(fā)一個(gè)商業(yè)應(yīng)用,可能這里要注意一下,有很多國(guó)內(nèi)的公司都是收到過(guò) Qt 的律師函要求收費(fèi)的。Qt 還提供了很多組件,其中有一些復(fù)雜的組件對(duì)于控制 UI 的細(xì)節(jié)是比較難的,這里就不再舉例了。

Qt 還有很多的動(dòng)態(tài)鏈接庫(kù),如果要做靜態(tài)鏈接也是比較難的,當(dāng)然社區(qū)中提供了一種辦法,就是可以編譯 Qt 的源碼做靜態(tài)鏈接,但是這就又要涉及版權(quán)的問(wèn)題了。

2、GTK

GTK 框架比較偏 Linux,在 Linux 中有很多桌面應(yīng)用都是用 GTK 開(kāi)發(fā)的,在 Windows 下 GTK 相對(duì)較少,并且在 Windows 系統(tǒng)下的靜態(tài)鏈接也是比較難的,甚至搭環(huán)境都比在 Linux 系統(tǒng)下要難得多。

另外,GTK 在 Windows 下也做了系統(tǒng) API 的封裝,但是在 Windows 下的封裝比在 Linux 系統(tǒng)下的封裝要少一些。也就是說(shuō),有些 API 在 Linux 下能用,而在 Windows 下是不能用的,這樣的 API 不在少數(shù)。最后 GTK 的商業(yè)授權(quán)是非常友好的。

3、FLTK

FLTK 框架是 C++ 之父推薦使用的,它就是一個(gè)非常輕量的 GUI 框架,但是輕量意味著功能是不足的,它的功能比較少,幾乎不做系統(tǒng) API 的封裝,大部分都要開(kāi)發(fā)人員自己用 C++ 編寫(xiě)。這樣導(dǎo)致開(kāi)發(fā)人員在每個(gè)平臺(tái)上都要重新編寫(xiě),比如要開(kāi)放一個(gè)跨平臺(tái)的圖片應(yīng)用,那么在 Windows 下調(diào)用一些系統(tǒng)級(jí)的 API 進(jìn)行實(shí)現(xiàn),在 Mac 下可能又要實(shí)現(xiàn)一遍。

FLTK 的優(yōu)點(diǎn)是它的產(chǎn)物很小,因此它編譯出來(lái)的東西可以做到很小,而且性能也非常好(比前兩個(gè)都好)。FLTK 的商業(yè)授權(quán)也很友好,可以支持靜態(tài)鏈接。但是 FLTK 有一些不足,就是因?yàn)樗且粋€(gè) GUI 框架,因此在繪制 GUI 組件這方面是不太好的。

我在使用 FLTK 的時(shí)候發(fā)現(xiàn),在其中做動(dòng)畫(huà)控制、組件疊加(這時(shí)用到就是絕對(duì)定位,就需要對(duì)組件的層級(jí)進(jìn)行控制)都會(huì)遇到問(wèn)題。另外,在繪制圓角的時(shí)候,雖然 FLTK 提供了相關(guān)的功能,但是用戶還要控制圓角的特殊大小、某一個(gè)圓角出現(xiàn)等,這些都要寫(xiě)非常復(fù)雜的代碼。

4、wxWidgets

wxWidgets 跟前面 3 個(gè)框架有所區(qū)別,它是基于操作系統(tǒng)的 API 來(lái)做桌面應(yīng)用的,也就是說(shuō),在 Windows 下開(kāi)發(fā)一個(gè)桌面應(yīng)用時(shí),看起來(lái)就像是傳統(tǒng)的 Windows 桌面軟件的風(fēng)格,在 Mac 下則是 Mac 的風(fēng)格,而前面三個(gè)都有自己的自繪引擎。

也就是說(shuō),在前面三個(gè)框架中做一個(gè)按鈕,不管用什么樣的繪制方式,在三個(gè)平臺(tái)下表現(xiàn)都是一致的,但是 wxWidgets 在三個(gè)平臺(tái)上都是按照三個(gè)平臺(tái)自己的 API 來(lái)繪制這個(gè)按鈕的。wxWidgets 提供了非常多的操作系統(tǒng)的 API,并且可以做到靜態(tài)鏈接,但小問(wèn)題比較多。

5、Swing/JavaFX

Swing /JavaFX 是基于 Java 的技術(shù)棧來(lái)做桌面應(yīng)用的,因?yàn)橐蕾?JVM,所以系統(tǒng) API 比較多,但性能會(huì)一般,這兩個(gè)框架可能相對(duì)來(lái)說(shuō)用得少一些。

如果大家在這幾個(gè)桌面軟件框架當(dāng)中做選擇的話,我個(gè)人推薦還是用 Qt。

02 新興桌面軟件開(kāi)發(fā)框架

剛才我們說(shuō)的一些框架可能用的技術(shù)比較陳舊,大家開(kāi)發(fā)起來(lái)比較麻煩。新興的框架,比如微軟的 MAUI、谷歌的 Flutter Desktop 和 JetBrains 公司的 Compose Multiplatform,都是采用非常新的技術(shù)來(lái)做的,開(kāi)發(fā)起來(lái)很容易,開(kāi)發(fā)體驗(yàn)也非常好。

但是因?yàn)檫@幾個(gè)框架都比較新,基本上都是今年發(fā)布的正式版(最早是 Compose Multiplatform 發(fā)布的,然后依次是 lutter Desktop 和 MAUI),所以社區(qū)相對(duì)來(lái)說(shuō)不如前面幾個(gè)框架成熟,資料和成功案例也相對(duì)來(lái)說(shuō)少一些。

1、MAUI

MAUI 是用 XAML 是寫(xiě)界面和邏輯的,大家如果用 WPF 寫(xiě)過(guò)軟件的話,應(yīng)該會(huì)對(duì)這項(xiàng)技術(shù)很熟悉。MAUI 用 C# 編寫(xiě)業(yè)務(wù)邏輯,只兼容 Windows 操作系統(tǒng)和 Mac 操作系統(tǒng)。MAUI 在 Linux 下是社區(qū)提供的一套支持體系,可能會(huì)有一些問(wèn)題。另外,MAUI 是依賴 .NET 框架的,API 比較多,并且支持移動(dòng)端(這三個(gè)框架都是支持移動(dòng)端的,新興的開(kāi)發(fā)框架都兼容移動(dòng)端的開(kāi)發(fā))。

2、Flutter Desktop

Flutter Desktop 是使用 dart 編寫(xiě)界面邏輯的,它的組件比較豐富,并且支持 Win 10 操作系統(tǒng)(之前的操作系統(tǒng)就不太支持了),API 是比較少的,需要開(kāi)發(fā)人員自己來(lái)寫(xiě)。

3、Compose Multiplatform

Compose Multiplatform 依賴 JVM,是用 Kotlin 編寫(xiě)邏輯的界面和邏輯的,有消息說(shuō)將來(lái)可能會(huì)推出 Kotlin/native*,這樣就可以不用依賴 JVM 了,但是這可能還比較遙遠(yuǎn)的事情。Compose Multiplatform 的組件也是比較豐富的,大家都知道 Java 社區(qū)中有很多框架、模塊等都可以使用,并且也是支持應(yīng)用端的。

在這幾類(lèi)框架里中我推薦大家使用 Flutter Desktop,雖然它們都是新興的框架,所以很難說(shuō)哪一個(gè)將來(lái)會(huì)更受歡迎,但是根據(jù)它們的共同點(diǎn)(技術(shù)更現(xiàn)代化、更加易用、資料較少、社區(qū)不成熟、成功案例較少、用戶較少、不穩(wěn)定),我還是推薦 Flutter Desktop。

03 基于瀏覽器的桌面軟件開(kāi)發(fā)框架

基于瀏覽器的桌面軟件開(kāi)發(fā)框架相對(duì)較多,比如 Electron、NW.js、CEF、Sciter、WebView2、webview 和 TAURI。其中使用 Electron 比較多,也已經(jīng)非常成熟。它們的共同點(diǎn)是它們可以復(fù)用瀏覽器的技術(shù),比如 html、JS 和 CSS 等一系列生態(tài)中的組件。

除此之外,它們還可以做非常絢麗的界面,因?yàn)?Web 技術(shù)發(fā)展這么年,CSS、html 等在標(biāo)記和控制界面特性方面的技術(shù)都已經(jīng)非常成熟,不像剛才提到的 FLTK 要做疊加動(dòng)畫(huà)效果都非常困難,如果用這些技術(shù)做這些界面會(huì)非常從容。但這些框架的功能也是有強(qiáng)有弱。

1、Electron/NW.js

Electron 和 NW.js 這兩個(gè)框架是非常相似的技術(shù),它們都是把 Chromium 與 Node.js 集成到一起,讓開(kāi)發(fā)者可以只使用前端技術(shù)開(kāi)發(fā)桌面應(yīng)用。如果要訪問(wèn)系統(tǒng)的 API,就用 Node.js 提供的 API,當(dāng)然也有一些特殊的 API,比方創(chuàng)建桌面圖標(biāo)、訪問(wèn)剪切板、控制窗口大小等,是 Electron 框架本身提供的,而不是 Node.js 提供的,也不是傳統(tǒng) HTML 系統(tǒng)提供的,是在其中做了一些附加的操作,當(dāng)然 NW.js 也有。

這兩個(gè)框架的作者都有很深的淵源,這里就不細(xì)說(shuō)了。我個(gè)人覺(jué)得 NW.js 實(shí)現(xiàn)起來(lái)相對(duì)來(lái)說(shuō)比較巧妙,對(duì)開(kāi)發(fā)者比較友好,而 Electron 維護(hù)更給力,社區(qū)也很龐大。

2、CEF/WebView2

CEF 和 WebView2 框架都是直接基于 Chromium 開(kāi)發(fā)的。CEF 的歷史比較悠久,而且更靈活,大家可以通過(guò)這個(gè)框架進(jìn)行自由的控制,API 也更多。

WebView2 是微軟的短期團(tuán)隊(duì)提供的一個(gè)框架,這個(gè)框架也是直接基于基于 Chromium 做的封裝,它提供了 .NET 和 C++ 的 API,大家可以用 .NET、C++ 或者 C# 語(yǔ)言去操作這個(gè)框架,目前還不支持 MAC(將來(lái)可能會(huì)支持)。

相對(duì)來(lái)說(shuō) CEF 更像作者個(gè)人在維護(hù),WebView2 就更像一個(gè)團(tuán)隊(duì),但是因?yàn)?WebView2 不開(kāi)源,所以也沒(méi)法參與。

3、webview/TAURI

webview 和 TAURI 使用操作系統(tǒng)內(nèi)配置的瀏覽器核心,比如應(yīng)該在 Windows 下部署,那么就用 WebView2;如果在 Mac 下部署,就用 WKWebView;如果在 Linux 下部署,就用 webkitgtk 來(lái)做渲染,因此這里可能就會(huì)有一些兼容性的問(wèn)題。

在做前端的時(shí)候經(jīng)常會(huì)碰到一些兼容性的問(wèn)題,但是目前來(lái)看,因?yàn)樗鼈兌际潜容^現(xiàn)代的瀏覽器核心了,所以這個(gè)問(wèn)題還沒(méi)有這么明顯。另外,TAURI 是使? Rust 開(kāi)發(fā)的,如果要選擇這個(gè)框架,可能還得熟悉 Rust 語(yǔ)言。

4、Sciter

Sciter 是一個(gè)比較特殊的框架,這里把它單列出來(lái),Sciter 做了很多的削減,可以把產(chǎn)物的體積縮減到 10M 以內(nèi),前面幾種框架基本上只要把瀏覽器核心分發(fā)給用戶,即使壓縮過(guò)后也得 60M。

Sciter 以前有一個(gè)自己的腳本叫 TIscript,現(xiàn)在用的是 QuickJS,它的功能非常強(qiáng)大,而且集成了 skia 的核心版本。我不知道大家有沒(méi)有關(guān)注過(guò)一個(gè)叫作 rustdesk 的項(xiàng)目,之前它選擇的就是 Sciter 框架,當(dāng)然這個(gè)框架的小問(wèn)題也會(huì)比較多。

如果大家選擇這類(lèi)框架,我推薦使用 Electron/CEF 框架。如果團(tuán)隊(duì)中沒(méi)有 C++ 開(kāi)發(fā)人員,或者不易于使用 C++ 進(jìn)行開(kāi)發(fā)應(yīng)用,就選擇 Electron;如果有 C++ 開(kāi)發(fā)人員,而且應(yīng)用非常注重性能,就選擇 CEF。

04 即時(shí)渲染桌面軟件開(kāi)發(fā)框架

即時(shí)渲染相對(duì)應(yīng)用的是保持模式的桌面應(yīng)用框架,一般做桌面應(yīng)用都是哪里需要更新,就更新哪里,框架會(huì)進(jìn)行渲染。但是即時(shí)渲染是不一樣的,它是每刷新一幀,就會(huì)把顯示的內(nèi)容都更新一遍,也就是說(shuō)每一幀都會(huì)全部更新一遍。

所以這類(lèi)框架有一個(gè)共同的特點(diǎn),就是它們要消耗 CPU 和 GPU 資源,傳統(tǒng)框架的配置都是保持模式,如果不更新是不會(huì)做渲染的。另外,這種框架與游戲應(yīng)用可以無(wú)縫對(duì)接,但是傳統(tǒng)應(yīng)用案例比較少,小問(wèn)題比較多,且尚在發(fā)展中。

1、Dear ImGui

即時(shí)渲染桌面軟件開(kāi)發(fā)框架中,Dear ImGui 比較流行,最近作者在開(kāi)發(fā) Dock 模式,估計(jì)今年有可能會(huì)推出,到時(shí)候大家可以去嘗試一下。

它的開(kāi)發(fā)方式是比較特別的,就是每個(gè)循環(huán)都在做渲染。比如使用 Dear ImGui 做事件開(kāi)發(fā)時(shí),會(huì)將某一個(gè)變量設(shè)置為 true 或者 false, 在這一輪渲染的過(guò)程當(dāng)中是 true,在它下一輪渲染過(guò)程當(dāng)中,我發(fā)現(xiàn)變成 false 了,我們就認(rèn)為觸發(fā)了某個(gè)事件。而不是像 web 開(kāi)發(fā)領(lǐng)域中,當(dāng)出現(xiàn)一個(gè) event 時(shí),另一個(gè)組件就可以接收到它。

2、Nuklear

Nuklear 是使? C 語(yǔ)?開(kāi)發(fā)的,更貼近 C 開(kāi)發(fā)者的習(xí)慣,?戶相對(duì) Dear ImGui 更少、?問(wèn)題更多。

3、RmIui

RmlUi 比較特殊,它不是即時(shí)渲染框架,但是卻有即時(shí)渲染框架的通病,就是用它開(kāi)發(fā)應(yīng)用之后會(huì)持續(xù)消耗 CPU 和 GPU 資源,它可以使用 HTML 和 CSS 描述界面,上手相對(duì)比較難,開(kāi)發(fā)非常靈活,界面也很靈活,資源消耗相對(duì)更多。

我最近一直在用這個(gè)框架,也跟作者進(jìn)行了深入的交流。這個(gè)框架開(kāi)發(fā)出來(lái)的應(yīng)用程序可以做到 2M 左右,它可以解析你的 HTML,做一些非常特殊的效果,比如陰影、漸變之類(lèi)的動(dòng)畫(huà),但是它很小,不像瀏覽器一樣,即使壓縮也得 60 多兆,這也是它的優(yōu)勢(shì)。

這幾類(lèi)框架中我個(gè)人推薦 RmlUi,如果到作者的項(xiàng)目中進(jìn)行提問(wèn),他基本上隔天就會(huì)回復(fù)。

05 總結(jié)

在做總結(jié)之前,我先簡(jiǎn)述一下這幾個(gè)框架的對(duì)比。

其實(shí)我們?cè)诮榻B傳統(tǒng)的桌面開(kāi)發(fā)框架的時(shí)候,Qt 和 wxWidgets 內(nèi)置的組件也有基于瀏覽器的, 就是 QWebEngin 和 wxWebView,QWebEngin 封裝的是 Chromium 的核心,其實(shí)與 CEF 和 QWebEngin 挺像的,但是很多人在用 Qt 的時(shí)候,是把 CEF 集成到 Qt 中,反而不用 QWebEngin。

他們堅(jiān)持的觀點(diǎn)就是 QWebEngin 還不成熟,性能力相對(duì)來(lái)較弱,不如 CEF,但是目前來(lái)看,我個(gè)人認(rèn)為,在 Qt 6.2 和 Qt 6.3 之后,QWebEngin 的 API 會(huì)更多,應(yīng)用的需求更容易滿足。

wxWebView 更像是 webview 和 TAURI,它也是在不同的操作系統(tǒng)上使用操作系統(tǒng)的瀏覽器核心,這里就不多說(shuō)了。

再看一下 RmlUi 和 Sciter 的對(duì)比。RmlUi 可以用 html 和 CSS,Sciter 也可以用 html 和 CSS,因?yàn)?Sciter 集成了 QuickJS,所以它也可以寫(xiě) JS 代碼(但是也得寫(xiě) C++,因?yàn)槟悴豢赡懿挥貌僮飨到y(tǒng)的 API,但是它的 C++ 可能會(huì)比 RmlUi 的 C++ 代碼量要少很多)。兩個(gè)框架都不支持全部的 html 和 CSS 規(guī)范。

如果要選一個(gè)桌面軟件開(kāi)發(fā)框架,應(yīng)該確認(rèn)側(cè)重哪方面的能力,我認(rèn)為有三方面的能力是需要注重的:

  • 界面的描述能力:比如布局、元素定位、圓角、陰影、漸變

  • 事件處理能力:比如鼠標(biāo)事件、鍵盤(pán)事件、觸屏事件、媒體播放結(jié)束、網(wǎng)絡(luò)狀態(tài)變更等

  • 異步處理能力:處理業(yè)務(wù)邏輯的時(shí)候,界面渲染工作不能暫停

另外,桌面軟件開(kāi)發(fā)框架各有各的優(yōu)勢(shì),比如軟件開(kāi)發(fā)邏輯很復(fù)雜,而且要快速地完成,那么 BrowserCore 可能是一個(gè)不錯(cuò)的方式,因?yàn)橛们岸思夹g(shù)來(lái)編寫(xiě)速度更快,但是如果軟件需要更少的資源消耗和更快的運(yùn)行速度,那么就需要考慮 Native 方式。

最后,要做桌面應(yīng)用開(kāi)發(fā)需要了解一些底層知識(shí),比如多線程、多進(jìn)程的控制;各種通信協(xié)議;?志收集;版本控制;設(shè)計(jì)模式與架構(gòu)原則;本地?cái)?shù)據(jù)控制;操作系統(tǒng)。

06 問(wèn)答環(huán)節(jié)

1、用 Electron 怎么處理 crash?

Electron 也有非常多問(wèn)題,它也會(huì)崩潰,并且有崩潰報(bào)告的收集方式,收集這些報(bào)告之后還要進(jìn)行分析,但是分析出來(lái)的崩潰報(bào)告實(shí)并不能很明確地反映到底是哪一行代碼、哪一段業(yè)務(wù)出了問(wèn)題。很多時(shí)候崩潰報(bào)告中可能更多的是說(shuō)明一個(gè)指針指向的內(nèi)存出現(xiàn)了問(wèn)題,這時(shí)一種方法是盡量聯(lián)系用戶復(fù)現(xiàn)問(wèn)題;第二種方式是做大量的自動(dòng)化測(cè)試,收窄問(wèn)題的范圍,將其局限在一定的范圍內(nèi)再做精細(xì)化處理;第三種方式就是做 AB 測(cè)試。

2、Electron 開(kāi)發(fā)的應(yīng)用安裝包太大這個(gè)問(wèn)題有沒(méi)有好的解決辦法。另外,開(kāi)發(fā)者該如何開(kāi)發(fā) Electron 應(yīng)用的守護(hù)進(jìn)程。

這是兩個(gè)問(wèn)題。第一個(gè)問(wèn)題就是包太大的問(wèn)題,這個(gè)其實(shí)是挺難解決的,在立項(xiàng)之前就應(yīng)該跟團(tuán)隊(duì)負(fù)責(zé)人溝通好需求,是要快速的業(yè)務(wù)開(kāi)發(fā),還是更高的性能,更小的體積?如果要更小的體積,那么就放棄業(yè)務(wù)開(kāi)發(fā)效率。可以使用 C++ 做一些工作,只是會(huì)消耗更長(zhǎng)的時(shí)間和更多的資源。在打包的時(shí)候,要先確認(rèn)是否用的是 LZMA 壓縮格式,這種格式可以壓縮得更小一點(diǎn),但是小不了多少,最低可能還是 60 多兆。

至于怎么做守護(hù)進(jìn)程,這個(gè)問(wèn)題現(xiàn)在有兩種辦法,一種是寫(xiě)一個(gè)獨(dú)立的應(yīng)用,在 Electron 啟動(dòng)的時(shí)候應(yīng)用就可以隨之啟動(dòng),然后它守護(hù) Electron 進(jìn)程。如果 Electron 進(jìn)程崩潰的時(shí)候,就由它來(lái)啟動(dòng) Electron 進(jìn)程。

另一種方法是分析應(yīng)用為什么崩潰,是主進(jìn)程崩潰了,還是渲染的時(shí)候崩潰了,你如果主進(jìn)程崩潰了,盡量還是要找到其崩潰的原因,因?yàn)橐坏┲鬟M(jìn)程崩潰,那么所有渲染都會(huì)失敗;如果是渲染進(jìn)程崩潰了,那么可以在主進(jìn)程中打開(kāi)一個(gè)其他的進(jìn)程,來(lái)保證將渲染崩潰的通知發(fā)送給用戶,由用戶重啟渲染進(jìn)程,或者自動(dòng)重啟。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多

    亚洲综合色在线视频香蕉视频| 日本精品免费在线观看| 欧美在线观看视频三区| 欧美激情视频一区二区三区| 亚洲国产日韩欧美三级| 色哟哟在线免费一区二区三区| 日本道播放一区二区三区| 一区二区三区亚洲国产| 亚洲综合伊人五月天中文| 成人午夜激情免费在线| 欧美日韩综合在线精品| 九九热这里只有精品哦 | 91日韩在线视频观看| 日韩欧美三级视频在线| 国产日产欧美精品视频| 国产中文另类天堂二区| 美女被后入福利在线观看| 夫妻性生活动态图视频| 日本加勒比在线观看不卡| 国产精品欧美一区二区三区不卡| 午夜亚洲少妇福利诱惑| 欧洲亚洲精品自拍偷拍| 国产又粗又长又大的视频| 国产午夜福利一区二区| 日本欧美一区二区三区在线播| 熟女乱一区二区三区四区| 午夜日韩在线观看视频| 在线观看欧美视频一区| 91欧美视频在线观看免费| 儿媳妇的诱惑中文字幕| 粉嫩国产美女国产av| 日韩少妇人妻中文字幕| 色哟哟哟在线观看视频| 国产一区二区精品高清免费| 欧美日韩国产的另类视频| 99福利一区二区视频| 国产精品二区三区免费播放心| 日韩高清中文字幕亚洲| 国产精品一区二区高潮| 亚洲黑人精品一区二区欧美| 青青操日老女人的穴穴|