• 操作系统实验一:时钟中断程序设计


    一、实验目的

    1、 了解和使用操作系统程序开发环境;
    2、 熟悉常用的功能菜单命令;
    3、 掌握图形化程序开发方法;
    4、 深入理解操作系统中的时钟中断的含义及其具体使用。

    二、实验内容:

    1、安装Linux虚拟机,熟悉Linux系统下各种操作命令,包括软件安装命令,程序编译运行命令等。
    2、在屏幕指定窗口区域绘制一辆小车(或载入一幅小车图片,去掉背景),让小车沿窗口左上角往右下角匀速移动。
    具体要求如下:
    (1)小车一定要是从左上角到右下角;
    (2)移动是基本匀速的,且能通过按钮调节其速度,速度设置至少在2种以上;
    (3)点击关闭按钮后,程序转入后台执行,程序对应图标出现在任务栏托盘区;
    (4)右键点击托盘区程序对应图标,弹出菜单,点击“恢复”,则程序重新被切换到前台运行,点击“退出”,程序退出内存,停止运行;
    (5)程序转入后台运行时,小车仍然在移动。只是不可见而已。

    三、实验要求

    1、复习教材有关内容。
    2、掌握VC控制台应用程序的开发、调试步骤。
    3、完成实验报告。

    四、实验代码

    结果展示

    在这里插入图片描述
    在这里插入图片描述

    代码思路

    创建界面使用的是tkinter库的窗口,先设置主窗口的各个参数,然后配置按钮的属性值,以及显现的小车图像。
    要想使小车图像png运动起来,可以通过移动图像的坐标,然后在创建的窗口上使用while循环不断调用中断刷新窗口即可。注意设计边界条件,当小车运动到边界时重头开始运动。
    然后通过keyboard库的add_hotkey函数监听键盘点击事件,然后触发绑定函数,更新图形的移动速度。
    最后绑定窗口点击关闭事件,右击显示“恢复”和退出菜单栏以及对应的函数都在class SysTrayIcon中。

    全部代码

    import win32api, win32con, win32gui_struct, win32gui
    import os, tkinter as tk
    import keyboard
    import pygame
    from multiprocessing import Process
    import os, time
    import psutil
    
    
    # 设置小车运行速度
    speed = 0.01
    
    class SysTrayIcon(object):
        '''SysTrayIcon类用于显示任务栏图标'''
        QUIT = 'QUIT'
        SPECIAL_ACTIONS = [QUIT]
        FIRST_ID = 5320
    
        def __init__(s, icon, hover_text, menu_options, on_quit, tk_window=None, default_menu_index=None,
                     window_class_name=None):
            '''
            icon         图标文件路径
            hover_text   鼠标停留在图标上方时显示的文字
            menu_options 右键菜单,格式: (('a', None, callback), ('b', None, (('b1', None, callback),)))
            on_quit      传递退出函数,在执行退出时一并运行
            tk_window    传递Tk窗口,s.root,用于单击图标显示窗口
            default_menu_index 不显示的右键菜单序号
            window_class_name  窗口类名
            '''
            s.icon = icon
            s.hover_text = hover_text
            s.on_quit = on_quit
            s.root = tk_window
    
            menu_options = menu_options + (('退出', None, s.QUIT),)
            s._next_action_id = s.FIRST_ID
            s.menu_actions_by_id = set()
            s.menu_options = s._add_ids_to_menu_options(list(menu_options))
            s.menu_actions_by_id = dict(s.menu_actions_by_id)
            del s._next_action_id
    
            s.default_menu_index = (default_menu_index or 0)
            s.window_class_name = window_class_name or "SysTrayIconPy"
    
            message_map = {win32gui.RegisterWindowMessage("TaskbarCreated"): s.restart,
                           win32con.WM_DESTROY: s.destroy,
                           win32con.WM_COMMAND: s.command,
                           win32con.WM_USER + 20: s.notify, }
            # 注册窗口类。
            wc = win32gui.WNDCLASS()
            wc.hInstance = win32gui.GetModuleHandle(None)
            wc.lpszClassName = s.window_class_name
            wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW;
            wc.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
            wc.hbrBackground = win32con.COLOR_WINDOW
            wc.lpfnWndProc = message_map  # 也可以指定wndproc.
            s.classAtom = win32gui.RegisterClass(wc)
    
        def activation(s):
            '''激活任务栏图标,不用每次都重新创建新的托盘图标'''
            hinst = win32gui.GetModuleHandle(None)  # 创建窗口。
            style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
            s.hwnd = win32gui.CreateWindow(s.classAtom,
                                           s.window_class_name,
                                           style,
                                           0, 0,
                                           win32con.CW_USEDEFAULT,
                                           win32con.CW_USEDEFAULT,
                                           0, 0, hinst, None)
            win32gui.UpdateWindow(s.hwnd)
            s.notify_id = None
            s.refresh(title='软件已后台!', msg='点击重新打开', time=500)
    
            win32gui.PumpMessages()
    
        def refresh(s, title='', msg='', time=500):
            '''刷新托盘图标
               title 标题
               msg   内容,为空的话就不显示提示
               time  提示显示时间'''
            hinst = win32gui.GetModuleHandle(None)
            if os.path.isfile(s.icon):
                icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
                hicon = win32gui.LoadImage(hinst, s.icon, win32con.IMAGE_ICON,
                                           0, 0, icon_flags)
            else:  # 找不到图标文件 - 使用默认值
                hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
    
            if s.notify_id:
                message = win32gui.NIM_MODIFY
            else:
                message = win32gui.NIM_ADD
    
            s.notify_id = (s.hwnd, 0,  # 句柄、托盘图标ID
                           win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP | win32gui.NIF_INFO,
                           # 托盘图标可以使用的功能的标识
                           win32con.WM_USER + 20, hicon, s.hover_text,  # 回调消息ID、托盘图标句柄、图标字符串
                           msg, time, title,  # 提示内容、提示显示时间、提示标题
                           win32gui.NIIF_INFO  # 提示用到的图标
                           )
            win32gui.Shell_NotifyIcon(message, s.notify_id)
    
        def show_menu(s):
            '''显示右键菜单'''
            menu = win32gui.CreatePopupMenu()
            s.create_menu(menu, s.menu_options)
    
            pos = win32gui.GetCursorPos()
            win32gui.SetForegroundWindow(s.hwnd)
            win32gui.TrackPopupMenu(menu,
                                    win32con.TPM_LEFTALIGN,
                                    pos[0],
                                    pos[1],
                                    0,
                                    s.hwnd,
                                    None)
            win32gui.PostMessage(s.hwnd, win32con.WM_NULL, 0, 0)
    
        def _add_ids_to_menu_options(s, menu_options):
            result = []
            for menu_option in menu_options:
                option_text, option_icon, option_action = menu_option
                if callable(option_action) or option_action in s.SPECIAL_ACTIONS:
                    s.menu_actions_by_id.add((s._next_action_id, option_action))
                    result.append(menu_option + (s._next_action_id,))
                else:
                    result.append((option_text,
                                   option_icon,
                                   s._add_ids_to_menu_options(option_action),
                                   s._next_action_id))
                s._next_action_id += 1
            return result
    
        def restart(s, hwnd, msg, wparam, lparam):
            s.refresh()
    
        def destroy(s, hwnd=None, msg=None, wparam=None, lparam=None, exit=1):
            nid = (s.hwnd, 0)
            win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid)
            win32gui.PostQuitMessage(0)  # 终止应用程序。
            # 判断是否后台来跳过tk操作
            if exit and s.on_quit:
                s.on_quit()  # 需要传递自身过去时用 s.on_quit(s)
            else:
                # print('0000000000')
                s.root.deiconify()  # 显示tk窗口
    
        def notify(s, hwnd, msg, wparam, lparam):
            '''鼠标事件,双击框体图标'''
            '''
                    可能的鼠标事件:
                    WM_MOUSEMOVE      #光标经过图标
                    WM_LBUTTONDOWN    #左键按下
                    WM_LBUTTONUP      #左键弹起
                    WM_LBUTTONDBLCLK  #双击左键
                    WM_RBUTTONDOWN    #右键按下
                    WM_RBUTTONUP      #右键弹起
                    WM_RBUTTONDBLCLK  #双击右键
                    WM_MBUTTONDOWN    #滚轮按下
                    WM_MBUTTONUP      #滚轮弹起
                    WM_MBUTTONDBLCLK  #双击滚轮
            '''
            if lparam == win32con.WM_LBUTTONDBLCLK:  # 双击左键
                pass
            elif lparam == win32con.WM_RBUTTONUP:  # 右键弹起
                s.show_menu()
            elif lparam == win32con.WM_LBUTTONUP:  # 左键弹起
                s.destroy(exit=0)
            return True
    
        def create_menu(s, menu, menu_options):
            for option_text, option_icon, option_action, option_id in menu_options[::-1]:
                if option_icon:
                    option_icon = s.prep_menu_icon(option_icon)
    
                if option_id in s.menu_actions_by_id:
                    item, extras = win32gui_struct.PackMENUITEMINFO(text=option_text,
                                                                    hbmpItem=option_icon,
                                                                    wID=option_id)
                    win32gui.InsertMenuItem(menu, 0, 1, item)
                else:
                    submenu = win32gui.CreatePopupMenu()
                    s.create_menu(submenu, option_action)
                    item, extras = win32gui_struct.PackMENUITEMINFO(text=option_text,
                                                                    hbmpItem=option_icon,
                                                                    hSubMenu=submenu)
                    win32gui.InsertMenuItem(menu, 0, 1, item)
    
        def prep_menu_icon(s, icon):
            # 加载图标。
            ico_x = win32api.GetSystemMetrics(win32con.SM_CXSMICON)
            ico_y = win32api.GetSystemMetrics(win32con.SM_CYSMICON)
            hicon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, ico_x, ico_y, win32con.LR_LOADFROMFILE)
    
            hdcBitmap = win32gui.CreateCompatibleDC(0)
            hdcScreen = win32gui.GetDC(0)
            hbm = win32gui.CreateCompatibleBitmap(hdcScreen, ico_x, ico_y)
            hbmOld = win32gui.SelectObject(hdcBitmap, hbm)
            brush = win32gui.GetSysColorBrush(win32con.COLOR_MENU)
            win32gui.FillRect(hdcBitmap, (0, 0, 16, 16), brush)
            win32gui.DrawIconEx(hdcBitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL)
            win32gui.SelectObject(hdcBitmap, hbmOld)
            win32gui.DeleteDC(hdcBitmap)
    
            return hbm
    
        def command(s, hwnd, msg, wparam, lparam):
            id = win32gui.LOWORD(wparam)
            s.execute_menu_option(id)
    
        def execute_menu_option(s, id):
            menu_action = s.menu_actions_by_id[id]
            if menu_action == s.QUIT:
                win32gui.DestroyWindow(s.hwnd)
            else:
                menu_action(s)
    
    
    class _Main:  # 调用SysTrayIcon的Demo窗口
        def __init__(s):
            s.SysTrayIcon = None  # 判断是否打开系统托盘图标
    
        def main(s):
            # tk窗口
            s.root = tk.Tk()
            # 设置主窗口标题
            s.root.title("A car is running")
            # 设置窗口宽高固定
            s.root.resizable(0, 0)
            canvas = tk.Canvas(s.root,width=500, height=500, bg='white')
            # s.root.protocol("WM_DELETE_WINDOW", callbackClose)
            s.root.bind("",
                        lambda event: s.Hidden_window() if s.root.state() == 'iconic' else False)  # 窗口最小化判断,可以说是调用最重要的一步
            s.root.protocol('WM_DELETE_WINDOW', s.callbackClose)  # 点击Tk窗口关闭时直接调用s.exit,不使用默认关闭
            s.root.resizable(0, 0)  # 锁定窗口大小不能改变
            # 正方形
            # s.root.geometry("500x500")
            tk.Button(s.root, width=5, height=5, text='lowspeed', anchor='c', bg='green', fg='red', padx=5, pady=5,
                   borderwidth=10, relief='ridge',  compound='bottom', command=s.lowspeed).pack()
            tk.Button(s.root, width=5, height=5, text='midspeed', anchor='c', bg='green', fg='red', padx=5, pady=5,
                      borderwidth=10, relief='ridge', compound='bottom', command=s.midspeed).pack()
            tk.Button(s.root, width=5, height=5, text='highspeed', anchor='c', bg='green', fg='red', padx=5, pady=5,
                      borderwidth=10, relief='ridge', compound='bottom', command=s.highspeed).pack()
            #  配置
            #  要打开的图像
            image1 = "car.png"
            # 初始坐标
            x0 = 50.0;y0 = 50.0
            # 列表将包含所有的x和y坐标.到目前为止,他们只包含初始坐标
            x = [x0];y = [y0]
            # 每次移动的速度或距离
            vx = 1.0 # x 速度;
            vy = 1.0  # y 速度
            # 边界,这里要考虑到图片的大小,要预留一半的长和宽
            x_max = 450.0
            y_max = 450.0
            # 运行步数
            range_min = 1;range_max = 2000
    
            while (True):
                # 创建500次的x和y坐标
                for t in range(range_min, range_max):
                    keyboard.add_hotkey('1', s.highspeed)
                    keyboard.add_hotkey('2', s.midspeed)
                    keyboard.add_hotkey('3', s.lowspeed)
    
                    # 新坐标等于旧坐标加每次移动的距离
                    new_x = x[t - 1] + vx
                    new_y = y[t - 1] + vy
                    # 如果已经越过边界,重头开始运动
                    if new_x >= x_max:
                        new_x = x0
                    if new_y >= y_max:
                        new_y = y0
                    # 添加新的值到列表
                    x.append(new_x)
                    y.append(new_y)
                # 开始使用tk绘图
                canvas.pack()
                photo1 = tk.PhotoImage(file=image1)
                width1 = photo1.width()
                height1 = photo1.height()
                # 每次的移动
                for t in range(range_min, range_max):
                    canvas.create_image(x[t], y[t], image=photo1, tag="pic")
                    canvas.update()
                    # 暂停 update time,然后删除图像
                    time.sleep(speed)
                    canvas.delete("all")
                s.root.mainloop()
    
        def callbackClose(self):
            self.Hidden_window()
    
        def highspeed(self):
            global speed
            # print("高速被点击")
            speed = 0.01
    
        def midspeed(self):
            global speed
            speed = 0.05
    
        def lowspeed(self):
            global speed
            speed = 0.3
    
        def switch_icon(s, _sysTrayIcon):
            s.root.deiconify()  # 显示tk窗口
            Main = _Main()
            Main.main()
            # pause.resume()  # 恢复子进程
            # print('\n子进程已恢复运行')
            # _sysTrayIcon.destroy(s.root)
    
        def show_msg(s, title='标题', msg='内容', time=500):
            s.SysTrayIcon.refresh(title=title, msg=msg, time=time)
    
        def Hidden_window(s, icon='', hover_text="SysTrayIcon.py Demo"):
            '''隐藏窗口至托盘区,调用SysTrayIcon的重要函数'''
    
            # 托盘图标右键菜单, 格式: ('name', None, callback),下面也是二级菜单的例子
            # 24行有自动添加‘退出’,不需要的可删除
            menu_options = (('恢复', None, s.switch_icon),
                            ('退出', None, (('恢复(二级)', None, s.switch_icon),)))
    
            s.root.withdraw()  # 隐藏tk窗口
            if not s.SysTrayIcon: s.SysTrayIcon = SysTrayIcon(
                icon,  # 图标
                hover_text,  # 光标停留显示文字
                menu_options,  # 右键菜单
                on_quit=s.exit,  # 退出调用
                tk_window=s.root,  # Tk窗口
            )
            s.SysTrayIcon.activation()
    
        def exit(s, _sysTrayIcon=None):
            s.root.destroy()
            print('exit...')
    
    
    if __name__ == '__main__':
        Main = _Main()
        Main.main()
        # 创建并启动子进程
        # p = Process(target=_Main.main, args=('test',))
        # p.start()
        # pid = p.pid  # 获取子进程的pid
        # pause = psutil.Process(pid)  # 传入子进程的pid
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351

    完善:代码解读

    SysTrayIcon,用于创建并管理系统托盘图标及其右键菜单

    初始化函数 __init__

    def __init__(s, icon, hover_text, menu_options, on_quit, tk_window=None, default_menu_index=None,
                 window_class_name=None):
    
    • 1
    • 2

    初始化函数用于创建一个SysTrayIcon对象。参数如下:

    • icon: 图标文件路径。
    • hover_text: 鼠标停留在图标上方时显示的文字。
    • menu_options: 右键菜单,格式为元组的嵌套,其中每个元组表示一个菜单项,包括菜单项文本、图标、回调函数。
    • on_quit: 传递退出函数,在执行退出时一并运行。
    • tk_window: 传递Tk窗口,用于单击图标时显示窗口。
    • default_menu_index: 不显示的右键菜单序号。
    • window_class_name: 窗口类名。

    激活函数 activation

    def activation(s):
    
    • 1

    此函数用于激活任务栏图标,不用每次都重新创建新的托盘图标。在任务栏上创建一个窗口,并在任务栏上显示图标。

    刷新函数 refresh

    def refresh(s, title='', msg='', time=500):
    
    • 1

    refresh 函数用于刷新托盘图标。参数如下:

    • title: 提示标题。
    • msg: 提示内容,如果为空则不显示提示。
    • time: 提示显示时间。

    显示右键菜单函数 show_menu

    def show_menu(s):
    
    • 1

    此函数用于显示右键菜单。

    添加菜单项ID _add_ids_to_menu_options

    def _add_ids_to_menu_options(s, menu_options):
    
    • 1

    该函数用于为每个菜单项添加唯一的ID。这些ID将用于处理菜单项的操作。

    重启函数 restart

    def restart(s, hwnd, msg, wparam, lparam):
    
    • 1

    此函数用于重新启动托盘图标。

    销毁函数 destroy

    def destroy(s, hwnd=None, msg=None, wparam=None, lparam=None, exit=1):
    
    • 1

    destroy 函数用于销毁托盘图标。如果 exit 为1,则执行退出操作。

    通知函数 notify

    def notify(s, hwnd, msg, wparam, lparam):
    
    • 1

    notify 函数处理鼠标事件,例如双击框体图标。

    创建右键菜单函数 create_menu

    def create_menu(s, menu, menu_options):
    
    • 1

    此函数用于创建右键菜单。它递归地创建子菜单项并设置其属性。

    准备菜单图标函数 prep_menu_icon

    def prep_menu_icon(s, icon):
    
    • 1

    prep_menu_icon 函数用于准备菜单图标。

    命令处理函数 command

    def command(s, hwnd, msg, wparam, lparam):
    
    • 1

    command 函数处理来自菜单的命令。

    执行菜单项操作函数 execute_menu_option

    def execute_menu_option(s, id):
    
    • 1

    execute_menu_option 函数执行菜单项操作,根据ID来执行相应的操作,例如退出应用程序。

    下面是对_Main类的代码进行详细解读,按照您提供的格式:

    _Main,用于创建Demo窗口和控制交互

    初始化函数 __init__

    def __init__(s):
    
    • 1

    初始化函数用于创建_Main对象。这个类负责创建Demo窗口和控制与系统托盘图标的交互。在初始化函数中,有以下属性:

    • s.SysTrayIcon: 用于判断是否已经打开系统托盘图标。初始值为None

    主函数 main

    def main(s):
    
    • 1

    主函数负责创建Demo窗口和控制Demo窗口的交互逻辑。以下是主要功能和部分重要变量的解释:

    • 创建一个Tk窗口:s.root,用于展示Demo窗口。
    • 设置窗口标题为 “A car is running”。
    • 锁定窗口大小不可改变。
    • 创建一个白色的画布 canvas 用于绘制图形。
    • 设置窗口最小化时的回调函数,即 s.Hidden_window 函数。
    • 设置点击窗口关闭按钮的回调函数,即 s.callbackClose 函数。
    • 创建三个按钮用于控制速度,分别是 “lowspeed”, “midspeed”, 和 “highspeed”。
    • 配置要加载的图像文件路径为 “car.png”。
    • 定义初始坐标 x0y0
    • 创建列表 xy,用于存储坐标。
    • 定义速度变量 vxvy
    • 定义边界坐标 x_maxy_max
    • 定义运行步数范围,range_minrange_max

    接下来,通过循环不断更新图形的位置,并在画布上绘制,然后删除之前的图形,以实现图形的移动效果。在不断更新图形的过程中,监测是否按下了键盘上的 “1”, “2”, 或 “3” 键,分别调用 s.highspeed, s.midspeed, 或 s.lowspeed 函数改变速度。

    最后,使用tkinter库的mainloop函数来显示Demo窗口。

    回调函数 callbackClose

    def callbackClose(self):
    
    • 1

    回调函数 callbackClose 用于关闭Demo窗口,它会调用 s.Hidden_window 函数,将Demo窗口隐藏到系统托盘中。

    设置速度函数

    def highspeed(self):
    def midspeed(self):
    def lowspeed(self):
    
    • 1
    • 2
    • 3

    这三个函数分别设置不同的速度。它们通过修改全局变量 speed 来改变图形的移动速度。

    switch_icon 函数

    def switch_icon(s, _sysTrayIcon):
    
    • 1

    switch_icon 函数用于切换图标。它会显示Demo窗口并启动主函数 main

    show_msg 函数

    def show_msg(s, title='标题', msg='内容', time=500):
    
    • 1

    show_msg 函数用于显示消息提示框。它接受标题、消息内容和显示时间作为参数,并通过 SysTrayIconrefresh 函数来刷新消息提示。

    Hidden_window 函数

    def Hidden_window(s, icon='', hover_text="SysTrayIcon.py Demo"):
    
    • 1

    Hidden_window 函数用于将Demo窗口隐藏到系统托盘中,调用 SysTrayIcon 的重要函数。它创建系统托盘图标右键菜单 menu_options,其中包括 “恢复” 和 “退出” 选项,以及一个二级菜单 “恢复(二级)”。然后,它隐藏Tk窗口,创建或激活系统托盘图标,并设置相应的图标、光标停留文字和右键菜单。最后,它调用系统托盘图标的 activation 函数来激活系统托盘图标。

    exit 函数

    def exit(s, _sysTrayIcon=None):
    
    • 1

    exit 函数用于退出应用程序,它会销毁Tk窗口并打印 “exit…”。

  • 相关阅读:
    配电网重构|基于新颖的启发式算法SOE的随机(SDNR)配电网重构(Matlab代码实现)【算例33节点、84节点、119节点、136节点、417节点】
    仿美团外卖微信小程序源码/美团外卖优惠券领劵小程序-自带流量主模式
    上传自己的私有的(公共的)CocoaPods支持库
    如何配置AI参数SK接口
    【必会篇】日常测试工作中,有哪些必须知道的 SQL 语句?
    这几款文档笔记工具,你习惯用哪个?
    【Swin Transformer原理和源码解析】Hierarchical Vision Transformer using Shifted Windows
    DNS1(Bind软件)
    【ccf-csp题解】第1次csp认证-第四题-无线网络-题解
    IOS总体框架介绍和详尽说明
  • 原文地址:https://blog.csdn.net/wtyuong/article/details/127437109