Python tkinter windows不';被摧毁后不要离开

Python tkinter windows不';被摧毁后不要离开,python,tkinter,raspberry-pi,focus,Python,Tkinter,Raspberry Pi,Focus,我正在编写一个python脚本,用于在触发输入时显示图像、播放音乐和在raspberry pi上显示视频。当我在这个项目上工作时,我决定在脚本中添加一个网络摄像头。我玩了不同的网络摄像头拖缆,直到我发现MPlayer似乎有最快的帧速率和使用最少的资源。问题是,MPlayer gui隐藏在我用来显示图像的tkinter窗口后面。我尝试了几种不同的方法将MPlayer窗口置于最前面,并使tkinter窗口消失,但似乎没有任何效果。这是我的密码: import sys import os import

我正在编写一个python脚本,用于在触发输入时显示图像、播放音乐和在raspberry pi上显示视频。当我在这个项目上工作时,我决定在脚本中添加一个网络摄像头。我玩了不同的网络摄像头拖缆,直到我发现MPlayer似乎有最快的帧速率和使用最少的资源。问题是,MPlayer gui隐藏在我用来显示图像的tkinter窗口后面。我尝试了几种不同的方法将MPlayer窗口置于最前面,并使tkinter窗口消失,但似乎没有任何效果。这是我的密码:

import sys
import os
import time
import subprocess
import RPi.GPIO as GPIO
if sys.version_info[0] == 2:
    import Tkinter
    tkinter = Tkinter
else:
    import tkinter
from PIL import Image, ImageTk
import board
import neopixel

x=1
GPIO.setmode(GPIO.BCM)
pixels = neopixel.NeoPixel(board.D10, 38)
pixels.fill((0, 0, 0))
GPIO.setwarnings(False)
GPIO.setup(17,GPIO.OUT)
GPIO.setup(18,GPIO.OUT)
GPIO.setup(27,GPIO.OUT)
GPIO.setup(22,GPIO.OUT)
GPIO.setup(24,GPIO.OUT)
GPIO.setup(25,GPIO.OUT)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.output(17,GPIO.LOW)
GPIO.output(18,GPIO.LOW)
GPIO.output(27,GPIO.LOW)
GPIO.output(22,GPIO.LOW)
GPIO.output(24,GPIO.LOW)
GPIO.output(25,GPIO.LOW)

def showPIL(pilImage, exVar = 0):
    try:
        root.withdraw()
        root.destroy()
        root.update()
    except:
        pass
    root = tkinter.Toplevel()
    if x == 1:
        w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    else:
        w, h = 100, 100
    root.overrideredirect(1)
    root.geometry("%dx%d+0+0" % (w, h))
    #root.focus_set()
    root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
    canvas = tkinter.Canvas(root,width=w,height=h)
    canvas.pack()
    canvas.configure(background='black')
    imgWidth, imgHeight = pilImage.size
    if imgWidth > w or imgHeight > h:
        ratio = min(w/imgWidth, h/imgHeight)
        imgWidth = int(imgWidth*ratio)
        imgHeight = int(imgHeight*ratio)
        pilImage = pilImage.resize((imgWidth,imgHeight), Image.ANTIALIAS)
    image = ImageTk.PhotoImage(pilImage)
    imagesprite = canvas.create_image(w/2,h/2,image=image)
    root.update()

showPIL(Image.open("Data/blank.png"))
while not GPIO.input(4):
    pass
music = subprocess.Popen(['cvlc', '/home/pi/Desktop/Data/music.mp3'])
showPIL(Image.open("Data/trophy.png"))
time.sleep(1)
GPIO.output(22,GPIO.HIGH)
time.sleep(0.5)
GPIO.output(27,GPIO.HIGH)
time.sleep(0.5)
GPIO.output(18,GPIO.HIGH)
time.sleep(0.5)
GPIO.output(17,GPIO.HIGH)
time.sleep(1)
showPIL(Image.open("Data/poison.png"))
pixels.fill((0, 255, 0))
os.system("pkill tk")
x=0
showPIL(Image.open("Data/blank.png"))
x=1
camera = subprocess.Popen(['mplayer', '-fs', 'tv://'])
os.system("wmctrl -a MPlayer")
time.sleep(8)
camera.kill()
os.system("omxplayer -b '/home/pi/Desktop/Data/movie.mp4'")
showPIL(Image.open("Data/gun.png"))
GPIO.output(24,GPIO.HIGH)
GPIO.output(25,GPIO.HIGH)
while not GPIO.input(23):
    pass
