diff --git a/docs/Application_guide/en/media/solutions/Wear/2023-11-24_145207.png b/docs/Application_guide/en/media/solutions/Wear/2023-11-24_145207.png new file mode 100644 index 0000000000000000000000000000000000000000..2713d201247ffbbc6d9737122b4d7d21b7eb222a Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/2023-11-24_145207.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/event-mesh.png b/docs/Application_guide/en/media/solutions/Wear/event-mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..1f064ea6b0f9dd67e0d0c864890aeaacca4e1a80 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/event-mesh.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124092228717.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124092228717.png new file mode 100644 index 0000000000000000000000000000000000000000..828ee31f7509e41ff3e8d1f64c05f5bbf95110b3 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124092228717.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124093958921.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124093958921.png new file mode 100644 index 0000000000000000000000000000000000000000..093426581497eb2eeecd2f169b09d4657b9ee965 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124093958921.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124094455949.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124094455949.png new file mode 100644 index 0000000000000000000000000000000000000000..c77b3f23633ae55ee16a8fe9f485196162c69705 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124094455949.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124095320999.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124095320999.png new file mode 100644 index 0000000000000000000000000000000000000000..4f85c8d16da71bf57b212b0243c83dd246db126b Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124095320999.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124095535783.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124095535783.png new file mode 100644 index 0000000000000000000000000000000000000000..638535cf39500cbe1ff1adbc2951768802827bbd Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124095535783.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124095630554.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124095630554.png new file mode 100644 index 0000000000000000000000000000000000000000..49bbf6997e22f924c30ef331398d953d2f6f59ed Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124095630554.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124095743048.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124095743048.png new file mode 100644 index 0000000000000000000000000000000000000000..cd93973c2a98eb69d16751685b5c51543bd2871d Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124095743048.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124095837758.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124095837758.png new file mode 100644 index 0000000000000000000000000000000000000000..da03352da1565d20d137a06c30985ca64a3d5739 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124095837758.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124112722602.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124112722602.png new file mode 100644 index 0000000000000000000000000000000000000000..f416eb9a1616579573f2a98c7f6f43f09eb4396c Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124112722602.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124113050485.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124113050485.png new file mode 100644 index 0000000000000000000000000000000000000000..da187e6de967ccb08e5882722fafa00dad1c05a0 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124113050485.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124113553528.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124113553528.png new file mode 100644 index 0000000000000000000000000000000000000000..1698cee5977ce66ae3ec87982be39d420df88a44 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124113553528.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124131736253.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124131736253.png new file mode 100644 index 0000000000000000000000000000000000000000..27dab273bc36d8b04b30a28b36dbccc5efeea354 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124131736253.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124133650808.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124133650808.png new file mode 100644 index 0000000000000000000000000000000000000000..35a52d1ab614551e91f8da0f57954c1431881e27 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124133650808.png differ diff --git a/docs/Application_guide/en/media/solutions/Wear/image-20231124140245780.png b/docs/Application_guide/en/media/solutions/Wear/image-20231124140245780.png new file mode 100644 index 0000000000000000000000000000000000000000..c429fda11ff490db02c4cb7a17042389489e3765 Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/image-20231124140245780.png differ diff --git a/docs/Application_guide/en/solutions/Wear/readme.md b/docs/Application_guide/en/solutions/Wear/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..8297490a21a534a4983c97e742d72f16a0391cbf --- /dev/null +++ b/docs/Application_guide/en/solutions/Wear/readme.md @@ -0,0 +1,516 @@ +# Wearable Solution + +[QuecPython](https://python.quectel.com/en) has launched a [GUI solution](https://github.com/QuecPython/solution-wearable.git) for the wearable industry, including clock display, call making/answering, heart rate/temperature/blood oxygen measurement, step count display, system settings and other optional functions. + +![image-20231124092228717](../../media/solutions/Wear/image-20231124092228717.png) + +The wearable industry solution uses [LVGL](https://lvgl.io/) to draw graphical interfaces. LVGL is a lightweight, open source embedded graphics library. QuecPython has integrated LVGL and uses NXP's [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) as a graphical interface design tool to automatically generate QuecPython code, greatly improving the efficiency of embedded platform graphical interface design. + +## Interface Introduction + +The wearable solution provides home page, dial page, application page, standby page, dial page, heart rate/blood oxygen/temperature detection page, settings page and other pages. + +### Dial Page + +!![Show Image](../../media/solutions/Wear/image-20231124093958921.png) + +Components: + +1. **Common Top Bar:** + - Signal display + - Operator display + - Battery level display + - Navigation icon display +2. **Dial Content:** + - Time display: The time is refreshed in real time + - Hour/Minute/Second hand: Updated in real time with the current time + - Background dial showing current time + - Date display: The date is refreshed in real time +3. **Interactions:** + - Swipe left on the digital dial to enter the lock screen, swipe right to enter the analog dial + - Swipe left on the analog dial to enter the digital dial, swipe right to enter the app list 1 + - After 30s of inactivity, the device will enter lock screen. Swipe right to unlock and enter dial + +### Application List Page + +![Show Image](../../media/solutions/Wear/image-20231124094455949.png) + +1. Heart Rate Measurement: + - Tap to enter heart rate measurement page +2. Phone: + - Tap to enter phone dial page +3. Chat: + - Tap to enter chat page to send/receive voice +4. Timer: + - Tap to enter timer page +5. Interactions: + - Swipe right on app list page to enter app list page 2 + - Swipe left on app list page 2 to return to app list page 1, swipe right to enter detection pages + +### Detection Page + +![Show Image](../../media/solutions/Wear/2023-11-24_145207.png) + +The detection page includes body temperature/blood oxygen/heart rate measurement, measurement status and historical measurement display. + +### Phone Page + +![Show Image](../../media/solutions/Wear/image-20231124095320999.png) + +Provides phone dialing, incoming/outgoing call modes and displays. + +### Step Count Page + +![Show Image](../../media/solutions/Wear/image-20231124095630554.png) + +Provides daily step count, historical step count display, and step goal setting display. + +### Timer Page + +![Show Image](../../media/solutions/Wear/image-20231124095535783.png) + +The timer page provides time setting, countdown timer, and alert when timer ends. + +### Alarm Page + +![Show Image](../../media/solutions/Wear/image-20231124095743048.png) + +Provides alarm setting and deletion, alarm alerts and displays. + +### Settings Page + +![Show Image](../../media/solutions/Wear/image-20231124095837758.png) + +1. About Device + - Provides basic system information like manufacturer, model, OS version +2. System Upgrade + - Used to check for system software updates to ensure all features are up-to-date + - May include auto-update options to automatically download and install updates when available +3. Set Watch Face + - Allows switching and displaying different watch faces +4. Device Ringtone + - Set incoming call ringtone + - Set alarm ringtone +5. Vibration Mode + - If device has a vibration motor, vibration mode can be set +6. Factory Reset + - Reset device to factory default settings +7. Power Off + - Send power off command to device + +## Code Introduction + +Code Github Repo: https://github.com/QuecPython/solution-wearable + +### Code Directory Structure + +``` +Copy code. +|-- EventMesh.py +|-- common.py +|-- constant.py +|-- lcd.py +|-- css.py +|-- ui.py +|-- mgr.py +|-- main_t.py +|-- 16px.bin +|-- 28px.bin +|-- 56px.bin +|-- img + |-- point.png + |-- gps.png + |-- bat4.png + |-- ...png +``` + +- `EventMesh.py` is an event management module. When events are triggered on screen controls, users only need to call related interfaces to send events and [EventMesh](https://github.com/QuecPython/EventMesh) will automatically switch screen contents. +- `common.py` mainly provides common abstract base classes and common dependent classes. For example, `class Abstract` provides lifecycle abstractions. +- `constant.py` mainly provides constant configurations. +- `lcd.py` mainly provides LCD driver initialization, TP driver initialization, and LVGL initialization. The screen will only display after successful initialization of this file. +- `css.py` mainly provides css functionalities, static styles, font styles etc for screen objects in `ui.py` to use. +- `ui.py` + - Provides base class `class Screen()` for screen objects, with public methods needed by all screens, like screen creation, status bar info display (operator name, signal strength, system time, battery level etc). + - `class **Screen` implements a class that inherits from `class Screen()`, representing code implementation for each screen's display content. The interface code is mainly automatically generated by the GUI Guider tool, with minor modifications done afterwards, primarily in the object initialization method `__init__()` and control event handler callbacks `__xxx_event_cb()`. Modifications can also be done at various lifecycle stages. +- `mgr.py` mainly provides background functionalities, allowing interfaces to interact with various managers at different lifecycle stages or upon event triggers. +- `main_t.py` is the application entry script file. + - Calls `lcd.py` to initialize screen drivers and display. + - Initializes `APP`, the wearable app. + - Calls `class UI()` in `ui.py` to create the GUI object for the wearable solution, and adds required screen objects to this GUI object's screen object adder, which would execute the page's initialization method during addition. + - Adds managers to `APP` and executes managers' initialization methods. + - Starts `APP`. + - Jumps to main interface. + +### Application Startup Process + +The application startup process is as follows: + +![Show Image](../../media/solutions/Wear/image-20231124140245780.png) + +## Software Design + +### Software Framework Design + +#### Application Design + +The software design framework diagram for the wearable solution is as follows: + +![Show Image](../../media/solutions/Wear/image-20231124112722602.png) + +#### Interface Switching Mechanism + +**EventMesh Event Management Framework** + +As mentioned above, interface switching is driven by the EventMesh event management framework. + +- EventMesh is an application framework based on the publish-subscribe mechanism. Users can subscribe to any topics they are interested in, representing specific events. +- When subscribing to a topic, a callback function needs to be registered to handle the generated event. +- Users can publish the event from anywhere events are triggered, carrying message content. The registered callback functions of subscribers will then be invoked to process the event. + +The EventMesh design framework is shown below: + +![Show Image](../../media/solutions/Wear/event-mesh.png) + +**Interface Switching Principles** + +![Show Image](../../media/solutions/Wear/image-20231124133650808.png) + +Page Template and Lifecycle Example + +```python +pythonCopy code# ui.py + +# Any new class **Screen must inherit from Screen. The lv_obj must be predefined. + +Class DemoScreen(Screen): + # NAME is required, it is used to find the screen when switching + # For example we use EventMesh.publish("load_screen", {"screen": "demo_screen"}) to find this screen + NAME = “demo_screen” + def __init__(self): + super().__init__() + # meta is the core switching object + self.meta = app_list_screen + # prop contains info passed during the jump + # if EventMesh.publish("load_screen", {"screen": "demo_screen", “test”:1}) is called + # then prop = {"screen": "demo_screen", “test”:1} + self.prop = None + + # Called only once when ui.add_screen(DemoScreen()) + # Users can implement initialization here + def post_processor_after_instantiation(self, *args, **kwargs): + """Called after instantiation""" + pass + + # These methods will be called in sequence whenever + # EventMesh.publish("load_screen", {"screen": "demo_screen"}) switches to this screen + # post_processor_before_initialization + # initialization + # post_processor_after_initialization + # Users can implement functionality here, called every time when switching to this screen + def post_processor_before_initialization(self, *args, **kwargs): + """Called before initialization""" + pass + + def initialization(self, *args, **kwargs): + """initialization""" + pass + + + def post_processor_after_initialization(self, *args, **kwargs): + """Called after initialization""" + pass + + # Called when leaving this screen, for example below will + # first call deactivate() before calling main screen init() + def deactivate(self, *args, **kwargs): + """initialize load""" + pass + + +# Note: If the screen is in a tileview, the mapping must be added for switching with +# EventMesh.publish("load_screen", {"screen": "main_screen"}) to work +# See example mapping below in UI class + +class UI(Abstract): + def __init__(self): + self.screens = [] + self.current = None + # display_screen maps to tile at column 0 row 0 + # main_screen maps to tile at column 0 row 1, etc + self.tileview_map = { + "display_screen": [0, 0, lv.ANIM.OFF], + "main_screen": [1, 0, lv.ANIM.OFF], + "watch_face_screen": [2, 0, lv.ANIM.OFF], + "app_list_1_screen": [3, 0, lv.ANIM.OFF], + #... + } + # Reverse mapping of above + self.tileview_position_map = { + (0, 0): "display_screen", + (1, 0): "main_screen", + (2, 0): "watch_face_screen", + #... + } + +# What is tileview? For example, tile1 is at position column 1 row 0, supports left/right slide +tile1 = tileview.add_tile(1, 0, lv.DIR.RIGHT | lv.DIR.LEFT) +# Put main_screen on tile1, swiping left enters tile at (0,0), swiping right enters tile at (2, 0) +main_screen = lv_obj( + parent=tile1, + #... +) +``` + +As can be seen from the above code, the callback implementation for each touch event is similar. + +Taking the application list control touch as an example, the code is: + +```python +# Event handling when app icon clicked +def btn_click(self, event, i): + screen_info = self.profile[i][1] + if screen_info: + # Found click event, switch page + EventMesh.publish("load_screen", screen_info) + +# Render app icons +def post_processor_after_instantiation(self): + for i, btn_profile in enumerate(self.profile): + btn = lv_img( + parent=self.container, + #... + ) + # Add click event to each button + btn.add_event_cb(lambda event, cur=i: self.btn_click(event, cur), lv.EVENT.CLICKED, None) + self.btn_list.append(btn) +``` + +The core statement is `EventMesh.publish("load_screen", screen_info)`, which sends a `"load_screen"` event indicating loading a new screen, carrying the message `screen_info` which contains the name of the screen to switch to, like `"blood_screen"`. + +**UI Startup** + +The `"load_screen"` event is subscribed in the `start()` method of class `AgriUi(object)` in `ui.py`: + +```python +class UI(Abstract): + + def lv_load(self, event, msg): + # Find screen based on name + for screen in self.screens: + if screen.NAME == msg["screen"]: + # Switch logic + + def start(self): + # Subscribe event + EventMesh.subscribe("load_screen", self.lv_load) + # Load first screen + EventMesh.publish("load_screen", {"screen": "main_screen"}) +``` + +The above code starts up the wearable GUI: + +- `add_screen` creates metadata for each screen + +- `EventMesh.subscribe()` subscribes to `"load_screen"`, invoking `lv_load()` when event occurs + + ``` + lv_load() finds the target screen based on name, loads it with lv.scr_load() + ``` + +- First screen loaded with `EventMesh.publish("load_screen", {"screen": "main_screen"})` + +This completes wearable GUI startup, subsequent screen switching is driven by user touch. + +### Graphical Interface Design + +As mentioned before, QuecPython uses NXP's [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) tool for graphical interface design. This tool allows not only interface layout design, but also automatic QuecPython code generation. [Click here for a GUI Guider tutorial](https://python.quectel.com/doc/Application_guide/en/multi-media/lvgl/lvgl_ui_tool.html). + +The following sections demonstrate the graphical interface design process using the wearable solution app as an example. + +#### Layout and Background Setup + +Start by selecting a suitable template and background design for a watch face app. This example starts from a blank template, setting the resolution to 240*280px. + +![Show Image](../../media/solutions/Wear/image-20231124113050485.png) + +#### Interface Drawing + +This section focuses on drawing the main dial page to demonstrate layout and quick code implementation. + +1. Top Bar + +![Show Image](../../media/solutions/Wear/image-20231124113553528.png) + +- **Components:** obj, img, label + +- Operator and Signal (Box 1): + + + + An obj containing an img for signal and label for operator name, left aligned in layout, 4px gap between img and label + + - obj size is specific pixel width * 20px + - img size is 20px * 20px + +- Navigation and Battery (Box 2): + + + + An obj containing a navigation img and battery level img, 8px gap between them, sizes: + + - obj size is 48px * 20px + - img size is 20px * 20px + +- Overall Layout: + + - Flex layout, default horizontal axis + - Size 240px * 34px + - Main axis left-right aligned using space-between + - Children aligned flex-end on cross axis, i.e. bottom + +- Layout padding: top 0px, right 12px, bottom 4px, left 12px + +Implementation: + +```python +pythonCopy code# Styles from css.py + +# Main page +main_screen = lv_obj( + size=(240, 280), + style=[...] +) + +# Top bar +main_top = lv_obj( + parent=main_screen, + size=(240, 34), + flex_flow=lv.FLEX_FLOW.ROW, + flex_align=(lv.FLEX_ALIGN.SPACE_BETWEEN, lv.FLEX_ALIGN.END, lv.FLEX_ALIGN.END), + style=[...] +) + +# Box 1 +main_top_cont_1 = lv_obj( + parent=main_top, + size=(88, 20), + flex_flow=lv.FLEX_FLOW.ROW, + flex_align=(...), + style=[ + # gap set to 4px in style + (style_main_top_cont_1, lv.PART.MAIN | lv.STATE.DEFAULT), + ...] +) + +# Signal img parent is Box 1 +main_top_cont_1_img_signal = lv_img( + parent=main_top_cont_1, + size=(20, 20), + src="U:/media/s4.png", + style[...] +) + +# Operator label parent is Box 1 +main_top_cont_1_label_operator = lv_label( + parent=main_top_cont_1, + size=(64, 19), + text="Operator", + style[...] +) + +# Box 2 +main_top_cont_2 = lv_obj( + parent=main_top, + size=(48, 20), + flex_flow=lv.FLEX_FLOW.ROW, + flex_align=(...), + style[...] +) + +# Navigation img parent is Box 2 +main_top_cont_2_img_gps = lv_img( + parent=main_top_cont_2, + ...) + +# Battery img parent is Box 2 +main_top_cont_2_img_bat = lv_img( + parent=main_top_cont_2, + ...) +``` + +1. Time Section + +![Show Image](../../media/solutions/Wear/image-20231124131736253.png) + +- Time Section + - Size 116px * 200px + - Position: + - top: 64px + - left: 16px +- Hour Hand Section (Box 1) + - Size 118px * 200px + - 2 images + - Each image size 58 * 100px + - Flex layout, horizontal axis +- Minute Hand Section (Box 2) + - 2 images + - Image size 58 * 100px each + - Flex layout, horizontal axis +- Layout: + - Flex layout, vertical axis + +```python +pythonCopy code# ... main_screen + +# Create time section +main_content_cont_1 = lv_obj( + parent=main_screen, + size=(116, 200), + pos=(19, 64), + flex_flow=lv.FLEX_FLOW.COLUMN, + flex_align=(...), + style[...] +) + +# Create Box 1 +main_content_cont_1_hour = lv_obj( + parent=main_content_cont_1, + size=(116, 100), + flex_flow=lv.FLEX_FLOW.ROW, + flex_align=(...), + style[...] +) + +# Hour hand img 1 in Box 1 +main_content_cont_1_hour_0 = lv_img( + parent=main_content_cont_1_hour, + size=(58, 100), + src="U:/media/h0.png", + style[...] +) + +# Hour hand img 2 in Box 1 +main_content_cont_1_hour_1 = lv_img( + ...) + +# Create Box 2 +main_content_cont_1_m = lv_obj( + parent=main_content_cont_1, + # Inherits vertical flex layout from parent + flex_flow=lv.FLEX_FLOW.ROW, + ...) + +# Minute hand img 0 in Box 2 +main_content_cont_1_m_0 = lv_img( + ...) + +# Minute hand img 1 in Box 2 +main_content_cont_1_m_1 = lv_img( + ...) +``` + +When placing elements in GUI Guider, ensure components align to grid and layout appropriately for different screen sizes and resolutions. The design should be clean and minimalist, use appropriate color schemes to make key info prominent yet non-intrusive, interactive elements should provide instant feedback e.g. hover/click change appearance. Test on different devices to ensure usability and performance. + +If the system will be used under various lighting conditions like direct sunlight, adjust contrast and brightness to enhance visibility. Finally, the design should be intuitive for new users to navigate without extensive training, reflecting good user experience (UX) design principles. + +The code generated by GUI tools lacks flexibility and maintainability. It's recommended to refactor as shown above for better encapsulation, simplicity and maintainability. \ No newline at end of file diff --git a/docs/Application_guide/zh/solutions/Wear/readme.md b/docs/Application_guide/zh/solutions/Wear/readme.md index db9c7616037028b0c840603dff0b492f5be03f55..255ce17e887b715df8062656a7e4fb68c70f70ba 100644 --- a/docs/Application_guide/zh/solutions/Wear/readme.md +++ b/docs/Application_guide/zh/solutions/Wear/readme.md @@ -2,13 +2,12 @@ -[QuecPython](https://python.quectel.com/en) 基于穿戴行业推出了一套[GUI 解决方案](https://github.com/QuecPython/solution-wearable.git),包括时钟显示、电话拨打与接听现实、心率/温度/血氧测量、计步显示、系统设置等选型功能。 +[QuecPython](https://python.quectel.com/en) 基于穿戴行业推出了一套[GUI 解决方案](https://github.com/QuecPython/solution-wearable.git),包括时钟显示、电话拨打与接听现实、心率/温度/血氧测量、计步显示、系统设置等选型功能。 ![image-20231124092228717](../../media/solutions/Wear/image-20231124092228717.png) - -穿戴行业方案使用 [LVGL](https://lvgl.io/) 绘制图形化界面,它是一个轻量级的、开源的嵌入式图形库。QuecPython 集成了 LVGL,并且使用 NXP 公司的 [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) 作为图形化界面设计工具,能自动生成 QuecPython 代码,极大提高了嵌入式平台图形化界面设计的效率。 +穿戴行业方案使用 [LVGL](https://lvgl.io/) 绘制图形化界面,它是一个轻量级的、开源的嵌入式图形库。QuecPython 集成了 LVGL,并且使用 NXP 公司的 [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) 作为图形化界面设计工具,能自动生成 QuecPython 代码,极大提高了嵌入式平台图形化界面设计的效率。 @@ -139,7 +138,7 @@ ` ``` -- `EventMesh.py` 是一个事件管理器模块,当屏幕控件上的事件被触发时,用户仅需要调用相关接口发送事件即可,[EventMesh](https://github.com/QuecPython/EventMesh) 会自动进行屏幕内容切换。 +- `EventMesh.py` 是一个事件管理器模块,当屏幕控件上的事件被触发时,用户仅需要调用相关接口发送事件即可,[EventMesh](https://github.com/QuecPython/EventMesh) 会自动进行屏幕内容切换。 - `common.py` 主要提供了公共的抽象基类和公共的依赖类, 例如`class Abstract`他提供了生命周期的抽象等。 - `constant.py`主要提供常量的配置。 - `lcd.py`主要提供LCD的驱动初始化, TP的驱动初始化, 以及LVGL的初始化, 只有当此文件初始化成功屏幕才会有显示。 @@ -451,7 +450,7 @@ class UI(Abstract): ### 图形化界面设计 -上文提到,QuecPython 使用 NXP 公司的 [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) 作为图形化界面设计工具,该工具不仅能够进行界面布局设计,还能自动生成 QuecPython 代码。[点此查看 GUI Guider 工具的使用教程]([LVGL-UI工具 - QuecPython (quectel.com)](https://python.quectel.com/doc/Application_guide/zh/multi-media/lvgl/lvgl_ui_tool.html))。 +上文提到,QuecPython 使用 NXP 公司的 [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) 作为图形化界面设计工具,该工具不仅能够进行界面布局设计,还能自动生成 QuecPython 代码。[点此查看 GUI Guider 工具的使用教程](https://python.quectel.com/doc/Application_guide/zh/multi-media/lvgl/lvgl_ui_tool.html))。 下文以穿戴方案的应用为例,来介绍图形化界面的设计过程。