为组态王编写的 时间段 选择 控件 python

发布时间 2023-07-04 20:11:12作者: 急先锋小米

日历控件使用说明

这是一个专门为组态软件(如组态王, 力控等)设计的时间选择控件,用于选择一个时间段,来进行数据报表的查询.

控件实际由2部分组成,1UI程序,1modbus TCP从机服务器.从机服务器用于UI程序和组态软件的通信.

 

 日期部分, 时间间隔 部分, 支持滚轮 改变日期, 改变时间间隔

Modbus TCP 从机服务器

地址: 127.0.0.1

端口: 9527

地址

数据类型

名称

功能

40001

Int/RW

启动画面

当赋值1,启动UI画面

40002

-

 

 

40003-40004

Long/R

起始时间

1970/01/01 8:00起经过的秒

40005-40006

Long/R

结束时间

同上

40007-40008

Long/R

查询间隔

定义每条查询记录间的时间间隔

40009

Int/R

起始-

 

40010

Int/R

起始-

 

40011

Int/R

起始-

 

40012

Int/R

起始-

 

40013

Int/R

起始-

 

40014

Int/R

结束-

 

40015

Int/R

结束-

 

40016

Int/R

结束-

 

40017

Int/R

结束-

 

40018

Int/R

结束-

 

 

