I'm currently making a code that will do various things such as controlling motors etc but at one point I need to code to popup a video on vlc and exit the window when the video ended, the problem is that the window currently stays after the video ended and the whole code just freezes and I can't do anything past the video
I tried various things such as calculating the video length and call a self.close() when the timer hit but still the same thing
I also tried adding "--play-and-exit" to the vlc parameters but it still won't budge...
Here's the code if someone knows how to do it properly !
import PySimpleGUI as sg
import os
import sys
import platform
import time
from time import sleep
from PyQt5.QtCore import (QCoreApplication, QObject, QRunnable, QThread,
QThreadPool, pyqtSignal)
from PyQt5 import QtCore, QtGui, QtWidgets
import vlc
class Player(QtWidgets.QMainWindow):
def __init__(self, master=None):
QtWidgets.QMainWindow.__init__(self, master)
self.media_files = [
"Toxic.mp4",
]
self.current_index = 0
self.showFullScreen()
self.init_ui()
vlc_options = [
"--embedded-video",
"--play-and-exit",
"--autoscale",
"--fullscreen",
"--video-on-top",
"--verbose -1",
"--canvas-aspect 3:4",
"--no-canvas-padd"
]
self.instance = vlc.Instance(" ".join(vlc_options))
self.media = None
self.player = self.instance.media_player_new()
if platform.system() == "Linux":
self.player.set_xwindow(int(self.videoframe.winId()))
elif platform.system() == "Windows": # for Windows
self.player.set_hwnd(int(self.videoframe.winId()))
self.open_file(self.media_files[self.current_index])
def init_ui(self):
self.videoframe = QtWidgets.QFrame()
self.palette = self.videoframe.palette()
self.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(0, 0, 0))
self.videoframe.setPalette(self.palette)
self.videoframe.setAutoFillBackground(True)
self.setCentralWidget(self.videoframe)
def with_opencv(filename):
import cv2
video = cv2.VideoCapture(filename)
duration = video.get(cv2.CAP_PROP_POS_MSEC)
frame_count = video.get(cv2.CAP_PROP_FRAME_COUNT)
return duration, frame_count
def open_file(self, filename):
if not filename:
return
self.media = self.instance.media_new(filename)
self.player.set_media(self.media)
self.media.parse()
self.player.play()
def main():
layout = [[sg.Text('Test', font=("Helvetica", 30))],
[sg.Text('Clique sur le boutton <<Lancer>>', font=("Calibri", 20))],
[sg.Button('Lancer'), sg.Button('Sortie')]
]
window = sg.Window('02.05.2022', layout, size = (800, 480), element_justification="Center", finalize=True)
while True:
event, values = window.Read()
print(event, values)
if event in (sg.WINDOW_CLOSED, 'Sortie'):
break
if event in (sg.WINDOW_CLOSED, 'Lancer'):
app = QtWidgets.QApplication(sys.argv)
player = Player()
player.show()
sys.exit(app.exec_())
break
window.close()
if __name__ == '__main__':
main()
Thank you !
I have found the solution. This is the new main loop:
while True:
event, values = window.Read()
print(event, values)
if event in (sg.WINDOW_CLOSED, 'Sortie'):
break
if event in (sg.WINDOW_CLOSED, 'Lancer'):
app = QtWidgets.QApplication(sys.argv)
player = Player()
player.show()
# Wait for is_playing to register the fact that it is playing
time.sleep(0.1)
while True:
app.processEvents()
if not player.player.is_playing():
break
break
Instead of app.exec_(), it calls app.processEvents() in a loop and also checks if player stopped playing in that loop.
Related
I am using a simple GUI with PyQt5 in which I have 3 buttons to record, stop and play the audio. I have some know-how of the Tkinter GUI, but I am totally confused here in PyQt5. In Tkinter Buttons, I am using commands something like this:
record_btn = Button(voice_rec, text="Record Audio", command=lambda m=1: threading_rec(m))
# Stop button
stop_btn = Button(voice_rec, text="Stop Recording", command=lambda m=2: threading_rec(m))
# Play button
play_btn = Button(voice_rec, text="Play Recording", command=lambda m=3: threading_rec(m))
I tried this in Pyqt5 Buttons, but still not working:
self.record_btn = QPushButton('Record', self)
self.record_btn.clicked.connect(lambda: self.threading_rec(x=1))
self.record_btn.move(100, 70)
self.stop_btn = QPushButton('Stop', self)
self.stop_btn.clicked.connect(lambda: self.threading_rec(x=2))
self.stop_btn.move(200, 70)
self.play_btn = QPushButton('Play', self)
self.play_btn.clicked.connect(lambda: self.threading_rec(x=3))
self.play_btn.move(300, 70)
Here is my complete code:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
import sounddevice as sd
import queue
import soundfile as sf
import threading
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'Voice Recorder'
self.left = 400
self.top = 300
self.width = 500
self.height = 200
self.initUI()
# Create a queue to contain the audio data
q = queue.Queue()
# Declare variables and initialise them
recording = False
file_exists = False
# Fit data into queue
def callback(indata, frames, time, status):
q.put(indata.copy())
def threading_rec(x):
if x == 1:
# If recording is selected, then the thread is activated
t1 = threading.Thread(target=record_audio)
t1.start()
elif x == 2:
# To stop, set the flag to false
global recording
recording = False
messagebox.showinfo(message="Recording finished")
elif x == 3:
# To play a recording, it must exist.
if file_exists:
# Read the recording if it exists and play it
data, fs = sf.read("trial.wav", dtype='float32')
sd.play(data, fs)
sd.wait()
else:
# Display and error if none is found
messagebox.showerror(message="Record something to play")
def record_audio(self):
# Declare global variables
global recording
# Set to True to record
recording = True
global file_exists
# Create a file to save the audio
messagebox.showinfo(message="Recording Audio. Speak into the mic")
with sf.SoundFile("trial.wav", mode='w', samplerate=44100,
channels=2) as file:
# Create an input stream to record audio without a preset time
with sd.InputStream(samplerate=44100, channels=2, callback=callback):
while recording == True:
# Set the variable to True to allow playing the audio later
file_exists = True
# write into file
file.write(q.get())
# Button to record audio
record_btn = Button(voice_rec, text="Record Audio", command=lambda m=1: threading_rec(m))
# Stop button
stop_btn = Button(voice_rec, text="Stop Recording", command=lambda m=2: threading_rec(m))
# Play button
play_btn = Button(voice_rec, text="Play Recording", command=lambda m=3: threading_rec(m))
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
record_btn = QPushButton('Record', self)
record_btn.move(100, 70)
stop_btn = QPushButton('Stop', self)
stop_btn.move(200, 70)
play_btn = QPushButton('Play', self)
play_btn.move(300, 70)
button.clicked.connect(self.on_click)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Someone please help me with this code!
I'll try to answer this in a simple way.
Let's say you have a button like this:
def init_UI(self):
self.sum_button = QPushButton(text='sum')
self.sum_button.clicked.connect(lambda: self.get_sum(int_a, int_b))
def get_sum(self, int_a, int_b):
return int_a + int_b
I'm trying to play an online video using python-vlc library.
First, I was using a simple version of the player to test it out:
import vlc
#example url
url="https://player.vimeo.com/external/363536021.hd.mp4?s=6f6e87d86a49149479ebdab6c8bc421aa89f327c&profile_id=175&oauth2_token_id=57447761"
player = vlc.Instance().media_player_new()
player.set_media(vlc.Instance().media_new(url))
player.play()
while str(player.get_state()) != "State.Ended":
pass
player.stop()
It plays the while video from URL without any problems!
Now I wanted to use the more complex version with pyqt5 GUI (original source-code here):
import sys
import os.path
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPalette, QColor
from PyQt5.QtWidgets import QMainWindow, QWidget, QFrame, QSlider, QHBoxLayout, QPushButton, \
QVBoxLayout, QAction, QFileDialog, QApplication
import vlc
class Player(QMainWindow):
def __init__(self, videoUrl, master=None):
QMainWindow.__init__(self, master)
self.setWindowTitle("Media Player")
# creating a basic vlc instance
self.instance = vlc.Instance()
# creating an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.playableVideo = videoUrl
self.createUI()
self.isPaused = False
def createUI(self):
"""Set up the user interface, signals & slots
"""
self.widget = QWidget(self)
self.setCentralWidget(self.widget)
# In this widget, the video will be drawn
if sys.platform == "darwin": # for MacOS
from PyQt5.QtWidgets import QMacCocoaViewContainer
self.videoframe = QMacCocoaViewContainer(0)
else:
self.videoframe = QFrame()
self.palette = self.videoframe.palette()
self.palette.setColor (QPalette.Window,
QColor(0,0,0))
self.videoframe.setPalette(self.palette)
self.videoframe.setAutoFillBackground(True)
self.positionslider = QSlider(Qt.Horizontal, self)
self.positionslider.setToolTip("Position")
self.positionslider.setMaximum(5000)
self.positionslider.sliderMoved.connect(self.setPosition)
self.hbuttonbox = QHBoxLayout()
self.playbutton = QPushButton("Play")
self.hbuttonbox.addWidget(self.playbutton)
self.playbutton.clicked.connect(self.PlayPause)
self.stopbutton = QPushButton("Exit")
self.hbuttonbox.addWidget(self.stopbutton)
self.stopbutton.clicked.connect(self.Stop)
self.hbuttonbox.setAlignment(Qt.AlignHCenter)
self.vboxlayout = QVBoxLayout()
self.vboxlayout.addWidget(self.videoframe)
self.vboxlayout.addWidget(self.positionslider)
self.vboxlayout.addLayout(self.hbuttonbox)
self.widget.setLayout(self.vboxlayout)
self.timer = QTimer(self)
self.timer.setInterval(200)
self.timer.timeout.connect(self.updateUI)
def PlayPause(self):
"""Toggle play/pause status
"""
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.playbutton.setText("Play")
self.isPaused = True
else:
if self.mediaplayer.play() == -1:
self.OpenFile()
return
self.mediaplayer.play()
self.playbutton.setText("Pause")
self.timer.start()
self.isPaused = False
def Stop(self):
"""Stop player
"""
self.mediaplayer.stop()
self.playbutton.setText("Play")
def OpenFile(self, filename=None):
"""Open a media file in a MediaPlayer
"""
if filename is None:
filename = self.playableVideo
if not filename:
return
# create the media
if sys.version < '3':
filename = unicode(filename)
self.media = self.instance.media_new(filename)
# put the media in the media player
self.mediaplayer.set_media(self.media)
# parse the metadata of the file
self.media.parse()
# set the title of the track as window title
self.setWindowTitle(self.media.get_meta(0))
# the media player has to be 'connected' to the QFrame
# (otherwise a video would be displayed in it's own window)
# this is platform specific!
# you have to give the id of the QFrame (or similar object) to
# vlc, different platforms have different functions for this
if sys.platform.startswith('linux'): # for Linux using the X Server
self.mediaplayer.set_xwindow(self.videoframe.winId())
elif sys.platform == "win32": # for Windows
self.mediaplayer.set_hwnd(self.videoframe.winId())
elif sys.platform == "darwin": # for MacOS
self.mediaplayer.set_nsobject(int(self.videoframe.winId()))
self.PlayPause()
def setPosition(self, position):
self.mediaplayer.set_position(position / 1000.0)
def updateUI(self):
self.positionslider.setValue(self.mediaplayer.get_position() * 1000)
if not self.mediaplayer.is_playing():
self.timer.stop()
if not self.isPaused:
self.Stop()
if __name__ == "__main__":
app = QApplication(sys.argv)
player = Player("https://player.vimeo.com/external/363536021.hd.mp4?s=6f6e87d86a49149479ebdab6c8bc421aa89f327c&profile_id=175&oauth2_token_id=57447761")
player.show()
player.resize(640, 480)
if sys.argv[1:]:
player.OpenFile(sys.argv[1])
sys.exit(app.exec_())
This code keeps returning an access stream error: HTTP connection failure.
The problem is that as soon as you start playing the video it is not available since the download is not immediate but with your code you try to update the position. The solution is to update is to get the position after it started playing:
def updateUI(self):
if not self.mediaplayer.is_playing():
return
self.positionslider.setValue(self.mediaplayer.get_position() * 1000)
if not self.mediaplayer.is_playing():
self.timer.stop()
if not self.isPaused:
self.Stop()
I am making an Mp3 Player, and I am almost done, the only thing left is the time slider.
I managed to make the slider so that it can change the position/time of the audio, but I want the vice-versa now, the slider to be moved by the audio progress.
(Ignore this pls, they are asking for more details but I got none other to give, thanks)
My MRE:
import os
import vlc # version 3.0.10114
from PyQt5 import QtCore, QtGui, QtWidgets
from tkinter import Tk, filedialog # 8.6
from time import sleep
from pygame import mixer # version 1.9.6
class UiMainWindow:
def __init__(self, main_window):
self.main_window = main_window
mixer.init() # For the volume
self.vlc_instance = vlc.Instance()
media = self.vlc_instance.media_new('')
self.player = self.vlc_instance.media_player_new()
self.player.set_media(media)
self.main_window.setStyleSheet('background-color: gray')
self.main_window.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(self.main_window)
# Initiating the buttons and labels
self.add_new_song_button = QtWidgets.QPushButton(self.centralwidget)
self.add_new_song_button.setGeometry(QtCore.QRect(690, 50, 80, 24))
self.add_new_song_button.clicked.connect(self.add_song)
self.time_slider = QtWidgets.QSlider(self.centralwidget)
self.time_slider.setMinimum(0)
self.time_slider.setMaximum(10000)
self.time_slider.setValue(0)
self.time_slider.setSingleStep(1)
self.time_slider.setOrientation(QtCore.Qt.Horizontal)
self.time_slider.sliderMoved.connect(self.slider_moved)
# self.time_slider.valueChanged.connect(self.slider_changed)
self.time_slider.setGeometry(QtCore.QRect(200, 80, 400, 20))
# Initiating the lists and music
self.ui_song_list = QtWidgets.QListWidget(self.centralwidget)
self.ui_song_list.setGeometry(QtCore.QRect(10, 120, 780, 480))
self.ui_song_list.setEnabled(True)
self.ui_song_list.setStyleSheet('background-color: lightblue;')
self.current_audio = '' # To prevent errors when trying to play nothing
self.audio_paths = {}
self.ui_song_list.itemClicked.connect(self.play_song)
self.retranslate_ui(self.main_window)
QtCore.QMetaObject.connectSlotsByName(self.main_window)
def config_audio(self, audio=''): # Changes the song of the player
if not audio:
media = self.vlc_instance.media_new(audio)
else:
media = self.vlc_instance.media_new(self.audio_paths[audio])
self.player = self.vlc_instance.media_player_new()
self.player.set_media(media)
def play_song(self, song): # This is called when a song is clicked
self.current_audio = song.text()
self.player.stop()
self.config_audio(audio=self.current_audio)
self.player.play()
def add_song(self):
Tk().withdraw() # Creating the interface for choosing songs
filetypes = [('mp3 files', '*.mp3'), ('wav files', '*.wav')] # Only audio should pe added
list_of_chosen_audio = filedialog.askopenfilenames(title='Choose audio files', filetypes=filetypes)
for audio_path in list_of_chosen_audio:
audio_name = audio_path[:-4].split('/')[-1] # taking only the audio name without mp3 and audio_paths
self.audio_paths[audio_name] = audio_path
self.ui_song_list.addItem(audio_name)
self.all_songs = self.ui_song_list.findItems('', QtCore.Qt.MatchContains)
def slider_moved(self):
try:
self.player.set_position(self.time_slider.value()/10000) # / 10000 because the slider didnt work if lowered the maximum value
except Exception as e:
print(e)
def slider_changed(self):
if self.player.is_playing():
print(round(self.player.get_position()*10000, 2))
self.time_slider.setValue(round(self.player.get_position()*10000, 2))
self.player.set_position(self.time_slider.value()/10000)
def retranslate_ui(self, main_window): # Setting the text for all the buttons and labels
main_window.setCentralWidget(self.centralwidget)
main_window.setWindowTitle("MP3 Player")
self.add_new_song_button.setText("Add Songs")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = UiMainWindow(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Thanks in advance!
The slider has a setValue to set the slider position (0-1). To update the slider, add a timer to the app.
Update your code with the following changes:
class UiMainWindow:
def __init__(self, main_window):
..........
# timer to update slide bar
timer = QTimer(self.main_window)
timer.timeout.connect(self.time_hit)
timer.start(500) # 1/2 second
def time_hit(self):
if self.player.is_playing():
self.time_slider.setValue(self.player.get_position()*10000) # update slide bar
I am trying to use QMediaPlayer to create a.. media player. I want to have an ability to rewind videos on press of a button.
But setting a negative playbackRate via QMediaPlayer.setPlaybackRate doesn't seem to put video on rewind. It just keeps playing forward.
I don't want to change the position of the video, I want the video to play at negative speed. Through some logic of mine, setting playbackRate to a negative value would make the video play in reverse. But that just doesn't happen. If you can't understand me clearly, here is a video of what the playback should look like.
Here is some barebones code to reproduce the problem:
import sys
from PyQt5.QtCore import Qt, QUrl, QEvent
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication
class VideoWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
videoWidget = QVideoWidget()
self.setCentralWidget(videoWidget)
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.mediaPlayer.setVideoOutput(videoWidget)
self.mediaPlayer.setMedia(
QMediaContent(QUrl.fromLocalFile(r"<some video file>.mp4"))
)
self.mediaPlayer.play()
app.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.KeyPress:
key = event.key()
if key == Qt.Key_A:
self.mediaPlayer.setPlaybackRate(1.0)
elif key == Qt.Key_Y:
self.mediaPlayer.setPlaybackRate(-1.0) # This doesn't work! :(
return super().eventFilter(source, event)
def closeEvent(self, event):
self.mediaPlayer.setMedia(QMediaContent())
if __name__ == '__main__':
app = QApplication(sys.argv)
player = VideoWindow()
player.resize(640, 480)
player.show()
exitCode = app.exec_()
sys.exit(exitCode)
I tried searching for a solution, but I got nothing more than what documentation says (emphasis mine):
Values less than zero can be set and indicate the media will rewind at
the multiplier of the standard pace.
However, I am not seeing this effect.
I did notice this:
Not all playback services support change of the playback rate.
Is it possible that I can't rewind an mp4? Perhaps I need to install / change something?
QMediaPlayer.playbackRate property holds the playback rate of the current media.
This value is a multiplier applied to the media's standard play rate.
Press the Key_A, Key_Z, Key_Y keys to see how it works.
If you want to rewind the video, you should use QMediaPlayer.position property, which holds the playback position of the current media.
The value is the current playback position, expressed in milliseconds since the beginning of the media.
Press the Key_M, Key_P keys to see how it works.
import sys
from PyQt5.QtCore import Qt, QUrl, QEvent
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication
class VideoWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
videoWidget = QVideoWidget()
self.setCentralWidget(videoWidget)
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.mediaPlayer.setVideoOutput(videoWidget)
self.mediaPlayer.setMedia(
QMediaContent(QUrl.fromLocalFile(r"<some video file>.mp4"))
)
self.mediaPlayer.play()
app.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.KeyPress:
key = event.key()
# It Playback Rate !
if key == Qt.Key_A:
#self.mediaPlayer.setPlaybackRate(1.0)
self.mediaPlayer.setPlaybackRate(1.5)
elif key == Qt.Key_Z:
self.mediaPlayer.setPlaybackRate(0.8)
elif key == Qt.Key_Y:
self.mediaPlayer.setPlaybackRate(1.0)
# setPosition(int), argument is in milliseconds.
elif key == Qt.Key_M:
self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000)
elif key == Qt.Key_P:
self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000)
return super().eventFilter(source, event)
def closeEvent(self, event):
self.mediaPlayer.setMedia(QMediaContent())
if __name__ == '__main__':
app = QApplication(sys.argv)
player = VideoWindow()
player.resize(640, 480)
player.show()
exitCode = app.exec_()
sys.exit(exitCode)
I want to use python OpenCV bindings to display webcam stream in a QLabel. I found some previous posts here:
updating QLabel in non-GUI thread continuously
Displaying a video stream in QLabel with PySide
In the beginning I tried a simple "while" loop:
def onRun(self):
self.playing = True
capture = cv2.VideoCapture(0)
while self.playing:
_, data = capture.read()
data = cv2.cvtColor(data, cv2.cv.CV_BGR2RGB)
qImage = QtGui.QImage(data, data.shape[1], data.shape[0],
QtGui.QImage.Format_RGB888)
self.lblImage.setPixmap(QtGui.QPixmap.fromImage(qImage))
self.lblImage.adjustSize()
time.sleep(0.02)
But I met with a "white-window" problem. I found that proper way to solve this is to create a new thread. My question is: what is it all about new thread? should I create QThread or something? And what is it signal/slot emitting in a thread?
I've never used threads so it's totally new thing to me.
I can't test this myself, but would it not be enough to simply process the pending events within the loop?
That is:
def onRun(self):
self.playing = True
capture = cv2.VideoCapture(0)
while self.playing:
...
QtGui.qApp.processEvents()
time.sleep(0.02)
A solution is to use pyqtSignal. Here is an example:
import time
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
from PyQt5.QtGui import QPixmap, QImage
import sys
import threading
import numpy as np
class FakeCamera(QWidget):
"""Simulate a camera"""
image_taken = pyqtSignal(np.ndarray)
def __init__(self, callback, time_cost=0.01, image_shape=(256, 256)):
super(FakeCamera, self).__init__()
self.time_cost = time_cost # the time cost to take a frame, determine the frame rate
self.image_shape = image_shape
self.image_taken.connect(callback)
self._stop = threading.Event()
def start(self):
"""start a thread to take images"""
def run():
while not self._stop.is_set():
time.sleep(self.time_cost)
image = np.random.randint(0, 256, self.image_shape, np.uint8)
self.image_taken.emit(image)
threading.Thread(target=run).start()
def stop(self):
self._stop.set()
class WindowDemo(QWidget):
def __init__(self):
super(WindowDemo, self).__init__()
# label
self.label = QLabel()
self.label.setScaledContents(True)
self.label.setMinimumSize(1, 1)
# layout
vbox = QVBoxLayout()
vbox.addWidget(self.label)
self.setLayout(vbox)
# camera
self.camera = FakeCamera(self.show_image)
# start a thread to take images
self.camera.start()
#pyqtSlot(np.ndarray)
def show_image(self, image):
qimage = QImage(image, image.shape[1], image.shape[0], QImage.Format_Grayscale8)
self.label.setPixmap(QPixmap.fromImage(qimage))
def closeEvent(self, e):
self.camera.stop()
e.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
win = WindowDemo()
win.show()
sys.exit(app.exec_())