python GUI开发:实现主屏幕控制副屏显示

news/2024/7/5 3:31:17

实现效果

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

实现代码

import tkinter as tk
import threading
import pygetwindow as gw
import subprocess
import cv2
import pygame
import time
import screeninfo


def func1():
    print("影音播放")
    open_child_window()


def func5():
    print("视频播放")
    video_path = "C:/Users/Fengzhen/Videos/全向步态视频/侧向步态.mp4"
    threading.Thread(target=open_video, args=(video_path,)).start()


def func6():
    print("音乐播放")
    audio_path = "C:/Users/Fengzhen/Videos/music.mp3"
    threading.Thread(target=open_music, args=(audio_path,)).start()


def open_child_window():
    # 创建子窗口
    child_window = tk.Toplevel(window)
    child_window.attributes('-fullscreen', True)  # 设置子窗口为全屏显示
    child_window.geometry(
        "{0}x{1}+0+0".format(child_window.winfo_screenwidth(), child_window.winfo_screenheight()))  # 设置子窗口大小为屏幕大小
    # 添加子窗口的内容
    child_canvas = tk.Canvas(child_window, width=child_window.winfo_screenwidth(),
                             height=child_window.winfo_screenheight())

    # 在画布上创建背景图像
    child_canvas.create_image(child_window.winfo_screenwidth() / 2, child_window.winfo_screenheight() / 2,
                              image=scaled_bg_image)

    # 加载图片按钮图像
    video_button_image = tk.PhotoImage(file="videoshow.png")
    music_button_image = tk.PhotoImage(file="music.png")

    # 缩放图片按钮图像
    global scaled_video_button_image
    global scaled_music_button_image
    scaled_video_button_image = video_button_image.subsample(1, 1)  # 3倍缩放
    scaled_music_button_image = music_button_image.subsample(2, 2)

    # 布局图片按钮
    button_width = scaled_video_button_image.width()
    button_height = scaled_video_button_image.height()
    canvas_center_x = child_window.winfo_screenwidth() // 2
    button_y = (child_window.winfo_screenheight() - button_height * 2) // 2

    video_button_x = canvas_center_x - (button_width + 10) * 0.8
    music_button_x = canvas_center_x + (button_width + 10) * 0.8

    video_button = tk.Button(child_canvas, image=scaled_video_button_image, command=func5, borderwidth=0,
                             highlightthickness=0)
    music_button = tk.Button(child_canvas, image=scaled_music_button_image, command=func6, borderwidth=0,
                             highlightthickness=0)

    # 添加文字说明
    video_label = tk.Label(child_canvas, text="视频播放", font=("Arial", 20, "bold"), bg=child_canvas["bg"])
    music_label = tk.Label(child_canvas, text="音乐播放", font=("Arial", 20, "bold"), bg=child_canvas["bg"])

    # 显示图片按钮和文字说明
    child_canvas.create_window(video_button_x, button_y, anchor=tk.CENTER, window=video_button)
    child_canvas.create_window(music_button_x, button_y, anchor=tk.CENTER, window=music_button)

    child_canvas.create_window(video_button_x, button_y + button_height, anchor=tk.CENTER, window=video_label)
    child_canvas.create_window(music_button_x, button_y + button_height, anchor=tk.CENTER, window=music_label)

    # 添加返回主页的按钮
    home_button_image = tk.PhotoImage(file="return.png")
    global scaled_home_button_image
    scaled_home_button_image = home_button_image.subsample(4, 4)
    home_button = tk.Button(child_canvas, image=scaled_home_button_image, command=lambda: return_to_home(child_window),
                            borderwidth=0, highlightthickness=0)
    child_canvas.create_window(canvas_center_x, button_y + button_height * 2 + 20, anchor=tk.CENTER, window=home_button)

    # 显示画布
    child_canvas.pack()


def return_to_home(child_window):
    print("返回主页")
    child_window.destroy()
    close_video()
    close_music()