使用时, 应在启动上位机画面时,运行该程序.连接modbusTCP 从机服务器,并组态变量.当需要选择时间段时,400011,则启动选择画面.从其他地址读取选择的结果.

 上代码

  1 import tkinter as tk
  2 import tkinter.font as tkFont
  3 from datetime import date, timedelta, datetime, time
  4 import sys
  5 import modbus_tk
  6 import modbus_tk.defines as cst
  7 from modbus_tk import modbus_tcp
  8 from time import sleep
  9 
 10 
 11 class 日历控件():
 12     def __init__(self, 通讯器):
 13         self.通讯器 = 通讯器
 14         self.起始时间文本 = ''
 15         self.间隔1天 = timedelta(days=1)
 16         self.间隔1周 = timedelta(days=7)
 17         self.间隔1月 = timedelta(days=30)
 18         self.间隔1年 = timedelta(days=365)
 19         self.间隔9天 = timedelta(days=9)
 20         self.时间区尾 = date.today()
 21         self.时间区头 = self.时间区尾 - self.间隔9天
 22         self.中文周 = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日']
 23         self.选中的起始时间 = None
 24         self.选中的结束时间 = None
 25         self.时间间隔 = 1
 26         self.日期标签列表 = []
 27         self.时间区列表 = []
 28         self.时间位总列表 = []
 29         self.日期列表 = []
 30         self.跟随指针文本 = ''
 31         self.跟随指针控件 = None
 32         self.当前指针对应时间点位ID = -1
 33         self.主窗口 = tk.Tk()
 34         self.绘制窗口()
 35 
 36     def 绘制窗口(self):
 37         self.主窗口.title('查询时间选择')
 38         self.主窗口.geometry('1300x345+20+20')
 39         self.主框架 = tk.Frame(self.主窗口)
 40         self.主框架.pack()
 41         tk.Label(self.主框架, text='请选择查询的时间范围,时间间隔', font=('黑体', 30)).grid(row=0, column=0)
 42         self.cv = tk.Canvas(self.主框架, background='white', width=1300, height=260)
 43         self.cv.grid(row=2, column=0)
 44         self.cv.bind('<Motion>', self.move_handler)
 45         # self.cv.bind('<Button-1>', self.click_handler)
 46         self.cv.bind('<Enter>', self.enter_handler)
 47         self.cv.bind('<Leave>', self.leave_handler)
 48         self.cv.bind('<Button-1>', self.click_handler)
 49         self.cv.bind('<MouseWheel>', self.mwheel_handler)
 50         # 绘制日期区
 51         日期区坐标 = (10, 40)
 52         for j in range(0, 10):
 53             当前行日期 = self.时间区头 + timedelta(days=j)
 54             self.日期列表.append(当前行日期)
 55             日期标签 = self.cv.create_text(日期区坐标[0], 日期区坐标[1] + 20 * j,
 56                                        anchor=tk.W,
 57                                        justify=tk.LEFT,
 58                                        text=当前行日期.isoformat() + self.中文周[当前行日期.isoweekday()])
 59             self.日期标签列表.append(日期标签)
 60             # 根据ID设置元件属性
 61             # self.cv.itemconfigure(日期标签, fill='red')
 62             # 根据ID取属性
 63             # print(self.cv.itemcget(日期标签, 'text'))
 64         # 绘制时间点阵
 65         时间点阵区坐标 = (120, 30)
 66         for j in range(0, 10):
 67             当前行时间点位矩形列表 = []
 68             self.时间位总列表.append(当前行时间点位矩形列表)
 69             for i in range(0, 144):
 70                 当前时间点位矩形 = self.cv.create_rectangle(时间点阵区坐标[0] + i * 8, 时间点阵区坐标[1] + j * 20,
 71                                                     时间点阵区坐标[0] + i * 8 + 8, 时间点阵区坐标[1] + j * 20 + 20)
 72                 当前行时间点位矩形列表.append(当前时间点位矩形)
 73                 self.cv.itemconfigure(当前时间点位矩形, outline='#C0C0C0')
 74         # 绘制日期变更按钮
 75         日期减按钮区坐标 = (10, 5)
 76         日期变动按钮尺寸 = (25, 20)
 77         日期减按钮文本列表 = ['-日', '-周', '-月', '-年']
 78         for i in range(0, 4):
 79             self.cv.create_rectangle(日期减按钮区坐标[0] + i * 日期变动按钮尺寸[0], 日期减按钮区坐标[1],
 80                                      日期减按钮区坐标[0] + i * 日期变动按钮尺寸[0] + 日期变动按钮尺寸[0], 日期减按钮区坐标[1] + 日期变动按钮尺寸[1])
 81             self.cv.create_text(日期减按钮区坐标[0] + i * 日期变动按钮尺寸[0] + 2, 日期减按钮区坐标[1] + 3,
 82                                 anchor=tk.NW,
 83                                 justify=tk.LEFT,
 84                                 text=日期减按钮文本列表[i])
 85         日期加按钮区坐标 = (10, 235)
 86         日期加按钮文本列表 = ['+日', '+周', '+月', '+年']
 87         for i in range(0, 4):
 88             self.cv.create_rectangle(日期加按钮区坐标[0] + i * 日期变动按钮尺寸[0], 日期加按钮区坐标[1],
 89                                      日期加按钮区坐标[0] + i * 日期变动按钮尺寸[0] + 日期变动按钮尺寸[0], 日期加按钮区坐标[1] + 日期变动按钮尺寸[1])
 90             self.cv.create_text(日期加按钮区坐标[0] + i * 日期变动按钮尺寸[0] + 2, 日期加按钮区坐标[1] + 3,
 91                                 anchor=tk.NW,
 92                                 justify=tk.LEFT,
 93                                 text=日期加按钮文本列表[i])
 94         # 绘制时间标尺
 95         for i in range(0, 23):
 96             self.cv.create_line(时间点阵区坐标[0] + (i + 1) * 8 * 6, 时间点阵区坐标[1],
 97                                 时间点阵区坐标[0] + (i + 1) * 8 * 6, 时间点阵区坐标[1] + 20 * 10)
 98         for i in range(0, 24):
 99             self.cv.create_text(时间点阵区坐标[0] + i * 8 * 6 + 24, 15,
100                                 anchor=tk.N,
101                                 justify=tk.LEFT,
102                                 text='%02d' % i)
103         # 绘制 选择结果描述标签
104         self.选择结果描述标签 = self.cv.create_text(150, 235,
105                                             anchor=tk.NW,
106                                             justify=tk.LEFT,
107                                             text='---',
108                                             font=tkFont.Font(family='黑体', size=18))
109         # 时间间隔选择区
110         self.时间间隔选择区 = tk.Frame(self.主框架)
111         self.时间间隔选择区.grid(row=3, column=0, sticky='w')
112         self.时间间隔描述标签 = tk.Label(self.时间间隔选择区, text='时间间隔为: %d 分钟' % self.时间间隔, font=('宋体', 20))
113         self.时间间隔描述标签.grid(row=0, column=0)
114         self.时间间隔描述标签.bind('<MouseWheel>', self.时间间隔描述标签滚动响应())
115         self.设置为1分 = tk.Button(self.时间间隔选择区, text='1分')
116         self.设置为1分.grid(row=0, column=1)
117         self.设置为5分 = tk.Button(self.时间间隔选择区, text='5分')
118         self.设置为5分.grid(row=0, column=2)
119         self.设置为10分 = tk.Button(self.时间间隔选择区, text='10分')
120         self.设置为10分.grid(row=0, column=3)
121         self.设置为30分 = tk.Button(self.时间间隔选择区, text='30分')
122         self.设置为30分.grid(row=0, column=4)
123         self.设置为60分 = tk.Button(self.时间间隔选择区, text='60分')
124         self.设置为60分.grid(row=0, column=5)
125         self.设置加1分 = tk.Button(self.时间间隔选择区, text='+1分')
126         self.设置加1分.grid(row=0, column=6, padx=(30, 0))
127         self.设置减1分 = tk.Button(self.时间间隔选择区, text='-1分')
128         self.设置减1分.grid(row=0, column=7)
129         self.设置加10分 = tk.Button(self.时间间隔选择区, text='+10分')
130         self.设置加10分.grid(row=0, column=8, padx=(30, 0))
131         self.设置减10分 = tk.Button(self.时间间隔选择区, text='-10分')
132         self.设置减10分.grid(row=0, column=9)
133         self.设置加60分 = tk.Button(self.时间间隔选择区, text='+60分')
134         self.设置加60分.grid(row=0, column=10, padx=(30, 0))
135         self.设置减60分 = tk.Button(self.时间间隔选择区, text='-60分')
136         self.设置减60分.grid(row=0, column=11)
137         self.设置为1分.bind('<Button-1>', self.设置时间间隔(1))
138         self.设置为5分.bind('<Button-1>', self.设置时间间隔(5))
139         self.设置为10分.bind('<Button-1>', self.设置时间间隔(10))
140         self.设置为30分.bind('<Button-1>', self.设置时间间隔(30))
141         self.设置为60分.bind('<Button-1>', self.设置时间间隔(60))
142         self.设置加1分.bind('<Button-1>', self.改变时间间隔(1))
143         self.设置加10分.bind('<Button-1>', self.改变时间间隔(10))
144         self.设置加60分.bind('<Button-1>', self.改变时间间隔(60))
145         self.设置减1分.bind('<Button-1>', self.改变时间间隔(-1))
146         self.设置减10分.bind('<Button-1>', self.改变时间间隔(-10))
147         self.设置减60分.bind('<Button-1>', self.改变时间间隔(-60))
148         self.确定按钮 = tk.Button(self.时间间隔选择区, text='确定')
149         self.确定按钮.grid(row=0, column=12, padx=(50, 0))
150         self.确定按钮.bind('<Button-1>', self.ok_action)
151 
152     def move_handler(self, event):
153         # self.跟随指针文本 = '当前坐标 %s , %s ' % (event.x, event.y)
154         # print(type(event.x))
155         # print(int(event.type))
156         时间点阵区坐标 = (120, 30)
157         点位ID = self.坐标转点位ID(event.x, event.y)
158         if 点位ID != -1 and 点位ID != self.当前指针对应时间点位ID:
159 
160             行列 = self.坐标点位转行列(event.x, event.y)
161             row = 行列[0]
162             column = 行列[1]
163             self.cv.coords(self.跟随指针控件,
164                            时间点阵区坐标[0] + column * 8 + 40,
165                            时间点阵区坐标[1] + row * 20 - 10)
166             小时 = column // 6
167             分钟 = column % 6 * 10
168             # print(self.日期标签列表[row]['text'])
169             self.跟随指针文本 = str(self.日期列表[row].day) + '日%02d:%02d' % (小时, 分钟)
170             self.cv.itemconfigure(self.跟随指针控件, text=self.跟随指针文本)
171 
172             self.当前指针对应时间点位ID = 点位ID
173             for 点位行 in self.时间位总列表:
174                 for 点位 in 点位行:
175                     if 点位 == 点位ID:
176                         self.cv.itemconfigure(点位, width=3, outline='#0000FF')
177                     else:
178                         self.cv.itemconfigure(点位, width=1, outline='#C0C0C0')
179         # 在滚动时触发
180         if int(event.type) == 38:
181             # print('滚动引发')
182             if 点位ID != -1:
183                 行列 = self.坐标点位转行列(event.x, event.y)
184             else:
185                 行列 = self.ID转转行列(self.当前指针对应时间点位ID)
186             row = 行列[0]
187             column = 行列[1]
188             self.cv.coords(self.跟随指针控件,
189                            时间点阵区坐标[0] + column * 8 + 40,
190                            时间点阵区坐标[1] + row * 20 - 10)
191             小时 = column // 6
192             分钟 = column % 6 * 10
193             self.跟随指针文本 = str(self.日期列表[row].day) + '日%02d:%02d' % (小时, 分钟)
194             self.cv.itemconfigure(self.跟随指针控件, text=self.跟随指针文本)
195 
196     def 时间间隔描述标签滚动响应(self):
197         def wheel_handler(event):
198             # print('滚动时间间隔描述区')
199             # print(event)
200             if event.delta > 0:
201                 self.改变时间间隔(1)(None)
202             elif event.delta < 0:
203                 self.改变时间间隔(-1)(None)
204         return wheel_handler
205 
206     def enter_handler(self, event):
207         self.跟随指针控件 = self.cv.create_text(event.x, event.y,
208                                           anchor=tk.E,
209                                           justify=tk.LEFT,
210                                           text=self.跟随指针文本)
211 
212     def leave_handler(self, event):
213         self.cv.delete(self.跟随指针控件)
214 
215     def click_handler(self, event):
216         变更日期文本 = self.日期变动按钮区判断(event.x, event.y)
217         行列 = self.坐标点位转行列(event.x, event.y)
218         if 变更日期文本:
219             变更日期文本参数字典 = {
220                 '-日': -1,
221                 '-周': -7,
222                 '-月': -30,
223                 '-年': -365,
224                 '+日': 1,
225                 '+周': 7,
226                 '+月': 30,
227                 '+年': 365,
228             }
229             self.改动时间区(变更日期文本参数字典[变更日期文本])
230             self.刷新范围底色()
231         elif 行列:
232             row = 行列[0]
233             column = 行列[1]
234             if self.选中的起始时间 and self.选中的结束时间:
235                 self.选中的起始时间 = None
236                 self.选中的结束时间 = None
237                 # self.选择结果描述标签.configure(text='取消上次的选择结果,请重新选择查询起始时间')
238                 self.cv.itemconfigure(self.选择结果描述标签, text='取消上次的选择结果,请重新选择查询起始时间')
239             elif not self.选中的起始时间 and self.选中的结束时间:
240                 self.选中的起始时间 = None
241                 self.选中的结束时间 = None
242                 # self.选择结果描述标签.configure(text='取消上次的选择结果,请重新选择查询起始时间')
243                 self.cv.itemconfigure(self.选择结果描述标签, text='取消上次的选择结果,请重新选择查询起始时间')
244             elif not self.选中的起始时间 and not self.选中的结束时间:
245                 self.选中的起始时间 = datetime(self.日期列表[row].year,
246                                         self.日期列表[row].month,
247                                         self.日期列表[row].day,
248                                         column // 6,
249                                         column % 6 * 10)
250                 # self.选择结果描述标签.configure(text='您已选择 %s 作为查询起始时间,请再选择查询结束时间' % self.选中的起始时间.strftime('%Y年%m月%d日 %H:%M'))
251                 self.cv.itemconfigure(self.选择结果描述标签,
252                                       text='您已选择 %s 作为查询起始时间,请再选择查询结束时间' % self.选中的起始时间.strftime('%Y年%m月%d日 %H:%M'))
253             elif self.选中的起始时间 and not self.选中的结束时间:
254                 self.选中的结束时间 = datetime(self.日期列表[row].year,
255                                         self.日期列表[row].month,
256                                         self.日期列表[row].day,
257                                         column // 6,
258                                         column % 6 * 10)
259                 if self.选中的起始时间 > self.选中的结束时间:
260                     临时替换变量 = self.选中的起始时间
261                     self.选中的起始时间 = self.选中的结束时间
262                     self.选中的结束时间 = 临时替换变量
263                 self.刷新结果描述()
264             self.刷新范围底色()
265 
266     def mwheel_handler(self, event):
267         # print(event)
268         日期区坐标 = (10, 40)
269         if ((日期区坐标[0] < event.x < 1800) and
270                 (日期区坐标[1] < event.y < 日期区坐标[1] + 200)):
271             if event.delta > 0:
272                 self.改动时间区(1)
273             else:
274                 self.改动时间区(-1)
275             self.刷新范围底色()
276             # print('滚动')
277             # print(event)
278             # print(dir(event))
279             # print(event.type)
280             self.move_handler(event)
281 
282     def 坐标转点位ID(self, x, y):
283         行列 = self.坐标点位转行列(x, y)
284         点位ID = -1
285         if 行列:
286             点位ID = self.时间位总列表[行列[0]][行列[1]]
287         return 点位ID
288 
289     def 坐标点位转行列(self, x, y):
290         时间点阵区坐标 = (120, 30)
291         点位尺寸 = (8, 20)
292         if ((时间点阵区坐标[0] < x < 时间点阵区坐标[0] + 点位尺寸[0] * 144) and
293                 (时间点阵区坐标[1] < y < 时间点阵区坐标[1] + 点位尺寸[1] * 10)):
294             列序号 = (x - 时间点阵区坐标[0]) // 点位尺寸[0]
295             行序号 = (y - 时间点阵区坐标[1]) // 点位尺寸[1]
296             return 行序号, 列序号
297         else:
298             return None
299 
300     def ID转转行列(self, ID):
301         行序号 = -1
302         列序号 = -1
303         for 行点位 in self.时间位总列表:
304             行序号 += 1
305             列序号 = -1
306             for 点位 in 行点位:
307                 列序号 += 1
308                 if 点位 == ID:
309                     return 行序号, 列序号
310         return None
311 
312     def 日期变动按钮区判断(self, x, y):
313         日期减按钮区坐标 = (10, 5)
314         日期变动按钮尺寸 = (25, 20)
315         日期减按钮文本列表 = ['-日', '-周', '-月', '-年']
316         日期加按钮区坐标 = (10, 235)
317         日期加按钮文本列表 = ['+日', '+周', '+月', '+年']
318         点击的按钮 = None
319         if ((日期减按钮区坐标[0] < x < 日期减按钮区坐标[0] + 日期变动按钮尺寸[0] * 4) and
320                 (日期减按钮区坐标[1] < y < 日期减按钮区坐标[1] + 日期变动按钮尺寸[1] * 1)):
321             点击的按钮 = 日期减按钮文本列表[int((x - 日期减按钮区坐标[0]) // 日期变动按钮尺寸[0])]
322             print('点击了按钮: %s' % 点击的按钮)
323         elif ((日期加按钮区坐标[0] < x < 日期加按钮区坐标[0] + 日期变动按钮尺寸[0] * 4) and
324               (日期加按钮区坐标[1] < y < 日期加按钮区坐标[1] + 日期变动按钮尺寸[1] * 1)):
325             点击的按钮 = 日期加按钮文本列表[int((x - 日期加按钮区坐标[0]) // 日期变动按钮尺寸[0])]
326             print('点击了按钮: %s' % 点击的按钮)
327         else:
328             点击的按钮 = None
329             print('没有点击日期变更按钮')
330         return 点击的按钮
331 
332     def 改动时间区(self, 改动天数):
333         self.时间区尾 = self.时间区尾 + timedelta(days=改动天数)
334         self.时间区头 = self.时间区头 + timedelta(days=改动天数)
335         for j in range(0, 10):
336             当前行日期 = self.时间区头 + timedelta(days=j)
337             self.cv.itemconfigure(self.日期标签列表[j], text=当前行日期.isoformat() + self.中文周[当前行日期.isoweekday()])
338             self.日期列表[j] = 当前行日期
339         # self.刷新范围底色()
340 
341     def 刷新范围底色(self):
342         if not self.选中的起始时间:
343             for 时间位行 in self.时间位总列表:
344                 for 时间位 in 时间位行:
345                     # 时间位.configure(bg='#F0F0F0')
346                     self.cv.itemconfigure(时间位, fill='#FFFFFF')
347         elif self.选中的起始时间 and not self.选中的结束时间:
348             row, column = self.根据选择的时间点判断对应时间位的位置(self.选中的起始时间)
349             if 0 <= row < 10 and 0 <= column < 144:
350                 # self.时间位总列表[row][column].configure(bg='#00FF00')
351                 self.cv.itemconfigure(self.时间位总列表[row][column], fill='#00FF00')
352             选中时间坐标 = self.根据选择的时间点判断对应时间位的位置(self.选中的起始时间)
353             选中时间一维坐标 = 选中时间坐标[0] * 1000 + 选中时间坐标[1]
354             for j in range(0, 10):
355                 for i in range(0, 144):
356                     if j * 1000 + i == 选中时间一维坐标:
357                         # self.时间位总列表[j][i].configure(bg='#00FF00')
358                         self.cv.itemconfigure(self.时间位总列表[j][i], fill='#00FF00')
359                     else:
360                         # self.时间位总列表[j][i].configure(bg='#F0F0F0')
361                         self.cv.itemconfigure(self.时间位总列表[j][i], fill='#FFFFFF')
362         elif self.选中的起始时间 and self.选中的结束时间:
363             起始时间坐标 = self.根据选择的时间点判断对应时间位的位置(self.选中的起始时间)
364             结束时间坐标 = self.根据选择的时间点判断对应时间位的位置(self.选中的结束时间)
365             起始时间一维坐标 = 起始时间坐标[0] * 1000 + 起始时间坐标[1]
366             结束时间一维坐标 = 结束时间坐标[0] * 1000 + 结束时间坐标[1]
367             for j in range(0, 10):
368                 for i in range(0, 144):
369                     if 起始时间一维坐标 <= j * 1000 + i <= 结束时间一维坐标:
370                         # self.时间位总列表[j][i].configure(bg='#00FF00')
371                         self.cv.itemconfigure(self.时间位总列表[j][i], fill='#00FF00')
372                     else:
373                         # self.时间位总列表[j][i].configure(bg='#F0F0F0')
374                         self.cv.itemconfigure(self.时间位总列表[j][i], fill='#FFFFFF')
375 
376     def 改变时间间隔(self, 偏移值):
377         def change_dtime(e):
378             if self.时间间隔 + 偏移值 > 0:
379                 self.时间间隔 += 偏移值
380             else:
381                 self.时间间隔 = 1
382             self.时间间隔描述标签.configure(text='时间间隔为: %d 分钟' % self.时间间隔)
383             self.刷新结果描述()
384         return change_dtime
385 
386     def 设置时间间隔(self, 设置值):
387         def set_dtime(e):
388             self.时间间隔 = 设置值
389             self.时间间隔描述标签.configure(text='时间间隔为: %d 分钟' % self.时间间隔)
390             self.刷新结果描述()
391 
392         return set_dtime
393 
394     def 刷新结果描述(self):
395         # print('刷新结果描述')
396         if self.选中的起始时间 and self.选中的结束时间:
397             # print(self.选中的起始时间)
398             第1个时间文本 = self.选中的起始时间.strftime('%Y年%m月%d日%H:%M')
399             第2个时间文本 = self.选中的结束时间.strftime('%Y年%m月%d日%H:%M')
400             if 第1个时间文本[:11] == 第2个时间文本[:11]:
401                 第2个时间文本 = 第2个时间文本[12:]
402             elif 第1个时间文本[:8] == 第2个时间文本[:8]:
403                 第2个时间文本 = 第2个时间文本[8:]
404             elif 第1个时间文本[:5] == 第2个时间文本[:5]:
405                 第2个时间文本 = 第2个时间文本[5:]
406             时间跨度 = self.选中的结束时间 - self.选中的起始时间
407             天数 = int(时间跨度.total_seconds() // (3600 * 24))
408             小时 = int(时间跨度.total_seconds() % (3600 * 24) // 3600)
409             分钟 = int(时间跨度.total_seconds() % 3600 // 60)
410             时间范围描述文本 = ''
411             if 天数 > 0:
412                 时间范围描述文本 += str(天数) + ''
413             if 小时 > 0:
414                 时间范围描述文本 += str(小时) + '小时'
415             if 分钟 > 0:
416                 时间范围描述文本 += str(分钟) + '分钟'
417             时间间隔文本 = str(int(self.时间间隔))
418             生成记录条数 = int(时间跨度 / timedelta(minutes=self.时间间隔))
419             记录数量文本 = '预计生成%d条记录' % 生成记录条数
420             if 生成记录条数 > 19990:
421                 记录数量文本 += ',超出最大限制!!!'
422             self.cv.itemconfigure(self.选择结果描述标签, text='查询范围是%s到%s,共计%s,时间间隔%s分钟,%s' %
423                                                       (第1个时间文本,
424                                                        第2个时间文本,
425                                                        时间范围描述文本,
426                                                        时间间隔文本,
427                                                        记录数量文本))
428 
429     def 根据选择的时间点判断对应时间位的位置(self, 时间点):
430         # 时间点 = datetime.today()
431         时间偏移 = (时间点 - datetime.combine(self.时间区头, time())).total_seconds()
432         row = int(时间偏移 // (3600 * 24))
433         column = int(时间偏移 % (3600 * 24) // (10 * 60))
434         return row, column
435 
436     def run(self):
437         self.读取从机数据()
438         self.主窗口.mainloop()
439 
440     def close_win(self):
441         self.主窗口.destroy()
442 
443     def ok_action(self, e):
444         self.通讯器.写数据(0, [2])
445         self.通讯器.写数据(1, [7788])
446         if not self.选中的起始时间 or not self.选中的结束时间:
447             当前时间 = datetime.now()
448             分钟 = int(当前时间.minute // 10 * 10)
449             self.选中的结束时间 = datetime(当前时间.year,
450                                     当前时间.month,
451                                     当前时间.day,
452                                     当前时间.hour,
453                                     分钟)
454             self.选中的起始时间 = self.选中的结束时间 - timedelta(hours=2)
455         给组态王的起始时间 = self.转换为组态王时间(self.选中的起始时间)
456         给组态王的结束时间 = self.转换为组态王时间(self.选中的结束时间)
457         给组态王的时间间隔 = self.时间间隔 * 60
458         self.通讯器.写数据(2, self.转换为长整型(给组态王的起始时间))
459         self.通讯器.写数据(4, self.转换为长整型(给组态王的结束时间))
460         self.通讯器.写数据(6, self.转换为长整型(给组态王的时间间隔))
461         self.通讯器.写数据(8, [int(self.选中的起始时间.year)])
462         self.通讯器.写数据(9, [int(self.选中的起始时间.month)])
463         self.通讯器.写数据(10, [int(self.选中的起始时间.day)])
464         self.通讯器.写数据(11, [int(self.选中的起始时间.hour)])
465         self.通讯器.写数据(12, [int(self.选中的起始时间.minute)])
466         self.通讯器.写数据(13, [int(self.选中的结束时间.year)])
467         self.通讯器.写数据(14, [int(self.选中的结束时间.month)])
468         self.通讯器.写数据(15, [int(self.选中的结束时间.day)])
469         self.通讯器.写数据(16, [int(self.选中的结束时间.hour)])
470         self.通讯器.写数据(17, [int(self.选中的结束时间.minute)])
471         self.close_win()
472 
473     def 转换为长整型(self, 数据):
474         数据 = 数据 % (2 ** 31)
475         高16位 = int(数据 // (2 ** 16))
476         低16位 = int(abs(数据 % (2 ** 16)))
477         return [高16位, 低16位]
478 
479     def 转换为组态王时间(self, 时间点):
480         组态王时间 = 时间点 - datetime(1970, 1, 1, 8, 0, 0, 0)
481         # 组态王时间 = timedelta(seconds=0)
482         return 组态王时间.total_seconds()
483 
484     def 解码长整形(self, 字列表):
485         return int(字列表[0] * (2 ** 16) + 字列表[1])
486 
487     def 读取从机数据(self):
488         开始时间_组态王格式 = self.解码长整形(self.通讯器.读数据(2, 2))
489         结束时间_组态王格式 = self.解码长整形(self.通讯器.读数据(4, 2))
490         查询间隔_组态王格式 = self.解码长整形(self.通讯器.读数据(6, 2))
491         self.选中的起始时间 = datetime(1970, 1, 1, 8, 0, 0) + timedelta(seconds=开始时间_组态王格式)
492         self.选中的结束时间 = datetime(1970, 1, 1, 8, 0, 0) + timedelta(seconds=结束时间_组态王格式)
493         if 查询间隔_组态王格式 > 0:
494             self.时间间隔 = int(查询间隔_组态王格式 // 60)
495             self.时间间隔描述标签.configure(text='时间间隔为: %d 分钟' % self.时间间隔)
496         self.刷新结果描述()
497         self.刷新范围底色()
498 
499 
500 class modbus从机服务器():
501     def __init__(self):
502         # Create the server
503         self.server = modbus_tcp.TcpServer(address='127.0.0.1', port=9527)
504         self.server.start()
505         self.从机 = self.server.add_slave(1)
506         self.从机.add_block('0', cst.HOLDING_REGISTERS, 0, 100)
507 
508     def 关闭服务(self):
509         self.server.stop()
510 
511     def 写数据(self, 地址, 数据列表):
512         self.从机.set_values('0', 地址, 数据列表)
513 
514     def 读数据(self, 地址, 长度):
515         return self.从机.get_values('0', 地址, 长度)
516 
517 
518 if __name__ == '__main__':
519     从机 = modbus从机服务器()
520     日历选择控件 = 日历控件(从机)
521     # 日历选择控件.run()
522     while True:
523         # 从机.写数据(0, [5])
524         启动画面指令 = 从机.读数据(0, 1)[0]
525         # print(启动画面指令)
526         # print(type(启动画面指令))
527         if 启动画面指令 == 1:
528             日历选择控件.run()
529         if 启动画面指令 == 2:
530             日历选择控件 = 日历控件(从机)
531             从机.写数据(0, [0])
532         sleep(1)
View Code

依赖

链接:https://pan.baidu.com/s/1hNS7lQXIUSP34JzuU5gvgA?pwd=y62b
提取码:y62b

给懒汉的可执行文件

链接:https://pan.baidu.com/s/18n4FO4kiHDQDw0U2LCtcpg?pwd=bel7
提取码:bel7