使用相机¶
几乎每一台现代计算机都配备某种类型的摄像头。在本教程中,我们将编写一个新程序,使该程序能够请求访问摄像头、拍摄照片,然后在这个新的应用程序当中显示所拍摄的照片。
本教程并不适用于所有平台!
遗憾的是,目前本教程仅适用于 macOS 系统和 Android。
虽然所有 iPhone 都有摄像头,iOS 虚拟机\ 没有正常工作的摄像头。Windows 与 Linux 设备也有摄像头,但 Toga 目前不提供在这些平台上访问摄像头的能力。
这里展示的代码可以在 Windows 或 Linux 上运行,但是当您尝试照相时,它会报错。
这段代码在 iOS 设备上会正常工作,但部署到 iOS 虚拟器时,它将无法正常拍照。
启动新项目¶
在本教程中,我们不会在核心教程中的应用程序上进行构建,而是要启动一个全新的项目。您可以使用与第一个项目相同的虚拟环境;但我们需要重新运行 "新建公文包 "向导。
返回包含 helloworld 项目文件夹的目录,并启动名为 "Hello Camera "的新项目:
(beeware-venv) $ cd ..
(beeware-venv) $ briefcase new
...
[hellocamera] Generated new application 'Hello Camera'
To run your application, type:
$ cd hellocamera
$ briefcase dev
(beeware-venv) $ cd hellocamera
添加拍摄照片的代码¶
向导已经生成了一个新的空 Toga 项目。现在我们可以添加代码来拍摄并显示照片。编辑新应用程序的 app.py,使其包含以下内容:
import toga
from toga.style.pack import COLUMN, ROW
class HelloCamera(toga.App):
def startup(self):
main_box = toga.Box()
self.photo = toga.ImageView(height=300, margin=5)
camera_button = toga.Button(
"Take photo",
on_press=self.take_photo,
margin=5,
)
main_box.add(self.photo)
main_box.add(camera_button)
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
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:
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",
)
)
def main():
return HelloCamera()
与 Briefcase 生成的默认应用程序相比,这段代码有两处改动。上面突出显示了这些新增内容:
- 第一个突出显示的代码块(在
startup()方法中)添加了控制摄像头所需的两个部件:显示照片的ImageView和触发摄像头的Button。 - 第二个突出显示的代码块("take_photo()
"方法)定义了按下按钮时的事件处理程序。该处理程序首先会确认应用程序是否有拍照权限;如果没有权限,则会请求权限。然后拍摄照片。请求权限和请求拍照都是异步请求,因此需要使用
await;当应用程序等待用户确认权限或拍照时,应用程序的事件循环可以在后台继续。
如果相机成功拍摄了照片,它将返回一个 Image 对象,该对象可被分配为 ImageView
的内容。如果用户取消了拍照请求,self.camera.take_photo()
调用将返回None,结果可以忽略。如果用户未授予使用相机的权限,或当前平台未实现相机,则会引发错误,并向用户显示对话框。
添加设备权限¶
我们刚刚添加的代码中有一部分要求获得使用摄像头的权限。这是现代应用程序平台的一个共同特点–如果不事先明确征求用户许可,就无法访问硬件功能。
不过,这种请求分为两部分。第一部分在我们刚刚看到的代码中;但在应用程序请求权限之前,它需要声明要请求的权限。
每个平台所需的权限略有不同,但 Briefcase 为许多常见硬件权限提供了跨平台表示。在应用程序的 pyproject.toml 文件的
[tool.briefcase.app.hellocamera]配置部分,添加以下内容(就在 sources 声明的上方):
permission.camera = "App will take mugshots."
这将声明您的应用程序需要访问摄像头,并提供一个简短的说明,说明为什么需要使用摄像头。某些平台(尤其是 macOS 和 iOS)需要此说明,并将在权限对话框显示时作为附加信息显示给用户。
我们现在可以生成并运行应用程序:
(beeware-venv) $ briefcase create
(beeware-venv) $ briefcase build
(beeware-venv) $ briefcase run
(beeware-venv) $ briefcase create android
(beeware-venv) $ briefcase build android
(beeware-venv) $ briefcase run android
程序运行时,会出现一个按钮。按下按钮后,平台的默认相机对话框就会显示。拍照后,相机对话框将消失,照片将显示在应用程序中,就在按钮上方。然后,您可以再拍一张照片;这张照片将取代第一张照片。
添加设备权限¶
权限声明在最初调用 briefcase create 时生成的文件中。不幸的是,Briefcase
无法在最初生成这些文件后对其进行更新;因此,如果您想在应用程序中添加新权限或修改现有权限,则需要重新创建应用程序。您可以通过重新运行 briefcase
create 来做到这一点;这将警告您现有的应用程序将被覆盖,然后用新的权限重新生成应用程序。