日历控件使用说明
这是一个专门为组态软件(如组态王, 力控等)设计的时间选择控件,用于选择一个时间段,来进行数据报表的查询.
控件实际由2部分组成,1个UI程序,和1个modbus 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 从机服务器,并组态变量.当需要选择时间段时,将40001置1,则启动选择画面.从其他地址读取选择的结果.
上代码
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
标签:控件,python,self,组态王,日期,时间,坐标,按钮,间隔 From: https://www.cnblogs.com/jichao1515/p/17526881.html