def open_video(file_path):
    try:
        # 使用cv2读取视频
        cap = cv2.VideoCapture(file_path)

        # 创建窗口并设置位置
        cv2.namedWindow("Video", cv2.WINDOW_NORMAL)
        # cv2.moveWindow("Video", 3000, 100)
        cv2.setWindowProperty("Video", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

        while True:
            ret, frame = cap.read()
            if not ret:
                break

            # 在指定位置显示视频帧
            cv2.imshow("Video", frame)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        cap.release()
        cv2.destroyWindow("Video")

    except Exception as e:
        print(e)


def close_video():
    print("关闭视频")
    # cv2.destroyWindow("Video")


def open_music(file_path):
    try:
        # 初始化pygame
        pygame.init()

        # 设置音频设备
        pygame.mixer.init()

        # 加载音乐文件
        pygame.mixer.music.load(file_path)

        # 播放音乐
        pygame.mixer.music.play()

        # 等待音乐播放完毕
        while pygame.mixer.music.get_busy():
            continue

        # 停止音乐播放
        pygame.mixer.music.stop()

    except Exception as e:
        print(e)



def close_music():
    print("关闭音乐")
    pygame.mixer.init()
    pygame.mixer.music.stop()
    pygame.mixer.quit()
    pygame.quit()


# def func2():
#     print("浏览器")
#     software_path = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
#     subprocess.Popen(software_path)
#     window.attributes("-fullscreen", True)

def func2():
    print("浏览器")
    software_path = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
    # software_path = "C:/Program Files (x86)/Thunder Network/Thunder/Program/ThunderStart.exe"
    # software_path = "D:/Program Files/uvnc bvba/UltraVNC/vncviewer.exe"
    subprocess.Popen(software_path)

    # 等待打开的窗口出现
    time.sleep(0.35)

    # 获取所有窗口
    windows = gw.getAllWindows()
    # 获取副屏幕的尺寸
    screen = screeninfo.get_monitors()[1]  # 假设副屏幕是第二个屏幕
    screen_width = screen.width
    screen_height = screen.height

    # 遍历窗口,找到浏览器窗口
    for window in windows:
        # print(window.title)
        # if "UltraVNC Viewer - 1.4.0.9" in window.title:
        if "新建标签页" in window.title:
            # 将浏览器窗口移动到副屏上
            window.moveTo(3000, 100)

            # 设置窗口大小为副屏幕大小
            window.resizeTo(screen_width, screen_height)

            # 最大化浏览器窗口
            window.maximize()

            break


def func3():
    print("游戏")
    software_path = "C:/Program Files (x86)/Thunder Network/Thunder/Program/ThunderStart.exe"
    subprocess.Popen(software_path)
    # 等待打开的窗口出现
    time.sleep(0.35)
    # 获取所有窗口
    windows = gw.getAllWindows()
    # 获取副屏幕的尺寸
    screen = screeninfo.get_monitors()[1]  # 假设副屏幕是第二个屏幕
    screen_width = screen.width
    screen_height = screen.height
    # 遍历窗口,找到指定的窗口
    for window in windows:
        print(window.title)
        if "迅雷" in window.title:  # 替换为你想要找到的窗口标题
            # 将窗口移动到副屏上
            window.moveTo(3000, 10)

            # 设置窗口大小为副屏幕大小
            window.resizeTo(screen_width, screen_height)

            # 最大化窗口
            window.maximize()

            break


def func4():
    print("设置")
    folder_path = "C:/"  # 替换为你要打开的文件夹路径

    # 使用 explorer.exe 应用程序打开指定文件夹
    subprocess.Popen(["explorer.exe", folder_path])

    # 等待打开的窗口出现
    time.sleep(0.5)

    # 获取所有窗口
    windows = gw.getAllWindows()

    # 获取副屏幕的尺寸
    screen = screeninfo.get_monitors()[1]  # 假设副屏幕是第二个屏幕
    screen_width = screen.width
    screen_height = screen.height

    # 遍历窗口,找到指定的窗口
    for window in windows:
        print(window.title)
        if "文档" in window.title:  # 替换为你想要找到的窗口标题
            # 将窗口移动到副屏上
            window.moveTo(3000, 10)

            # 设置窗口大小为副屏幕大小
            window.resizeTo(screen_width, screen_height)

            # 最大化窗口
            window.maximize()

            break

# 创建主窗口
window = tk.Tk()

# 设置窗口全屏显示
window.attributes('-fullscreen', True)  # 设置窗口为全屏显示
window.geometry("{0}x{1}+0+0".format(window.winfo_screenwidth(), window.winfo_screenheight()))  # 设置窗口大小为屏幕大小

# 加载背景图像
background_image = tk.PhotoImage(file="background.png")

# 创建画布
canvas_width = window.winfo_screenwidth()  # 获取屏幕宽度
canvas_height = window.winfo_screenheight()  # 获取屏幕高度
canvas = tk.Canvas(window, width=canvas_width, height=canvas_height)

# 缩放背景图像
scaled_bg_image = background_image.zoom(2, 2)

# 在画布上创建背景图像
canvas.create_image(canvas_width / 2, canvas_height / 2, image=scaled_bg_image)

# 加载按钮图像
button1_image = tk.PhotoImage(file="video.png")
button2_image = tk.PhotoImage(file="edge.png")
button3_image = tk.PhotoImage(file="play.png")
button4_image = tk.PhotoImage(file="setting.png")

# 缩放按钮图像
scaled_button1_image = button1_image.subsample(2, 2)  # 2倍缩放
scaled_button2_image = button2_image.subsample(2, 2)
scaled_button3_image = button3_image.subsample(2, 2)
scaled_button4_image = button4_image.subsample(2, 2)

# 布局图标按钮
button_width = scaled_button1_image.width()
button_height = scaled_button1_image.height()
canvas_center_x = canvas_width // 2
button_y = (canvas_height - button_height * 2) // 2

button1_x = canvas_center_x - (button_width + 10) * 2.2
button2_x = canvas_center_x - (button_width + 10) * 0.7
button3_x = canvas_center_x + (button_width + 10) * 0.8
button4_x = canvas_center_x + (button_width + 10) * 2.2

button1 = tk.Button(canvas, image=scaled_button1_image, command=func1, borderwidth=0, highlightthickness=0)
button2 = tk.Button(canvas, image=scaled_button2_image, command=func2, borderwidth=0, highlightthickness=0)
button3 = tk.Button(canvas, image=scaled_button3_image, command=func3, borderwidth=0, highlightthickness=0)
button4 = tk.Button(canvas, image=scaled_button4_image, command=func4, borderwidth=0, highlightthickness=0)

# 添加文字说明
label1 = tk.Label(canvas, text="影音播放", font=("Arial", 20, "bold"), bg=canvas["bg"])
label2 = tk.Label(canvas, text="浏览器", font=("Arial", 20, "bold"), bg=canvas["bg"])
label3 = tk.Label(canvas, text="游戏", font=("Arial", 20, "bold"), bg=canvas["bg"])
label4 = tk.Label(canvas, text="设置", font=("Arial", 20, "bold"), bg=canvas["bg"])

# 显示按钮和文字说明
canvas.create_window(button1_x, button_y, anchor=tk.CENTER, window=button1)
canvas.create_window(button2_x, button_y, anchor=tk.CENTER, window=button2)
canvas.create_window(button3_x, button_y, anchor=tk.CENTER, window=button3)
canvas.create_window(button4_x, button_y, anchor=tk.CENTER, window=button4)

canvas.create_window(button1_x, button_y + button_height, anchor=tk.CENTER, window=label1)
canvas.create_window(button2_x, button_y + button_height, anchor=tk.CENTER, window=label2)
canvas.create_window(button3_x, button_y + button_height, anchor=tk.CENTER, window=label3)
canvas.create_window(button4_x, button_y + button_height, anchor=tk.CENTER, window=label4)

# 显示画布
canvas.pack()

# 运行主循环
window.mainloop()

问题

将ImageTk.PhotoImage()放在函数里图片不显示
不显示图片的代码如下:

def open_child_window():
    # 创建子窗口
    child_window = tk.Toplevel(window)
    child_window.attributes('-fullscreen', True)  # 设置子窗口为全屏显示
    child_window.geometry(
        "{0}x{1}+0+0".format(child_window.winfo_screenwidth(), child_window.winfo_screenheight()))  # 设置子窗口大小为屏幕大小
    # 添加子窗口的内容
    child_canvas = tk.Canvas(child_window, width=child_window.winfo_screenwidth(),
                             height=child_window.winfo_screenheight())

    # 在画布上创建背景图像
    child_canvas.create_image(child_window.winfo_screenwidth() / 2, child_window.winfo_screenheight() / 2,
                              image=scaled_bg_image)

    # 加载图片按钮图像
    video_button_image = tk.PhotoImage(file="videoshow.png")
    music_button_image = tk.PhotoImage(file="music.png")

    # 缩放图片按钮图像
    scaled_video_button_image = video_button_image.subsample(1, 1)  # 3倍缩放
    scaled_music_button_image = music_button_image.subsample(2, 2)

    # 布局图片按钮
    button_width = scaled_video_button_image.width()
    button_height = scaled_video_button_image.height()
    canvas_center_x = child_window.winfo_screenwidth() // 2
    button_y = (child_window.winfo_screenheight() - button_height * 2) // 2

    video_button_x = canvas_center_x - (button_width + 10) * 0.8
    music_button_x = canvas_center_x + (button_width + 10) * 0.8

    video_button = tk.Button(child_canvas, image=scaled_video_button_image, command=func5, borderwidth=0,
                             highlightthickness=0)
    music_button = tk.Button(child_canvas, image=scaled_music_button_image, command=func6, borderwidth=0,
                             highlightthickness=0)

    # 添加文字说明
    video_label = tk.Label(child_canvas, text="视频播放", font=("Arial", 20, "bold"), bg=child_canvas["bg"])
    music_label = tk.Label(child_canvas, text="音乐播放", font=("Arial", 20, "bold"), bg=child_canvas["bg"])

    # 显示图片按钮和文字说明
    child_canvas.create_window(video_button_x, button_y, anchor=tk.CENTER, window=video_button)
    child_canvas.create_window(music_button_x, button_y, anchor=tk.CENTER, window=music_button)

    child_canvas.create_window(video_button_x, button_y + button_height, anchor=tk.CENTER, window=video_label)
    child_canvas.create_window(music_button_x, button_y + button_height, anchor=tk.CENTER, window=music_label)

    # 添加返回主页的按钮
    home_button_image = tk.PhotoImage(file="return.png")
    scaled_home_button_image = home_button_image.subsample(4, 4)
    home_button = tk.Button(child_canvas, image=scaled_home_button_image, command=lambda: return_to_home(child_window),
                            borderwidth=0, highlightthickness=0)
    child_canvas.create_window(canvas_center_x, button_y + button_height * 2 + 20, anchor=tk.CENTER, window=home_button)

    # 显示画布
    child_canvas.pack()

运行后,图片并没有显示,究竟是怎么回事?

原因:在调用load_img()函数后,垃圾回收机制会把变量photo给回收了。
解决办法:使用global全局变量。如下(为了做对比,代码用图片展示):

def open_child_window():
    # 创建子窗口
    child_window = tk.Toplevel(window)
    child_window.attributes('-fullscreen', True)  # 设置子窗口为全屏显示
    child_window.geometry(
        "{0}x{1}+0+0".format(child_window.winfo_screenwidth(), child_window.winfo_screenheight()))  # 设置子窗口大小为屏幕大小
    # 添加子窗口的内容
    child_canvas = tk.Canvas(child_window, width=child_window.winfo_screenwidth(),
                             height=child_window.winfo_screenheight())

    # 在画布上创建背景图像
    child_canvas.create_image(child_window.winfo_screenwidth() / 2, child_window.winfo_screenheight() / 2,
                              image=scaled_bg_image)

    # 加载图片按钮图像
    video_button_image = tk.PhotoImage(file="videoshow.png")
    music_button_image = tk.PhotoImage(file="music.png")

    # 缩放图片按钮图像
    global scaled_video_button_image
    global scaled_music_button_image
    scaled_video_button_image = video_button_image.subsample(1, 1)  # 3倍缩放
    scaled_music_button_image = music_button_image.subsample(2, 2)

    # 布局图片按钮
    button_width = scaled_video_button_image.width()
    button_height = scaled_video_button_image.height()
    canvas_center_x = child_window.winfo_screenwidth() // 2
    button_y = (child_window.winfo_screenheight() - button_height * 2) // 2

    video_button_x = canvas_center_x - (button_width + 10) * 0.8
    music_button_x = canvas_center_x + (button_width + 10) * 0.8

    video_button = tk.Button(child_canvas, image=scaled_video_button_image, command=func5, borderwidth=0,
                             highlightthickness=0)
    music_button = tk.Button(child_canvas, image=scaled_music_button_image, command=func6, borderwidth=0,
                             highlightthickness=0)

    # 添加文字说明
    video_label = tk.Label(child_canvas, text="视频播放", font=("Arial", 20, "bold"), bg=child_canvas["bg"])
    music_label = tk.Label(child_canvas, text="音乐播放", font=("Arial", 20, "bold"), bg=child_canvas["bg"])

    # 显示图片按钮和文字说明
    child_canvas.create_window(video_button_x, button_y, anchor=tk.CENTER, window=video_button)
    child_canvas.create_window(music_button_x, button_y, anchor=tk.CENTER, window=music_button)

    child_canvas.create_window(video_button_x, button_y + button_height, anchor=tk.CENTER, window=video_label)
    child_canvas.create_window(music_button_x, button_y + button_height, anchor=tk.CENTER, window=music_label)

    # 添加返回主页的按钮
    home_button_image = tk.PhotoImage(file="return.png")
    global scaled_home_button_image
    scaled_home_button_image = home_button_image.subsample(4, 4)
    home_button = tk.Button(child_canvas, image=scaled_home_button_image, command=lambda: return_to_home(child_window),
                            borderwidth=0, highlightthickness=0)
    child_canvas.create_window(canvas_center_x, button_y + button_height * 2 + 20, anchor=tk.CENTER, window=home_button)

    # 显示画布
    child_canvas.pack()

只需要在声明变量scaled_video_button_image、scaled_music_button_image、scaled_home_button_image之前将它设为全局变量即可。
注意:global不要放在函数外面,否则会没效果。


http://lihuaxi.xjx100.cn/news/1966126.html

相关文章

想进入游戏开发领域,应该先学习C++编程还是C#编程?

想进入游戏开发领域,应该先学习C编程还是C#编程? 当你决心踏入游戏开发者的行列时,最先迎接你的将是引擎的选择。引擎是游戏的心脏,所有精彩的画面和内容都是脉脉游戏血液从引擎中流淌而出。Unity、Unreal Engine、Cocos等引擎盛…

构建基于RHEL8系列(CentOS8,AlmaLinux8,RockyLinux8等)的MySQL8.0.32的RPM包

本文适用:rhel8系列,或同类系统(CentOS8,AlmaLinux8,RockyLinux8等) 文档形成时期:2023年 因系统版本不同,构建部署应略有差异,但本文未做细分,对稍有经验者应不存在明显障碍。 因软件世界之复杂和个人能力…

虾皮开通:如何在虾皮(Shopee)平台上开通店铺详细步骤

在全球电商市场的竞争中,越来越多的卖家选择在虾皮(Shopee)平台上开设店铺。作为东南亚地区最大的电子商务平台之一,虾皮提供了一个便捷的销售渠道,吸引了数百万的买家和卖家。如果您想在虾皮上开设自己的店铺&#xf…

node-red实现ModBus-RTU 通信协议(RS485信号输出)的数据交互

node-red实现485型 - 温湿度变表数据转换 一、介绍二、 通讯协议2.1 通讯基本参数2.2 数据帧格式定义2.3 寄存器地址2.4 通讯协议示例以及解释 三、 node-red实现数据交互3.1 node-red读取数据3.2 node-red写回数据 本文参考《86 壳液晶温湿度变送器使用说明书(485 …

【ES6 Map数据结构】建议日常开发操作数组时使用 new Map

Map数据结构 new Map使用属性及方法:1. size属性2. set(key,value)3. get(key)4. has(key)5. delete(key)6. clear()7. 遍历方法: keys()、values()、entries()、forEach()(1). keys()(2). values()(3). entries()(4). forEach() 8. toString()9. valueOf 算法使用 …

深入探讨:开发连锁餐饮APP的关键技术要点

时下,开发一款功能强大、用户友好的连锁餐饮APP成为许多餐饮企业的当务之急。在本文中,我们将深入探讨开发连锁餐饮APP的关键技术要点,涵盖了前端、后端以及数据库等方面。 一、前端开发 前端是用户与APP交互的入口,因此设计良好…

Linux 多个php版本选择需要的php的版本(修改环境变量)

这两天遇到了个问题, 原本服务器的php版本是7.3.13,经过一些操作之后不知道怎么了变成了5.6 #php版本查看 php -v然后我就对 5.6版本进行了升级,升级到了7.3.33, 这个时候 php -v 是7.3.33, 神奇的一幕出现了&#xf…

大数据开发之Hive(压缩和存储)

第 9 章:压缩和存储 Hive不会强制要求将数据转换成特定的格式才能使用。利用Hadoop的InputFormat API可以从不同数据源读取数据,使用OutputFormat API可以将数据写成不同的格式输出。 对数据进行压缩虽然会增加额外的CPU开销,但是会节约客观…