====== wxPython ====== {{python:wxpython_logo.png?309|wxPython Logo}}\\ 本家: [[https://wxpython.org/|Welcome to wxPython! | wxPython]]\\ ソースコード: \\ ・[[git>wxWidgets/Phoenix|wxWidgets/Phoenix: wxPython's Project Phoenix. A new implementation of wxPython, better, stronger, faster than he was before.]] (wxPython Phoenix 4系)\\ ・[[git>wxWidgets/wxPython-Classic|wxWidgets/wxPython-Classic: This is the repository for "Classic" wxPython. All new development is happening in the Phoenix project at https://github.com/wxWidgets/Phoenix]] (wxPython Classic 3系)\\ リリース: \\ ・[[https://pypi.org/project/wxPython/|wxPython · PyPI]] (wxPython Phoenix 4系)\\ ・[[sf>wxpython/files/wxPython/|wxPython - Browse /wxPython at SourceForge.net]] (wxPython Classic 3系)\\ \\  wxPythonは、wxWidgets C++ クラス ライブラリ(クロス プラットフォーム GUI ライブラリ)の Python 言語向けバインディングである。つまり、Python から wxWidgets を利用できるようにしたものである。\\  wxPython を使い Python でプログラムを記述すると、スクリプト言語で GUI アプリケーションを作成できる。さらに、そのプログラムは Linux や Windows、Mac OS Xで同じように動作する。(Python と wxPython が利用できる様々なプラットフォームで動作する。) ===== インストール ===== **wxPython Phoenix 4**系\\ $ pip install wxpython Collecting wxpython Downloading wxPython-4.1.1-cp39-cp39-win_amd64.whl (18.1 MB) |████████████████████████████████| 18.1 MB 2.2 MB/s Collecting six Downloading six-1.16.0-py2.py3-none-any.whl (11 kB) Collecting pillow Downloading Pillow-8.2.0-cp39-cp39-win_amd64.whl (2.2 MB) |████████████████████████████████| 2.2 MB 3.3 MB/s Collecting numpy; python_version >= "3.0" Downloading numpy-1.20.3-cp39-cp39-win_amd64.whl (13.7 MB) |████████████████████████████████| 13.7 MB 3.3 MB/s Installing collected packages: six, pillow, numpy, wxpython Successfully installed numpy-1.20.3 pillow-8.2.0 six-1.16.0 wxpython-4.1.1 ===== ビルドする場合 ===== ==== wxPython Classic 3系 ==== フォルダ構成を以下のようにする。\\ ^ build_folder ^^ | + ^ wxWidgets ^ | + ^ wxPython-Classic ^ **wxWidgets** をダウンロードする。\\ [[https://github.com/wxWidgets/wxWidgets|GitHub - wxWidgets/wxWidgets: Cross-Platform GUI Library - Report issues here: https://trac.wxwidgets.org/]] より clone する。\\ > git clone --recurse-submodules https://github.com/wxWidgets/wxWidgets.git ※**--recurse-submodules** 無しで clone してしまった場合は以下のコマンドを実行する。\\ > cd wxWidgets > git submodule update --init **v3.0.2** タグをチェックアウトする。\\ > cd wxWidgets > git checkout -f v3.0.2 > git submodule update --init > git status HEAD detached at v3.0.2 nothing to commit, working tree clean **wxPython** をダウンロードする。\\ > git clone https://github.com/wxWidgets/wxPython-Classic.git **wxPy-3.0.2.0** タグをチェックアウトする。\\ > cd wxPython-Classic > git checkout -f wxPy-3.0.2.0 **wxPython** をビルドする。\\ Python 2.7 向けにビルドする場合\\ 予め [[http://aka.ms/vcpython27|Microsoft Visual C++ Compiler Pack for Python 2.7]] のインストールが必要である。\\ > cd wxPython-Classic\wxPython x32 ビルド\\ > "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" x86 Setting environment for using Microsoft Visual Studio 2008 x86 tools. > set CPU=x86 > py -2 build-wxpython.py x64 ビルド\\ > "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" x64 Setting environment for using Microsoft Visual Studio 2008 x64 tools. > set CPU=x64 > py -2 build-wxpython.py ==== wxPython Phoenix 4系 ==== フォルダ構成を以下のようにする。\\ ^ build_folder ^^ | + ^ wxWidgets ^ | + ^ wxPython-Phoenix ^ > git clone https://github.com/wxWidgets/Phoenix.git wxPython-Phoenix > cd wxPython-Phoenix > "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 -vcvars_ver=14.16 ********************************************************************** ** Visual Studio 2019 Developer Command Prompt v16.4.5 ** Copyright (c) 2019 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64' > echo %VCToolsVersion% 14.16.27023 > git submodule update --init --recursive ==== トラブルシューティング ==== === link.EXE : return code '0x458' が発生する場合 === **vcvarsall.bat** の引数 **x86/x64** を適切に指定する。\\ > "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" x86 Setting environment for using Microsoft Visual Studio 2008 x86 tools. or > "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" x64 Setting environment for using Microsoft Visual Studio 2008 x64 tools. === error: Microsoft Visual C++ 9.0 is required. が発生する場合 === 以下のエラーが発生する場合\\ error: Microsoft Visual C++ 9.0 is required. Get it from http://aka.ms/vcpython27 ERROR: failed building wxPython. [[http://aka.ms/vcpython27|Download Microsoft Visual C++ Compiler for Python 2.7 from Official Microsoft Download Center]] より [[https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi|VCForPython27.msi]] をダウンロードする。\\ **VCForPython27.msi** を実行してライセンスに同意してインストールする。\\ 以下のコマンドを実行して Microsoft Visual C++ Compiler Pack for Python 2.7 環境を有効にする。\\ > "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" Setting environment for using Microsoft Visual Studio 2008 x86 tools. === error: Unable to find vcvarsall.bat が発生する場合 === 以下のエラーが発生する場合\\ error: Unable to find vcvarsall.bat ERROR: failed building wxPython. > set VS90COMNTOOLS="%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0" Test\\ > py -2 Python 2.7.17 (v2.7.17:c2f86d86e6, Oct 19 2019, 21:01:17) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from distutils.msvccompiler import get_build_version >>> version = get_build_version() >>> version 9.0 >>> from distutils.msvc9compiler import * >>> find_vcvarsall(version) >>> query_vcvarsall(version, 'x64') Traceback (most recent call last): File "", line 1, in File "C:\Python27\lib\distutils\msvc9compiler.py", line 271, in query_vcvarsall raise DistutilsPlatformError("Unable to find vcvarsall.bat") distutils.errors.DistutilsPlatformError: Unable to find vcvarsall.bat >>> from setuptools import setup >>> from distutils.msvc9compiler import * >>> find_vcvarsall(version) u'C:\\Users\\tomoyan\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\vcvarsall.bat' >>> ^Z ※**setuptools** の **import** により monkey patch が当たり **Visual C++ for Python** が検出される。\\ ==== 参考文献 ==== [[https://wiki.python.org/moin/WindowsCompilers|WindowsCompilers - Python Wiki]]\\ [[https://stackoverflow.com/questions/2817869/error-unable-to-find-vcvarsall-bat|python - error: Unable to find vcvarsall.bat - Stack Overflow]]\\ [[https://docs.python.org/3/c-api/stable.html|Stable Application Binary Interface — Python 3.8.1 documentation]]\\ [[https://stackoverflow.com/questions/9233118/library-abi-compatibility-between-versions-of-visual-studio|c++ - Library ABI compatibility between versions of Visual Studio - Stack Overflow]]\\ ==== distutils.msvccompiler の get_build_version() の実装 (Python 3.8) ==== def get_build_version(): """Return the version of MSVC that was used to build Python. For Python 2.3 and up, the version number is included in sys.version. For earlier versions, assume the compiler is MSVC 6. """ prefix = "MSC v." i = sys.version.find(prefix) if i == -1: return 6 i = i + len(prefix) s, rest = sys.version[i:].split(" ", 1) majorVersion = int(s[:-2]) - 6 if majorVersion >= 13: # v13 was skipped and should be v14 majorVersion += 1 minorVersion = int(s[2:3]) / 10.0 # I don't think paths are affected by minor version in version 6 if majorVersion == 6: minorVersion = 0 if majorVersion >= 6: return majorVersion + minorVersion # else we don't know what version of the compiler this is return None >>> from distutils.msvccompiler import get_build_version >>> version = get_build_version(); version 14.1 >>> import sys >>> sys.version '3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)]' >>> s[:-2] '19' >>> majorVersion = int(s[:-2]) - 6 >>> majorVersion 13 >>> majorVersion += 1 >>> majorVersion 14 >>> s[2:3] '1' >>> minorVersion = int(s[2:3]) / 10.0 >>> minorVersion 0.1 >>> majorVersion + minorVersion 14.1 ==== distutils.msvc9compiler の find_vcvarsall() の実装 (Python 3.8) ==== def find_vcvarsall(version): """Find the vcvarsall.bat file At first it tries to find the productdir of VS 2008 in the registry. If that fails it falls back to the VS90COMNTOOLS env var. """ vsbase = VS_BASE % version try: productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, "productdir") except KeyError: log.debug("Unable to find productdir in registry") productdir = None if not productdir or not os.path.isdir(productdir): toolskey = "VS%0.f0COMNTOOLS" % version toolsdir = os.environ.get(toolskey, None) if toolsdir and os.path.isdir(toolsdir): productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") productdir = os.path.abspath(productdir) if not os.path.isdir(productdir): log.debug("%s is not a valid directory" % productdir) return None else: log.debug("Env var %s is not set or invalid" % toolskey) if not productdir: log.debug("No productdir found") return None vcvarsall = os.path.join(productdir, "vcvarsall.bat") if os.path.isfile(vcvarsall): return vcvarsall log.debug("Unable to find vcvarsall.bat") return None ===== 最小の wxPython アプリケーション ===== ※ UTF-8 で保存すること。\\ ==== wx.Frame サンプル ==== {{:python:wxpython_minimum_app_001.png?276|wxPython minimum app 001}}\\ #!/usr/bin/env python # -*- coding: utf-8 -*- import wx # PyWxHelloFrame クラス(wxFrame から派生) class PyWxHelloFrame(wx.Frame): def __init__(self, *args, **kwds): wx.Frame.__init__(self, *args, **kwds) # Panel 生成 panel = wx.Panel(self, -1) # Panel に [閉じる] ボタンを追加 btnClose = wx.Button(panel, wx.NewIdRef(), u"閉じる") # ボタンの位置を設定 btnClose.SetPosition((100, 35)) # クリックイベントにイベントハンドラをバインド self.Bind(wx.EVT_BUTTON, self.btnClose_Click, btnClose) # [閉じる] ボタンクリック時 def btnClose_Click(self, event): # 閉じる self.Close(True) # PyWxHelloApp クラス(wxApp から派生) class PyWxHelloApp(wx.App): def OnInit(self): # PyWxHelloFrame クラスを生成(タイトル、サイズを指定) mainFrame = PyWxHelloFrame(None, -1, "Hello wxPython!!", size=(290, 100)) # トップウインドウとして設定 self.SetTopWindow(mainFrame) # 表示 mainFrame.Show(True) # 正常終了 return True # メイン処理 def main(): # PyWxHelloApp クラスを生成 app = PyWxHelloApp(False) # メインループを開始 app.MainLoop() # スクリプト起動時にmain()を実行 if __name__ == "__main__": main() サンプルアプリケーションの実行。\\ $ python PyWxHelloMain.py ==== wx.html2.WebView サンプル ==== {{:python:wxpython_minimum_app_002.png?640|wxPython minimum app 002}}\\ #!/usr/bin/env python # -*- coding: utf-8 -*- import wx import wx.html2 # PyWxWebViewDialog (wxDialog ) class PyWxWebViewDialog(wx.Dialog): def __init__(self, *args, **kwds): wx.Dialog.__init__(self, *args, **kwds) # BoxSizer sizer = wx.BoxSizer(wx.VERTICAL) # WebView self.browser = wx.html2.WebView.New(self, backend=wx.html2.WebViewBackendIE) #self.browser = wx.html2.WebView.New(self, backend=wx.html2.WebViewBackendEdge) # BoxSizer WebView sizer.Add(self.browser, 1, wx.EXPAND, 10) # Dialog BoxSizer self.SetSizer(sizer) # Dialog self.SetSize((1024, 700)) # Dialog self.SetMinSize((600,300)) # Dialog self.Center() if __name__ == '__main__': # wxApp app = wx.App() # PyWxWebViewDialog dialog = PyWxWebViewDialog(None, -1) # WebView URL dialog.browser.LoadURL('https://html5test.com/') # Dialog dialog.Show() # app.MainLoop() サンプルアプリケーションの実行。\\ $ python PyWxWebView.py ===== 技術情報 ===== ==== WebView ==== WebView は [[https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/controls/webbrowser-control-overview|WebBrowser コントロール]] で実装されている。\\ [[https://html5test.com/|HTML5test]] 確認すると **Internet Explorer 11.0** 相当であることがわかる。\\ bool wxWebViewIE::Create(wxWindow* parent, wxWindowID id, const wxString& url, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name)) { return false; } m_webBrowser = NULL; m_isBusy = false; m_historyLoadingFromList = false; m_historyEnabled = true; m_historyPosition = -1; m_zoomType = wxWEBVIEW_ZOOM_TYPE_TEXT; FindClear(); if (::CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER, // CLSCTX_INPROC, IID_IWebBrowser2 , (void**)&m_webBrowser) != 0) { wxLogError("Failed to initialize IE, CoCreateInstance returned an error"); return false; } m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE); m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE); m_uiHandler = new DocHostUIHandler(this); m_container = new wxIEContainer(this, IID_IWebBrowser2, m_webBrowser, m_uiHandler); EnableControlFeature(21 /* FEATURE_DISABLE_NAVIGATION_SOUNDS */); LoadURL(url); return true; } ===== 参考文献 ===== [[https://wiki.gnuradio.org/index.php/WxPythonCygwin|WxPythonCygwin - GNU Radio]]\\ [[http://eternalwindows.jp/browser/webbrowser/webbrowser03.html|ホストの実装]]\\ [[https://www.atmarkit.co.jp/ait/articles/1807/04/news017.html|WPFやWindowsフォームでEdgeのWebViewを使うには?[Windows 10 1803以降]:.NET TIPS - @IT]]\\ [[https://github.com/windows-toolkit/WindowsCommunityToolkit|windows-toolkit/WindowsCommunityToolkit: The Windows Community Toolkit is a collection of helper functions, custom controls, and app services. It simplifies and demonstrates common developer tasks building UWP apps for Windows 10. The toolkit is part of the .NET Foundation.]]\\ [[https://www.nuget.org/packages/Microsoft.Web.WebView2|NuGet Gallery | Microsoft.Web.WebView2 0.9.430]]\\ [[https://wiki.python.org/moin/WindowsCompilers#Which_Microsoft_Visual_C.2B-.2B-_compiler_to_use_with_a_specific_Python_version_.3F|WindowsCompilers - Python Wiki]]\\ ==== 付録 ==== [[tw>tomoyan596/status/1403202445094752264|wxPythonのWebViewはIEです😅💦💦💦 vue.jsなんて動きません🤤😇 $ pip install wxpython $ pip freeze wxPython==4.1.1 $ python / Twitter]]\\