
跨平台UI组件桌面应用【免费下载链接】togaA Python native, OS native GUI toolkit.项目地址https://gitcode.com/gh_mirrors/to/toga点击查看免费下载本指南围绕仓库中的 hardware 示例应用 及其配套 README系统讲解 Toga 框架如何通过App.camera与App.location两大设备接口完成拍照、权限申请、定位获取、持续跟踪与地图可视化。读完本文你将掌握 Toga 硬件 API 的异步调用模式、平台权限配置Android / iOS / macOS / Linux以及一套可直接复制运行的最小实现方案。示例概览hardware 测试应用examples/hardware是 Toga 官方提供的设备能力测试应用用于验证两个核心硬件 APICamera摄像头检查权限、申请权限、拍摄照片并在ImageView中展示Location定位服务检查/申请前后台权限、获取当前定位、启动/停止持续位置跟踪并通过MapView把定位结果渲染到地图上。应用通过 OptionContainer 将两个功能区组织为 Camera 与 Geo 两个标签页是理解 Toga 硬件 API 最直接、可运行的参考实现。快速开始按 examples/hardware/README.md 给出的方式运行$ python -m pip install toga $ python -m hardwarehardware包的入口在 examples/hardware/hardware/main.py它调用hardware.app.main()并进入main_loop()应用本体则在 examples/hardware/hardware/app.py 中定义def main(): return HardwareApp(Hardware, org.beeware.toga.examples.hardware) if __name__ __main__: main().main_loop()应用名称为 Hardware应用 ID 为org.beeware.toga.examples.hardware与 pyproject.toml 中tool.briefcase的bundle配置一一对应。若要在真实设备尤其是移动平台上打包分发则需使用 Briefcase[build-system] requires [briefcase]而非仅运行源码。应用 UI 结构Camera 页与 Geo 页HardwareApp.startup()在 examples/hardware/hardware/app.py#L6-L93 中完成全部界面搭建Camera 页一个宽度 200 的toga.ImageView用于显示照片下方放置 Take Photo 按钮其on_press绑定self.take_photo。按钮按flex1, margin5布局外层以directionCOLUMN的Box纵向排列照片区域两侧用Box(flex1)实现水平居中。Geo 页一个flex1的MapView占满主要空间下方一行四个按钮Update获取当前定位、Start开始跟踪、Stop停止跟踪、Background申请后台定位权限分别对应update_location、start_location_updates、stop_location_updates、request_background_location四个处理器。主窗口内容为一个OptionContainer包含两个OptionItemCamera 与 Geo。界面搭建遵循 Toga 的盒模型布局travertinoflex、margin、direction等样式参数均可直接用于控制硬件相关页面在桌面与移动端的自适应排布。Camera API拍照与权限管理摄像头通过App.camera属性访问。接口定义位于 core/src/toga/hardware/camera.py核心成员如下成员类型说明has_permission属性是否已获得摄像头使用权限平台要求显式确认而未确认时返回Falserequest_permission()异步申请拍照所需权限已授权则直接返回不会重复弹窗。await后返回booldevices属性可用摄像头设备列表元素为CameraDevicetake_photo(deviceNone, flashFlashMode.AUTO)异步拍照。await后返回toga.Image用户取消时返回None。未授权时抛出PermissionErrorCameraDevice提供id设备唯一标识、name人类可读名称、has_flash是否有闪光灯三个属性并实现了__eq__按id判等与__str__。FlashMode枚举AUTO/ON/OFF定义于toga.constants。示例中的拍照流程examples/hardware/hardware/app.py#L95-L118 展示了标准的三段式流程async def take_photo(self, widget, **kwargs): try: if not self.camera.has_permission: await self.camera.request_permission() image await self.camera.take_photo() if image is None: self.photo.image resources/default.png else: self.photo.image image except NotImplementedError: await self.main_window.dialog( toga.InfoDialog(Oh no!, The Camera API is not implemented on this platform) ) except PermissionError: await self.main_window.dialog( toga.InfoDialog(Oh no!, You have not granted permission to take photos) )要点先查权限再申请权限has_permission为False时调用request_permission()拍照结果是toga.Image直接赋值给ImageView.image即可刷新显示若返回None用户取消回退到默认占位图resources/default.png双重异常兜底平台未实现 Camera 后端时抛NotImplementedError以InfoDialog提示用户用户拒绝授权时抛PermissionError。权限的平台配置要求Toga 只负责在运行时申请权限应用本身必须在打包配置中声明对硬件的使用。官方 Camera 参考文档 明确了各平台要求iOSInfo.plist中必须定义NSCameraUsageDescriptionmacOS需启用com.apple.security.device.camera授权entitlement并在Info.plist中定义NSCameraUsageDescriptionAndroid必须声明android.permission.CAMERA权限。在 Briefcase 的 pyproject.toml 中这些声明由permission.camera键统一描述平台在构建时会自动转换为对应的原生配置详见下文权限声明与 Briefcase 配置。后端实现对照Camera 的接口层interface通过工厂模式调用各平台实现self._impl self.factory.Camera(self)。从源码可以看到Android 后端android/src/toga_android/hardware/camera.py基于camera2与MediaStore.ACTION_IMAGE_CAPTURE。get_devices()通过CameraManager.getCameraIdList()枚举设备并根据LENS_FACING区分 Front/Back/Externaltake_photo()在应用缓存目录的shared子目录创建临时.jpg借助FileProvider生成 URI 交给系统相机 Activity回调中把临时文件包装为toga.Image。iOS 后端iOS/src/toga_iOS/hardware/camera.py基于UIImagePickerController通过AVCaptureDevice.requestAccessForMediaType申请权限take_photo()设置拍摄模式、前后摄像头与闪光灯后以模态方式弹出系统相机界面结果经TogaImagePickerDelegate回调返回。若平台未提供对应后端访问app.camera会抛出NotImplementedError这正是示例中捕获该异常的原因。需要特别说明的是iOS 模拟器虽实现了 Camera API但无法实际拍照要测试拍照功能必须使用真机官方文档明确提示。Location API定位获取与持续跟踪定位服务通过App.location属性访问接口定义位于 core/src/toga/hardware/location.py核心成员如下成员类型说明has_permission属性是否已获得前台定位权限request_permission()异步申请前台应用运行期间定位权限await返回boolhas_background_permission属性是否已获得后台定位权限request_background_permission()异步申请后台定位权限。必须先获得前台权限否则抛PermissionErrorcurrent_location()异步获取当前定位await返回toga.LatLng纬度/经度 NamedTuple见 core/src/toga/types.py#L26-L36on_change属性位置更新时回调的处理器签名见OnLocationChangeHandler协议start_tracking()方法开始持续监听位置变化每次变化触发on_change未授权抛PermissionErrorstop_tracking()方法停止位置监听on_change处理器收到的是关键字参数locationtoga.LatLng与altitude海拔单位米取不到时为Noneasync def location_update(self, location, altitude, **kwargs): print(fYou are now at {location}, with altitude {altitude} meters)示例中的定位流程示例将定位逻辑拆成四个异步处理器Update获取当前定位app.py#L133-L153 先await self.location.request_permission()再await self.location.current_location()得到LatLng后调用_set_location更新地图。未授权时抛出PermissionError未实现时抛出NotImplementedError均以InfoDialog提示。Start / Stop持续跟踪app.py#L155-L193。start_tracking()前先申请权限on_change在startup()中通过self.location.on_change self.location_changed预先绑定。stop_tracking()同样先申请权限再停止。Background后台权限app.py#L195-L233 演示了标准的前后台权限阶梯先检查has_background_permission未获得时依次await request_permission()与await request_background_permission()任一步被拒绝都给出明确提示。location_changed与_set_locationapp.py#L120-L131负责地图联动def location_changed(self, geo, location, altitude, **kwargs): self._set_location(location) def _set_location(self, location): self.map_view.location location if self.pin is None: self.pin toga.MapPin(location, titleHere!) self.map_view.pins.add(self.pin) self.map_view.zoom 16 else: self.pin.location location第一次获得定位时创建MapPin(location, titleHere!)并加入map_view.pins同时把缩放级别设为 16此后每次定位更新只需移动已有 pin 的location。MapPin支持location、title、subtitle属性见 core/src/toga/widgets/mapview.py#L12-L75MapPinSet提供add/remove/clear管理地图标记。缩放级别与地图语义示例中zoom 16对应适合导航的街道级别。MapView.zoom的有效范围为 0–20越界自动裁剪其数学基础与 OpenStreetMap 一致longitude_per_256_pixels 360 / (2**zoom)。大致对应关系0–2 全球、9–11 城市范围、12–14 城区/小镇、15–17 导航级道路、18–19 单体建筑、20 单个建筑。MapView默认中心为澳大利亚珀斯-31.9559, 115.8606。这些细节可在 core/src/toga/widgets/mapview.py#L189-L236 的 docstring 中核实。后台定位的特殊语义request_background_permission()的实现core/src/toga/hardware/location.py#L96-L133直接体现了先前台、后后台的约束若has_permission为假会立即在返回的异步结果中设置PermissionError提示Cannot ask for background location permission before confirming foreground location permission.。需要留意平台差异见官方 Location 参考文档macOS 与 GTK没有后台权限与运行中权限的区分iOS若用户仅授予allow once前台权限后台权限请求会被拒绝Android 8API 34 之前海拔报告的是相对 WGS84 椭球体的高度而非平均海平面MSL高度。Linux 系统依赖GeoClue在 Linux 上使用 GTK 后端的定位功能需要安装 GeoClue2 系统包及其 GObject Introspection 绑定且 GeoClue 服务必须处于启用状态。官方文档给出的常见发行版包名Ubuntu / Debiangir1.2-geoclue-2.0Fedorageoclue2-libsArch / ManjarogeoclueOpenSUSE Tumbleweedgeoclue2 typelib(geoclue2)FreeBSDgeoclue部分发行版如 Ubuntu需要用户显式打开系统定位开关后 GeoClue 才能工作此外Linux 上非沙箱应用没有可靠的权限控制机制沙箱应用如 Flatpak则通过 XDG Portal Location API 获得粗粒度、可按应用关闭的定位权限。后端实现对照Android 后端android/src/toga_android/hardware/location.pyhas_permission同时检查粗/细定位权限ACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATIONcurrent_location()通过LocationManager.getCurrentLocation(FUSED_PROVIDER, ...)单次获取start_tracking()调用requestLocationUpdates注册监听频率限制为每 5 秒或每 10 米触发一次海拔优先取 API 34 引入的 MSL 高度。iOS 后端iOS/src/toga_iOS/hardware/location.py基于CLLocationManagerrequest_permission()调用requestWhenInUseAuthorization()后台权限则要求Info.plist含NSLocationAlwaysAndWhenInUseUsageDescription并调用requestAlwaysAuthorization()start_tracking()会设置allowsBackgroundLocationUpdates与pausesLocationUpdatesAutomatically。注意该实现与 cocoamacOS后端 共用同一套 delegate 回调逻辑。平台相关权限声明映射iOS 需NSLocationWhenInUseUsageDescription后台还需NSLocationAlwaysAndWhenInUseUsageDescription与UIBackgroundModes中的location、processing值macOS 需启用com.apple.security.personal-information.location授权并定义NSLocationUsageDescriptionAndroid 至少声明ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION之一只声明一个会影响定位精度后台跟踪另需ACCESS_BACKGROUND_LOCATION。权限声明与 Briefcase 配置hardware 示例把全部权限声明集中放在 pyproject.toml 的[tool.briefcase.app.hardware]段permission.camera This app demonstrates camera capabilities permission.fine_location This app demonstrates fine-grained geolocation services. permission.coarse_location This app demonstrates coarse-grained geolocation services. permission.background_location This app demonstrates capturing your location while in the background这四个键分别驱动平台生成对应的原生权限声明如 Android 的AndroidManifest.xml权限条目、iOS 的Info.plistusage description 字符串值是面向用户的权限用途说明。同时Android 构建还配置了额外的 Gradle 依赖与主题base_theme Theme.MaterialComponents.Light.DarkActionBar build_gradle_dependencies [ com.google.android.material:material:1.12.0, org.osmdroid:osmdroid-android:6.1.20, ]其中osmdroid是 Android 后端渲染MapView所需的依赖[tool.briefcase.app.hardware.android]段下的requires指向本地android后端源码。各桌面/移动平台的requires也在此处分别指定cocoa / gtk / winforms / iOS / android 后端均以本地相对路径引入。异步模型与源码级原理硬件 API 之所以必须await是因为权限申请、拍照与定位都是耗时且可能被用户中断的操作。其底层是 core/src/toga/handlers.py 中的异步结果机制AsyncResult包装一个asyncio.Future通过set_result()/set_exception()完成或失败并实现__await__使其可直接await任何对结果的直接比较、bool()等都会抛出RuntimeError提示use await or an on_result handler——这从语言层面强制了异步用法PermissionResult与PhotoResult、LocationResult都是AsyncResult的子类request_permission()在已授权时会同步set_result(True)直接完成避免不必要的系统弹窗未授权时把future传给后端实现由原生回调异步填充结果wrapped_handler统一包装on_change这类处理器普通函数同步调用协程自动asyncio.ensure_future挂载到事件循环因此location_changed等回调可以安全地直接操作 UI。定位/摄像头的懒加载同样值得注意App.camera与App.location是属性core/src/toga/app.py#L726-L761首次访问时才实例化Camera(self)/Location(self)并缓存到_camera/_location如果当前平台工厂没有注册对应实现访问会抛出NotImplementedError示例中的except NotImplementedError分支正是为多平台兼容而设计。测试佐证仓库为核心硬件 API 提供了完备的单元测试可用于验证上述行为core/tests/hardware/test_camera.py覆盖权限申请已授权不重复请求、未授权才请求、devices属性与设备相等性按id判等、take_photo在授权/未授权/用户取消三种场景下的行为core/tests/hardware/test_location.py覆盖前台权限申请、后台权限必须先于前台确认否则抛PermissionError、current_location的授权/拒绝分支、start_tracking/stop_tracking生命周期以及on_change处理器收到locationLatLng(16, 30), altitude6这类完整参数。测试基于toga_dummy后端见 dummy/src/toga_dummy通过assert_action_performed等断言验证接口层与实现层的调用关系可作为学习硬件 API 调用时序的补充资料。小结通过 hardware 示例可以完整掌握 Toga 设备能力开发的三条主线权限先行has_permission查询 →request_permission()申请 → 平台打包配置Briefcasepermission.*键 / 原生Info.plist、entitlement、Android 权限兜底声明异步调用所有硬件长耗时操作返回AsyncResult必须在异步处理器中await并对NotImplementedError平台无后端与PermissionError用户拒绝做显式处理前后台定位阶梯前台权限是后台权限的前提on_changestart_tracking()/stop_tracking()构成持续跟踪闭环MapViewMapPin负责可视化。以 examples/hardware/README.md 的快速开始命令为起点结合 app.py、核心接口 camera.py 与 location.py即可快速搭建自己的拍照与定位应用并平滑迁移到 Android、iOS、macOS、Linux、Windows 等多个平台。赞分享跨平台UI组件桌面应用【免费下载链接】togaA Python native, OS native GUI toolkit.项目地址https://gitcode.com/gh_mirrors/to/toga点击查看免费下载相关推荐Capacitor原生API详解设备硬件功能调用实战Capacitor原生API详解设备硬件功能调用实战 引言跨平台开发的硬件访问痛点与解决方案 移动应用开发中硬件功能调用如摄像头、传感器、文件系统等一移动开发跨平台插件系统前端Quasar Capacitor API 使用指南在 Quasar 应用中调用原生设备能力Quasar Capacitor API 使用指南在 Quasar 应用中调用原生设备能力 Quasar Framework 通过 quasar/app前端UI组件跨平台如何快速激活Windows和OfficeKMS_VL_ALL_AIO智能激活完整指南如何快速激活Windows和OfficeKMS_VL_ALL_AIO智能激活完整指南 还在为Windows系统激活而烦恼吗KMS_VL_ALL_AIO智能激跨平台UI组件桌面应用上一篇免费开源36款Cherry MX键帽3D模型5分钟装好你的专属键盘下一篇不想开口又想打字离线唇语转文字工具 Chaplin 让无声输入成为可能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考