1+ import ui
2+ import math
3+
4+ class CalculatorView (ui .View ):
5+ def __init__ (self ):
6+ super ().__init__ () # 添加父类初始化调用
7+ self .name = '计算器'
8+ self .background_color = 'black'
9+ self .display_text = '0'
10+ self .first_operand = None
11+ self .operator = None
12+ self .waiting_for_second_operand = False
13+ self .should_reset_display = False
14+
15+ # 按钮布局和标签 - 存储为实例变量以便 layout() 访问
16+ self .button_specs = [
17+ ('AC' , 0 , 0 , 1 ), ('⌫' , 1 , 0 , 1 ), ('%' , 2 , 0 , 1 ), ('÷' , 3 , 0 , 1 ),
18+ ('7' , 0 , 1 , 1 ), ('8' , 1 , 1 , 1 ), ('9' , 2 , 1 , 1 ), ('×' , 3 , 1 , 1 ),
19+ ('4' , 0 , 2 , 1 ), ('5' , 1 , 2 , 1 ), ('6' , 2 , 2 , 1 ), ('-' , 3 , 2 , 1 ),
20+ ('1' , 0 , 3 , 1 ), ('2' , 1 , 3 , 1 ), ('3' , 2 , 3 , 1 ), ('+' , 3 , 3 , 1 ),
21+ ('0' , 0 , 4 , 2 ), ('.' , 2 , 4 , 1 ), ('=' , 3 , 4 , 1 )
22+ ]
23+
24+ # 创建显示标签
25+ self .display_label = ui .Label ()
26+ self .display_label .text = self .display_text
27+ self .display_label .font = ('<system>' , 40 )
28+ self .display_label .text_color = 'white'
29+ self .display_label .alignment = ui .ALIGN_RIGHT
30+ self .display_label .number_of_lines = 1
31+ self .display_label .flex = 'W'
32+
33+ # 创建按钮
34+ self .buttons = {}
35+ for text , col , row , col_span in self .button_specs :
36+ btn = ui .Button (title = text )
37+ btn .font = ('<system>' , 28 )
38+ btn .background_color = self .get_button_color (text )
39+ btn .tint_color = 'white'
40+ btn .corner_radius = 40
41+ btn .action = self .button_tapped
42+ self .buttons [text ] = btn
43+ self .add_subview (btn )
44+
45+ self .add_subview (self .display_label )
46+
47+ def get_button_color (self , text ):
48+ # 数字和点按钮为深灰色
49+ if text in '0123456789.' :
50+ return (0.2 , 0.2 , 0.2 , 1 ) # 深灰
51+ # 操作符按钮为橙色
52+ elif text in '÷×-+=' :
53+ return (1.0 , 0.6 , 0.0 , 1 ) # 橙色
54+ # 功能按钮为浅灰色
55+ else :
56+ return (0.5 , 0.5 , 0.5 , 1 ) # 浅灰
57+
58+ def layout (self ):
59+ # 设置显示标签位置
60+ display_height = 120
61+ self .display_label .frame = (20 , 40 , self .width - 40 , display_height )
62+
63+ # 设置按钮位置
64+ button_size = 80
65+ button_margin = 10
66+ start_y = display_height + 60
67+
68+ for text , btn in self .buttons .items ():
69+ # 找到按钮在布局中的位置
70+ for spec_text , col , row , col_span in self .button_specs :
71+ if spec_text == text :
72+ x = 20 + col * (button_size + button_margin )
73+ y = start_y + row * (button_size + button_margin )
74+ width = button_size * col_span + button_margin * (col_span - 1 )
75+ btn .frame = (x , y , width , button_size )
76+ break
77+
78+ def button_tapped (self , sender ):
79+ text = sender .title
80+
81+ if text in '0123456789' :
82+ self .input_digit (text )
83+ elif text == '.' :
84+ self .input_decimal ()
85+ elif text in '÷×-+' :
86+ self .set_operation (text )
87+ elif text == '=' :
88+ self .calculate_result ()
89+ elif text == 'AC' :
90+ self .clear_all ()
91+ elif text == '±' :
92+ self .toggle_sign ()
93+ elif text == '⌫' :
94+ self .delete_last ()
95+ elif text == '%' :
96+ self .calculate_percentage ()
97+
98+ def input_digit (self , digit ):
99+ if self .display_text == '0' or self .waiting_for_second_operand or self .should_reset_display :
100+ self .display_text = digit
101+ self .waiting_for_second_operand = False
102+ self .should_reset_display = False
103+ else :
104+ self .display_text += digit
105+
106+ self .update_display ()
107+
108+ def input_decimal (self ):
109+ if self .waiting_for_second_operand or self .should_reset_display :
110+ self .display_text = '0.'
111+ self .waiting_for_second_operand = False
112+ self .should_reset_display = False
113+ elif '.' not in self .display_text :
114+ self .display_text += '.'
115+
116+ self .update_display ()
117+
118+ def set_operation (self , op ):
119+ if self .operator is not None and not self .waiting_for_second_operand :
120+ self .calculate_result ()
121+
122+ try :
123+ self .first_operand = float (self .display_text )
124+ except :
125+ self .first_operand = 0
126+
127+ self .operator = op
128+ self .waiting_for_second_operand = True
129+ self .should_reset_display = True
130+
131+ def calculate_result (self ):
132+ if self .operator is None or self .waiting_for_second_operand :
133+ return
134+
135+ try :
136+ second_operand = float (self .display_text )
137+
138+ if self .operator == '+' :
139+ result = self .first_operand + second_operand
140+ elif self .operator == '-' :
141+ result = self .first_operand - second_operand
142+ elif self .operator == '×' :
143+ result = self .first_operand * second_operand
144+ elif self .operator == '÷' :
145+ if second_operand == 0 :
146+ self .display_text = '错误'
147+ self .update_display ()
148+ self .clear_all ()
149+ return
150+ result = self .first_operand / second_operand
151+
152+ # 处理浮点数精度问题
153+ if result .is_integer ():
154+ self .display_text = str (int (result ))
155+ else :
156+ # 限制小数位数
157+ self .display_text = f'{ result :.10f} ' .rstrip ('0' ).rstrip ('.' )
158+
159+ self .first_operand = result
160+ self .operator = None
161+ self .waiting_for_second_operand = True
162+ self .should_reset_display = True
163+ self .update_display ()
164+
165+ except Exception as e :
166+ self .display_text = '错误'
167+ self .update_display ()
168+ self .clear_all ()
169+
170+ def clear_all (self ):
171+ self .display_text = '0'
172+ self .first_operand = None
173+ self .operator = None
174+ self .waiting_for_second_operand = False
175+ self .should_reset_display = False
176+ self .update_display ()
177+
178+ def toggle_sign (self ):
179+ try :
180+ value = float (self .display_text )
181+ value = - value
182+ if value .is_integer ():
183+ self .display_text = str (int (value ))
184+ else :
185+ self .display_text = str (value )
186+ self .update_display ()
187+ except :
188+ pass
189+
190+ def delete_last (self ):
191+ if self .display_text != '0' and len (self .display_text ) > 1 :
192+ self .display_text = self .display_text [:- 1 ]
193+ elif len (self .display_text ) == 1 :
194+ self .display_text = '0'
195+ self .update_display ()
196+
197+ def calculate_percentage (self ):
198+ try :
199+ value = float (self .display_text )
200+ value = value / 100
201+ if value .is_integer ():
202+ self .display_text = str (int (value ))
203+ else :
204+ self .display_text = str (value )
205+ self .update_display ()
206+ except :
207+ pass
208+
209+ def update_display (self ):
210+ # 限制显示长度
211+ if len (self .display_text ) > 12 :
212+ if '.' in self .display_text :
213+ self1 .display_text = self .display_text [:12 ]
214+ else :
215+ self .display_text = self .display_text [:12 ]
216+
217+ self .display_label .text = self .display_text
218+
219+ # 运行计算器
220+ if __name__ == '__main__' :
221+ view = CalculatorView ()
222+ view .present ('fullscreen' )
0 commit comments