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

日历控件使用说明

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

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

 

 

依赖

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

给懒汉的可执行文件

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

 

posted @   急先锋小米  阅读(714)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示