pixels.fill((0, 0, 0))
showPIL(Image.open("Data/dumbell.png"))
time.sleep(1)
showPIL(Image.open("Data/pipe.png"))
time.sleep(1)
showPIL(Image.open("Data/noose.png"))
time.sleep(1)
music.kill()
showPIL(Image.open("Data/blank.png"))
end = subprocess.Popen(['cvlc', '/home/pi/Desktop/Data/end.wav'])
time.sleep(8)
end.kill()
导入系统 导入操作系统 导入时间 导入子流程 将RPi.GPIO导入为GPIO 如果系统版本信息[0]==2: 进口Tkinter tkinter=tkinter 其他: 进口tkinter 从PIL导入图像,ImageTk 进口局 进口Neopix x=1 GPIO.setmode(GPIO.BCM) 像素=新像素。新像素(board.D10,38) 像素。填充((0,0,0)) GPIO.setwarnings(False) GPIO.setup(17,GPIO.OUT) GPIO.setup(18,GPIO.OUT) GPIO.setup(27,GPIO.OUT) GPIO.setup(22,GPIO.OUT) GPIO.setup(24,GPIO.OUT) GPIO.setup(25,GPIO.OUT) GPIO.setup(23,GPIO.IN,pull\u up\u down=GPIO.PUD\u down) GPIO.setup(4,GPIO.IN,pull\u up\u down=GPIO.PUD\u down) GPIO.setup(5,GPIO.IN,pull\u up\u down=GPIO.PUD\u down) GPIO.输出(17,GPIO.低) GPIO.输出(18,GPIO.低) GPIO.输出(27,GPIO.低) GPIO.输出(22,GPIO.低) GPIO.输出(24,GPIO.低) GPIO.输出(25,GPIO.低) def showPIL(pilImage,exVar=0): 尝试: root.draw() root.destroy() root.update() 除: 通过 root=tkinter.Toplevel() 如果x==1: w、 h=root.winfo_屏幕宽度(),root.winfo_屏幕高度() 其他: w、 h=100100 root.overrideredirect(1) 根几何体(“%dx%d+0+0”%(w,h)) #root.focus_set() root.bind(“,lambda e:(e.widget.draw(),e.widget.quit()) canvas=tkinter.canvas(根,宽度=w,高度=h) canvas.pack() canvas.configure(background='black') imgWidth,imgHeight=pilImage.size 如果imgWidth>w或imgHeight>h: 比值=最小值(宽/内径,高/内径) imgWidth=int(imgWidth*比率) imgHeight=int(imgHeight*比率) pilImage=pilImage.resize((imgWidth,imgHeight),Image.ANTIALIAS) image=ImageTk.PhotoImage(pilImage) imagesprite=canvas.create_image(w/2,h/2,image=image) root.update() showPIL(Image.open(“Data/blank.png”)) 而不是GPIO.input(4): 通过 music=subprocess.Popen(['cvlc','/home/pi/Desktop/Data/music.mp3'])) showPIL(Image.open(“Data/trophy.png”)) 时间。睡眠(1) GPIO.输出(22,GPIO.高) 睡眠时间(0.5) GPIO.输出(27,GPIO.高) 睡眠时间(0.5) GPIO.输出(18,GPIO.高) 睡眠时间(0.5) GPIO.输出(17,GPIO.高) 时间。睡眠(1) showPIL(Image.open(“Data/poison.png”)) 像素。填充((0,255,0)) 操作系统(“pkill-tk”) x=0 showPIL(Image.open(“Data/blank.png”)) x=1 camera=subprocess.Popen(['mplayer','-fs','tv://'])) 操作系统(“wmctrl-a MPlayer”) 时间。睡眠(8) 照相机 系统(“omxplayer-b'/home/pi/Desktop/Data/movie.mp4') showPIL(Image.open(“Data/gun.png”)) GPIO.输出(24,GPIO.高) GPIO.输出(25,GPIO.高) 虽然不是GPIO.input(23): 通过 像素。填充((0,0,0)) showPIL(Image.open(“Data/dumbell.png”)) 时间。睡眠(1) showPIL(Image.open(“Data/pipe.png”)) 时间。睡眠(1) showPIL(Image.open(“Data/noose.png”)) 时间。睡眠(1) 音乐杀人 showPIL(Image.open(“Data/blank.png”)) end=subprocess.Popen(['cvlc','/home/pi/Desktop/Data/end.wav'])) 时间。睡眠(8) end.kill()
好的,这里有几个关键问题

一个大问题是您的
try/except
语句

您的尝试总是要通过
。永远不会有这样一个时刻,你可以
销毁()
一些东西,然后调用
更新()
。这将始终导致错误,因此将运行
pass
的except语句

下一步
root=tkinter.Toplevel()
是一个问题。由于您从未定义tkinter实例或根目录,因此您创建了一个顶级窗口,这将导致tkinter实例被打开,但没有变量名可供使用。这里所说的根仅在函数的本地定义,因此,每当再次调用函数时,函数都不会尝试销毁根的记录,因为据函数所知,它尚未创建。对于类似这样的情况,您需要将根定义为
全局
变量

即使这对你有效,也应该有两个问题。一个是显示一个额外的空白窗口,第二个是当您关闭顶层窗口时,该窗口不会自动关闭

接下来,您将尝试在运行tkinter实例的同时使用
sleep
。如果不使用线程,这些东西是不兼容的,因此您需要将线程引入到这个系统中,或者更好地学习如何使用
after()
After()
是tkinter管理定时事件的方式


在这里,您需要使用
Tk()
,而不是使用
Toplevel()
。与其每次更新都破坏和重建GUI,不如只更新窗口。在您尝试做的事情的范围内,您可能应该在尝试raspberry pi项目之前更多地使用tkinter,并了解事件管理器是如何工作的。一旦您掌握了Tkinter GUI及其基于事件的流程,您将能够更轻松地完成更复杂的工作。

@Goyo在我声明函数showPIL后,代码试图破坏窗口。很抱歉,代码太长了,我不想在outIn showPil中留下任何东西。如果您引用的是一个没有声明的“root”(您通过传递捕获异常,因此python没有告诉您;))应该关闭窗口的行是try:root.draw()root.destroy()root.update(),除了: