smartpi 0.1.23__py3-none-any.whl → 0.1.24__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smartpi/__init__.py +1 -1
- smartpi/gui.py +218 -67
- {smartpi-0.1.23.dist-info → smartpi-0.1.24.dist-info}/METADATA +1 -1
- {smartpi-0.1.23.dist-info → smartpi-0.1.24.dist-info}/RECORD +6 -6
- {smartpi-0.1.23.dist-info → smartpi-0.1.24.dist-info}/WHEEL +0 -0
- {smartpi-0.1.23.dist-info → smartpi-0.1.24.dist-info}/top_level.txt +0 -0
smartpi/__init__.py
CHANGED
smartpi/gui.py
CHANGED
|
@@ -1,87 +1,238 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
可靠触摸屏GUI - 恢复可工作版本
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import tkinter as tk
|
|
7
|
+
from tkinter import font as tkfont
|
|
8
|
+
import os
|
|
9
|
+
import select
|
|
10
|
+
import struct
|
|
11
|
+
import threading
|
|
3
12
|
import time
|
|
4
13
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
14
|
+
# 全局变量
|
|
15
|
+
_root = None
|
|
16
|
+
_canvas = None
|
|
17
|
+
_fonts = {}
|
|
18
|
+
_touch_x = 0
|
|
19
|
+
_touch_y = 0
|
|
20
|
+
_touch_pressed = False
|
|
21
|
+
_x_cache = 0
|
|
22
|
+
_y_cache = 0
|
|
23
|
+
_exit_triggered = False
|
|
24
|
+
|
|
25
|
+
def _create_fonts():
|
|
26
|
+
"""创建字体"""
|
|
27
|
+
global _fonts
|
|
28
|
+
_fonts[16] = tkfont.Font(family="Arial", size=16)
|
|
29
|
+
_fonts[24] = tkfont.Font(family="Arial", size=24)
|
|
30
|
+
_fonts[32] = tkfont.Font(family="Arial", size=32)
|
|
31
|
+
_fonts[40] = tkfont.Font(family="Arial", size=40)
|
|
32
|
+
_fonts[48] = tkfont.Font(family="Arial", size=48)
|
|
33
|
+
|
|
34
|
+
def _read_touch_events():
|
|
35
|
+
"""可靠的触摸事件读取 - 使用之前验证过的方法"""
|
|
36
|
+
global _touch_x, _touch_y, _touch_pressed, _x_cache, _y_cache
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
# 打开输入设备
|
|
40
|
+
fd = os.open('/dev/input/event2', os.O_RDONLY | os.O_NONBLOCK)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
print(f"无法打开设备: {e}")
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
# input_event结构体格式
|
|
46
|
+
EVENT_FORMAT = 'llHHI'
|
|
47
|
+
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)
|
|
48
|
+
|
|
49
|
+
# 事件类型定义
|
|
50
|
+
EV_SYN = 0x00
|
|
51
|
+
EV_ABS = 0x03
|
|
52
|
+
|
|
53
|
+
# 绝对轴定义
|
|
54
|
+
ABS_MT_POSITION_X = 0x35
|
|
55
|
+
ABS_MT_POSITION_Y = 0x36
|
|
56
|
+
ABS_MT_TRACKING_ID = 0x39
|
|
57
|
+
|
|
58
|
+
# 持续读取触摸事件
|
|
59
|
+
while not _exit_triggered:
|
|
60
|
+
try:
|
|
61
|
+
# 使用select等待数据可读
|
|
62
|
+
r, w, e = select.select([fd], [], [], 0.1)
|
|
63
|
+
|
|
64
|
+
if fd in r:
|
|
65
|
+
data = os.read(fd, EVENT_SIZE * 10)
|
|
66
|
+
data_len = len(data)
|
|
67
|
+
pos = 0
|
|
68
|
+
|
|
69
|
+
while pos + EVENT_SIZE <= data_len:
|
|
70
|
+
# 解析事件
|
|
71
|
+
tv_sec, tv_usec, etype, code, value = struct.unpack(EVENT_FORMAT, data[pos:pos+EVENT_SIZE])
|
|
72
|
+
pos += EVENT_SIZE
|
|
73
|
+
|
|
74
|
+
if etype == EV_ABS:
|
|
75
|
+
if code == ABS_MT_POSITION_X:
|
|
76
|
+
_x_cache = value
|
|
77
|
+
_touch_x = value
|
|
78
|
+
elif code == ABS_MT_POSITION_Y:
|
|
79
|
+
_y_cache = value
|
|
80
|
+
_touch_y = value
|
|
81
|
+
elif code == ABS_MT_TRACKING_ID:
|
|
82
|
+
if value >= 0:
|
|
83
|
+
_touch_pressed = True
|
|
84
|
+
_touch_x = _x_cache
|
|
85
|
+
_touch_y = _y_cache
|
|
86
|
+
else:
|
|
87
|
+
_touch_pressed = False
|
|
88
|
+
|
|
89
|
+
# 同步事件
|
|
90
|
+
elif etype == EV_SYN:
|
|
91
|
+
if _touch_pressed:
|
|
92
|
+
_touch_x = _x_cache
|
|
93
|
+
_touch_y = _y_cache
|
|
94
|
+
|
|
95
|
+
except BlockingIOError:
|
|
96
|
+
pass
|
|
97
|
+
except OSError as e:
|
|
98
|
+
if e.errno != 11: # 忽略EAGAIN错误
|
|
99
|
+
print(f"读取错误: {e}")
|
|
100
|
+
break
|
|
101
|
+
except Exception as e:
|
|
102
|
+
print(f"触摸读取异常: {e}")
|
|
103
|
+
break
|
|
40
104
|
|
|
41
|
-
|
|
42
|
-
|
|
105
|
+
# 关闭设备
|
|
106
|
+
os.close(fd)
|
|
43
107
|
|
|
44
|
-
|
|
45
|
-
|
|
108
|
+
def _run_gui():
|
|
109
|
+
"""运行GUI主循环"""
|
|
110
|
+
global _root, _canvas
|
|
111
|
+
|
|
112
|
+
# 创建GUI
|
|
113
|
+
_root = tk.Tk()
|
|
114
|
+
_root.title("Touch GUI")
|
|
115
|
+
_root.geometry("480x800")
|
|
116
|
+
_root.attributes('-fullscreen', True)
|
|
117
|
+
|
|
118
|
+
_canvas = tk.Canvas(_root, width=480, height=800, bg="white")
|
|
119
|
+
_canvas.pack(fill=tk.BOTH, expand=True)
|
|
120
|
+
|
|
121
|
+
_create_fonts()
|
|
122
|
+
|
|
123
|
+
# 定期检查退出按钮点击
|
|
124
|
+
def check_exit_periodically():
|
|
125
|
+
if _exit_triggered:
|
|
126
|
+
_root.quit()
|
|
127
|
+
return
|
|
128
|
+
_root.after(100, check_exit_periodically)
|
|
129
|
+
|
|
130
|
+
check_exit_periodically()
|
|
131
|
+
|
|
132
|
+
# 启动主循环
|
|
133
|
+
_root.mainloop()
|
|
134
|
+
|
|
135
|
+
def init():
|
|
136
|
+
"""初始化GUI"""
|
|
137
|
+
# 启动GUI线程
|
|
138
|
+
gui_thread = threading.Thread(target=_run_gui, daemon=True)
|
|
139
|
+
gui_thread.start()
|
|
140
|
+
|
|
141
|
+
# 启动触摸事件读取线程
|
|
142
|
+
touch_thread = threading.Thread(target=_read_touch_events, daemon=True)
|
|
143
|
+
touch_thread.start()
|
|
144
|
+
|
|
145
|
+
# 等待GUI初始化完成
|
|
146
|
+
time.sleep(0.2)
|
|
46
147
|
|
|
47
|
-
# 创建全局实例
|
|
48
|
-
_client_instance = _gui_client()
|
|
49
148
|
|
|
50
|
-
#
|
|
149
|
+
# 公共接口函数
|
|
51
150
|
def show_text(x, y, text, color="black", size=16):
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
_client_instance.print(text)
|
|
56
|
-
|
|
57
|
-
def println(text):
|
|
58
|
-
_client_instance.println(text)
|
|
59
|
-
|
|
60
|
-
def show_image(x, y, path, width, height):
|
|
61
|
-
_client_instance.show_image(x, y, path, width, height)
|
|
151
|
+
if _canvas and _fonts:
|
|
152
|
+
font = _fonts.get(size, _fonts[16])
|
|
153
|
+
_root.after(0, lambda: _canvas.create_text(x, y, text=text, fill=color, font=font, anchor="nw"))
|
|
62
154
|
|
|
63
155
|
def draw_line(x1, y1, x2, y2, color="black", width=1):
|
|
64
|
-
|
|
156
|
+
if _canvas:
|
|
157
|
+
_root.after(0, lambda: _canvas.create_line(x1, y1, x2, y2, fill=color, width=width))
|
|
65
158
|
|
|
66
159
|
def fill_rect(x, y, w, h, color="black"):
|
|
67
|
-
|
|
68
|
-
|
|
160
|
+
if _canvas:
|
|
161
|
+
_root.after(0, lambda: _canvas.create_rectangle(x, y, x+w, y+h, fill=color, outline=""))
|
|
162
|
+
|
|
69
163
|
def draw_rect(x, y, w, h, width, color="black"):
|
|
70
|
-
|
|
164
|
+
if _canvas:
|
|
165
|
+
_root.after(0, lambda: _canvas.create_rectangle(x, y, x+w, y+h, width=width, outline=color))
|
|
71
166
|
|
|
72
167
|
def fill_circle(cx, cy, r, color="black"):
|
|
73
|
-
|
|
168
|
+
if _canvas:
|
|
169
|
+
_root.after(0, lambda: _canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill=color, outline=""))
|
|
74
170
|
|
|
75
171
|
def draw_circle(cx, cy, r, width, color="black"):
|
|
76
|
-
|
|
172
|
+
if _canvas:
|
|
173
|
+
_root.after(0, lambda: _canvas.create_oval(cx-r, cy-r, cx+r, cy+r, width=width, outline=color))
|
|
174
|
+
|
|
175
|
+
def fill_polygon(points, color):
|
|
176
|
+
"""填充多边形"""
|
|
177
|
+
if _canvas:
|
|
178
|
+
_root.after(0, lambda: _canvas.create_polygon(points, fill=color, outline=""))
|
|
77
179
|
|
|
78
180
|
def clear():
|
|
79
|
-
|
|
181
|
+
if _canvas:
|
|
182
|
+
_root.after(0, lambda: _canvas.delete("all"))
|
|
183
|
+
|
|
184
|
+
def get_touch_x():
|
|
185
|
+
return _touch_x
|
|
186
|
+
|
|
187
|
+
def get_touch_y():
|
|
188
|
+
return _touch_y
|
|
80
189
|
|
|
81
|
-
def
|
|
82
|
-
|
|
190
|
+
def get_touchscreen():
|
|
191
|
+
return _touch_pressed
|
|
83
192
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return
|
|
87
|
-
|
|
193
|
+
def should_exit():
|
|
194
|
+
"""检查是否应该退出程序"""
|
|
195
|
+
return _exit_triggered
|
|
196
|
+
|
|
197
|
+
def draw_exit_button():
|
|
198
|
+
"""绘制退出按钮"""
|
|
199
|
+
if not _canvas:
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
# 退出按钮位置 - 底部中间
|
|
203
|
+
button_width = 100
|
|
204
|
+
button_height = 80
|
|
205
|
+
x1 = 480//2 - button_width//2
|
|
206
|
+
y1 = 800 - button_height - 20
|
|
207
|
+
x2 = 480//2 + button_width//2
|
|
208
|
+
y2 = 800 - 20
|
|
209
|
+
|
|
210
|
+
# 绘制朝向左边的蓝色三角形
|
|
211
|
+
triangle_size = 50
|
|
212
|
+
center_x = (x1 + x2) // 2
|
|
213
|
+
center_y = (y1 + y2) // 2
|
|
214
|
+
|
|
215
|
+
# 三角形顶点坐标 - 朝向左边的三角形
|
|
216
|
+
points = [
|
|
217
|
+
center_x - triangle_size//2, center_y, # 左顶点
|
|
218
|
+
center_x + triangle_size//2, center_y - triangle_size//2, # 右上顶点
|
|
219
|
+
center_x + triangle_size//2, center_y + triangle_size//2 # 右下顶点
|
|
220
|
+
]
|
|
221
|
+
|
|
222
|
+
_root.after(0, lambda: _canvas.create_polygon(points, fill="blue", outline=""))
|
|
223
|
+
|
|
224
|
+
def check_exit_button(x, y):
|
|
225
|
+
"""检查是否点击了退出按钮"""
|
|
226
|
+
# 退出按钮位置 - 底部中间
|
|
227
|
+
button_width = 100
|
|
228
|
+
button_height = 80
|
|
229
|
+
x1 = 480//2 - button_width//2
|
|
230
|
+
y1 = 800 - button_height - 20
|
|
231
|
+
x2 = 480//2 + button_width//2
|
|
232
|
+
y2 = 800 - 20
|
|
233
|
+
|
|
234
|
+
if x1 <= x <= x2 and y1 <= y <= y2:
|
|
235
|
+
global _exit_triggered
|
|
236
|
+
_exit_triggered = True
|
|
237
|
+
return True
|
|
238
|
+
return False
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
smartpi/__init__.py,sha256=
|
|
1
|
+
smartpi/__init__.py,sha256=mtkDm-FlobRiZdbqGbS77ZzAwe5A9DRGKwIoWdhN2U4,55
|
|
2
2
|
smartpi/base_driver.py,sha256=jP8cuQ0LRfjMuVQ2I6tY7fxp3JsjcUH8fdWKooIogME,24188
|
|
3
3
|
smartpi/color_sensor.py,sha256=YXJjknYjp7teTZsHYZRAWgi73CH0MhBp1go9y0Inxyo,498
|
|
4
4
|
smartpi/cw2015.py,sha256=1lAF-pi_ye_ya1AZQS1sjbgsDf7MThO5IAskKsNGBzA,5695
|
|
5
5
|
smartpi/flash.py,sha256=-pUqg6FSVoBiLFKqrG9B4dFqn8lICnQsSPJr_MtZLIU,4132
|
|
6
|
-
smartpi/gui.py,sha256=
|
|
6
|
+
smartpi/gui.py,sha256=nUFfU-jbDMOHIqZOyiy-7bwO0gMTJllscjnTLyoPYsk,7228
|
|
7
7
|
smartpi/humidity.py,sha256=nZwiBtMWKNipVM83ymajZACPHxkC2vUJjDMmCOPN9lw,499
|
|
8
8
|
smartpi/led.py,sha256=flvN7EJfP6VDTSiC93w1uR8pRxcZD9w2vLXA1GbJTo8,538
|
|
9
9
|
smartpi/light_sensor.py,sha256=MayyVikWcXQfjeZrtYRnwYgHBDzu2g-mfJLpdd29EG8,1852
|
|
@@ -14,7 +14,7 @@ smartpi/temperature.py,sha256=VT79CYA41q1d_4AM-Y0eIMeIw7AtCkSXjWVws6Yx5yE,462
|
|
|
14
14
|
smartpi/touch_sensor.py,sha256=P57RRQlqY0KexpMi-ydqwF5albOKCBOGb0Rb6zeVTqk,440
|
|
15
15
|
smartpi/trace.py,sha256=tut7BMbq87ShaR5eNuv7PZtAEz9DS5_BDf0_muIZ-tQ,4577
|
|
16
16
|
smartpi/ultrasonic.py,sha256=kmVpUfvE1oHoqgv92ZU6Fi-sO6DSwm10ssKsImNeOkY,624
|
|
17
|
-
smartpi-0.1.
|
|
18
|
-
smartpi-0.1.
|
|
19
|
-
smartpi-0.1.
|
|
20
|
-
smartpi-0.1.
|
|
17
|
+
smartpi-0.1.24.dist-info/METADATA,sha256=EQIoqPSL55ic97bXSlKHbMhQYTH37iI-k9tCJHCJPXc,311
|
|
18
|
+
smartpi-0.1.24.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
19
|
+
smartpi-0.1.24.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
|
|
20
|
+
smartpi-0.1.24.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|