How can I use PyQt5/PySide or any other Python library to display a desired image on a secondary monitor in full-screen mode? In the past, I used a framebuffer image viewer (Fbi and Fbi improved). However, this approach requires me to use Linux. I prefer to work in Windows and preferably find a solution using Python.
Motivation/Context
I am working on a DLP projection based 3D printing process. When I connect a DLP projector to my Windows PC using HDMI, it shows up as a second monitor. I want to dedicate this secondary monitor (DLP) only to display my desired patterns images (png, bmp, or svg) for the 3D printing process. I would like to programmatically control using Python which image is being displayed.
This is a followup question to https://3dprinting.stackexchange.com/questions/1217/how-to-display-images-on-dlp-using-hdmi-for-3d-printing
Partial solution and issues
Below code is one possible solution, however I am unsure if its the correct or the most efficient approach. I found two approaches using PyQt5: 1) using splash screen, and 2) using QLabel. I am facing the following issues with my code:
Cursor is hidden as expected, however if I accidentally click mouse on secondary screen, the splash screen closes.
If I use the QLabel approach, I see a white screen appear and then my image gets loaded. There is a distinct delay of ~ 0.5-1s from the time white screen appears to when the actual image is displayed.
If the images are displayed in high frequency (ex: every 1 sec), this code doesn't work well. For example, in the code change the total_loops=1 to total_loops=25. When using splash screen method, I see the splash screen appear on the main screen then it moves to the secondary screen. When using the QLabel method, all I see is a white screen appear, and only the last iteration the image is displayed. In addition, the window of the QLabel becomes active on the main screen and is visible in the Task bar.
How do I handle a situation if I want to display a video instead of an image?
For 3D printing application, the solution needs to meet the following requirement:
Secondary screen is the DLP projector, and it should NOT contain any OS related windows/taskbars/etc...
No cursor/mouse or other applications should appear on the the secondary screen
Images/videos need to be displayed in fullscreen mode
When displaying or updating images on the secondary screen, there should be no disturbance on the primary screen. For example, the image window in secondary screen shouldn't take focus away from currently active window in the primary screen
import time
start_time = time.time()
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QSplashScreen
from PyQt5.QtGui import QPixmap, QCursor
from PyQt5.QtCore import Qt
import os
app = QApplication(sys.argv)
total_loops = 1
for i in range(total_loops):
# https://doc.qt.io/qtforpython/index.html
# https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html
s = app.screens()[1] # Get the secondary screen
# Display info about secondary screen
print('Screen Name: {} Size: {}x{} Available geometry {}x{} '.format(s.name(), s.size().width(), s.size().height(), s.availableGeometry().width(), s.availableGeometry().height()))
# Hide cursor from appearing on screen
app.setOverrideCursor(QCursor(Qt.BlankCursor)) # https://forum.qt.io/topic/49877/hide-cursor
# Select desired image to be displayed
pixmap = QPixmap('test.png')
# Splash screen approach
# https://doc.qt.io/qtforpython/PySide2/QtWidgets/QSplashScreen.html?highlight=windowflags
splash = QSplashScreen(pixmap) # Set the splash screen to desired image
splash.show() # Show the splash screen
splash.windowHandle().setScreen(s) # Set splash screen to secondary monitor https://stackoverflow.com/a/30597458/4988010
splash.showFullScreen() # Show in splash screen in full screen mode
# # Qlabel apporach
# l = QLabel()
# l.setPixmap(pixmap)
# l.move(1920,0)
# l.show()
# l.windowHandle().setScreen(s) # https://stackoverflow.com/a/30597458/4988010
# l.showFullScreen()
time.sleep(0.5)
end_time = time.time()
print('Execution time: ', end_time-start_time )
sys.exit(app.exec_())
The code below is one possible solution to my question. My solution assumes that Qt is only used to display the images in full-screen and not for the remaining logic. Therefore, I had to run the QT app in a secondary thread. This is because the moment I run the function app.exec_(), Qt will continuously run an event loop thus blocking the rest of my Python logic which does NOT rely on Qt. It is my understanding running QApplication outside of a main thread is not recommended, therefore I would welcome a more experienced user to post a better approach.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QObject, pyqtSignal
import sys
import time
import threading
def main():
print('Step 1')
print(' Some logic here without QT')
print('Step 2')
print(' Launch QT app to run in background')
myapp = myImageDisplayApp()
print('Step 3')
print(' Continue some logic while QT running in background')
time.sleep(2)
print('Step 4')
print(' Update the displayed image in the QT app running in background')
myapp.emit_image_update('qt_test_static_1.png')
time.sleep(2)
print('Step 5')
print(' Update displayed image again')
myapp.emit_image_update('qt_test_static_2.png')
time.sleep(2)
class myImageDisplayApp (QObject):
# Define the custom signal
# https://www.riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html#the-pyqtslot-decorator
signal_update_image = pyqtSignal(str)
def __init__ (self):
super().__init__()
# Setup the seperate thread
# https://stackoverflow.com/a/37694109/4988010
self.thread = threading.Thread(target=self.run_app_widget_in_background)
self.thread.daemon = True
self.thread.start()
def run_app_widget_in_background(self):
self.app = QApplication(sys.argv)
self.my_bg_qt_app = qtAppWidget(main_thread_object=self)
self.app.exec_()
def emit_image_update(self, pattern_file=None):
print('emit_image_update signal')
self.signal_update_image.emit(pattern_file)
class qtAppWidget (QLabel):
def __init__ (self, main_thread_object):
super().__init__()
# Connect the singal to slot
main_thread_object.signal_update_image.connect(self.updateImage)
self.setupGUI()
def setupGUI(self):
self.app = QApplication.instance()
# Get avaliable screens/monitors
# https://doc.qt.io/qt-5/qscreen.html
# Get info on selected screen
self.selected_screen = 0 # Select the desired monitor/screen
self.screens_available = self.app.screens()
self.screen = self.screens_available[self.selected_screen]
self.screen_width = self.screen.size().width()
self.screen_height = self.screen.size().height()
# Create a black image for init
self.pixmap = QPixmap(self.screen_width, self.screen_height)
self.pixmap.fill(QColor('black'))
# Create QLabel object
self.app_widget = QLabel()
# Varioius flags that can be applied to make displayed window frameless, fullscreen, etc...
# https://doc.qt.io/qt-5/qt.html#WindowType-enum
# https://doc.qt.io/qt-5/qt.html#WidgetAttribute-enum
self.app_widget.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus | Qt.WindowStaysOnTopHint)
# Hide mouse cursor
self.app_widget.setCursor(Qt.BlankCursor)
self.app_widget.setGeometry(0, 0, self.screen_width, self.screen_height) # Set the size of Qlabel to size of the screen
self.app_widget.setWindowTitle('myImageDisplayApp')
self.app_widget.setAlignment(Qt.AlignLeft | Qt.AlignTop) #https://doc.qt.io/qt-5/qt.html#AlignmentFlag-enum
self.app_widget.setPixmap(self.pixmap)
self.app_widget.show()
# Set the screen on which widget is on
self.app_widget.windowHandle().setScreen(self.screen)
# Make full screen
self.app_widget.showFullScreen()
def updateImage(self, pattern_file=None):
print('Pattern file given: ', pattern_file)
self.app_widget.clear() # Clear all existing content of the QLabel
self.pixmap = QPixmap(pattern_file) # Update pixmap with desired image
self.app_widget.setPixmap(self.pixmap) # Show desired image on Qlabel
if __name__ == "__main__":
main()
I would also like to thank #ekhumoro for pointing me to QWidget attributes/flags.
You should not run the GUI in other than the main thread since Qt does not guarantee that it works correctly as indicated by the docs. Instead of executing the GUI in another thread, you must execute the other heavy tasks in another thread.
You have to change your approach to classical sequential logic but you must use event-oriented programming where actions are taken before an event, in the case of Qt through signals.
Considering the above, the solution is:
import sys
import time
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, Qt, QThread, QTimer
from PyQt5.QtGui import QColor, QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
class TaskManager(QObject):
task3Finished = pyqtSignal()
task4Finished = pyqtSignal()
#pyqtSlot()
def task3(self):
print("Step 3")
print(" Continue some logic while QT running in background")
time.sleep(2)
self.task3Finished.emit()
#pyqtSlot()
def task4(self):
print("Step 4")
print(" Update the displayed image in the QT app running in background")
time.sleep(2)
self.task4Finished.emit()
class qtAppWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setupGUI()
def setupGUI(self):
self.app = QApplication.instance()
# Get avaliable screens/monitors
# https://doc.qt.io/qt-5/qscreen.html
# Get info on selected screen
self.selected_screen = 0 # Select the desired monitor/screen
self.screens_available = self.app.screens()
self.screen = self.screens_available[self.selected_screen]
self.screen_width = self.screen.size().width()
self.screen_height = self.screen.size().height()
# Create a black image for init
self.pixmap = QPixmap(self.screen_width, self.screen_height)
self.pixmap.fill(QColor("black"))
# Create QLabel object
self.app_widget = QLabel()
# Varioius flags that can be applied to make displayed window frameless, fullscreen, etc...
# https://doc.qt.io/qt-5/qt.html#WindowType-enum
# https://doc.qt.io/qt-5/qt.html#WidgetAttribute-enum
self.app_widget.setWindowFlags(
Qt.FramelessWindowHint
| Qt.WindowDoesNotAcceptFocus
| Qt.WindowStaysOnTopHint
)
# Hide mouse cursor
self.app_widget.setCursor(Qt.BlankCursor)
self.app_widget.setGeometry(
0, 0, self.screen_width, self.screen_height
) # Set the size of Qlabel to size of the screen
self.app_widget.setWindowTitle("myImageDisplayApp")
self.app_widget.setAlignment(
Qt.AlignLeft | Qt.AlignTop
) # https://doc.qt.io/qt-5/qt.html#AlignmentFlag-enum
self.app_widget.setPixmap(self.pixmap)
self.app_widget.show()
# Set the screen on which widget is on
self.app_widget.windowHandle().setScreen(self.screen)
# Make full screen
self.app_widget.show()
#pyqtSlot()
def on_task3_finished(self):
pixmap = QPixmap("qt_test_static_1.png")
self.app_widget.setPixmap(pixmap)
#pyqtSlot()
def on_task4_finished(self):
pixmap = QPixmap("qt_test_static_2.png")
self.app_widget.setPixmap(pixmap)
# quit application after to 2 secons
QTimer.singleShot(2 * 1000, QApplication.quit)
def main(args):
print("Step 1")
print(" Some logic here without QT")
print("Step 2")
print(" Launch QT app to run")
app = QApplication(args)
myapp = qtAppWidget()
thread = QThread()
thread.start()
manager = TaskManager()
# move the QObject to the other thread
manager.moveToThread(thread)
manager.task3Finished.connect(myapp.on_task3_finished)
manager.task3Finished.connect(manager.task4)
manager.task4Finished.connect(myapp.on_task4_finished)
# start task
QTimer.singleShot(0, manager.task3)
ret = app.exec_()
thread.quit()
thread.wait()
del thread, app
return ret
if __name__ == "__main__":
sys.exit(main(sys.argv))
Related
I'm new to Python and have mostly learnt C# in the past. I am creating a QWidget class:
class Window(QWidget):
def __init__(self, gif, width, height):
super().__init__()
self.setGeometry(400, 200, width, height)
self.setWindowTitle("Python Run GIF Images")
self.setWindowIcon(QIcon('icons/qt.png'))
label = QLabel(self)
movie = QMovie(gif)
label.setMovie(movie)
movie.start()
And then define a function that creates a QApplication and then the Window:
def run_gif(gif, width, height):
app = QApplication([])
window = Window(gif, width, height)
window.show()
app.exec()
app.shutdown()
My issue is getting the gif to show topmost when it is launched. There is a Topmost property you can set on a Winform in C# which means no other window or other app you click on will cover the Window. This isn't essential but I want it to at least be shown above the code editor it is launched from so that the user doesn't have to select the Window to see the gif contained in the Window. I've spent hours looking at properties I can set either in the class or the method and not getting the result I need.
However, when I call the run_gif method for the second time, it does show it topmost, but along with the below exception (at least I think it's an exception from what I'm reading, it doesn't affect the running of the program other than printing to the console).
QApplication::regClass: Registering window class 'Qt640ScreenChangeObserverWindow' failed. (Class already exists.)
The only advice I can find on this error is not Python-specific and I don't really understand it. Maybe I'm being a bit ambitious for my early stage learning Python but not really seeing anything much on this error.
This is using PySide6.
Using setWindowFlag(Qt.WindowType.WindowStaysOnTopHint, True) seems to be working for me so far.
Example:
from PySide6.QtWidgets import *
from PySide6.QtCore import *
from PySide6.QtGui import *
class Window(QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.layout = QVBoxLayout(self)
self.resize(200,100)
self.label = QLabel("Always on top...")
self.layout.addWidget(self.label)
self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint, True) # <--
if __name__ == '__main__':
app = QApplication([])
window = Window()
window.show()
app.exec()
I'm trying to figure out how to use Signal to send custom messages/commands between widgets. I've been up and down all kinds of sources and I still can't figure it out.
The base purpose is that, I want to set a picture in GUI (custom button) that when I click on it, it changes the index number of a stacked widget. But to simplify, I figured click on image, it just prints a message, like 'hi' --> But even better would be if that message could be a predefined string (ala, the index number that I want to connect my image to)
I have so many setups but I'm going to try and write here what I think is my best.
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
import sys
from PIL import Image, ImageQt
def just_go():
app.exit()
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
screen = app.primaryScreen()
size = screen.size()
# <Code that sizes the window based on screensize>
program_window = window.size()
if program_window.width() > 200 and program_window.height() > 100:
s_exit = QtWidgets.QPushButton(text="Quit", parent=window)
s_exit.setGeometry(program_window.width() - 140, program_window.height() - 50, 120, 30)
s_exit.clicked.connect(just_go)
image = ImageQt(Image.open('file'))
clicker = QLabel(window)
clicker.setPixmap(image)
b_buffer = QWidget(window)
foreground = QStackedLayout()
page_0 = QWidget()
page_1 = QWidget()
page_2 = QWidget()
foreground.addWidget(page_0)
foreground.addWidget(page_1)
foreground.addWidget(page_2)
b_buffer.setLayout(foreground)
window.show()
sys.exit(app.exec_())
and then:
def switch_tabs(page):
foreground.setCurrentIndex(page)
Now I'm trying to make my project modular, so the actual file is in multiple python files but how would I make a Signal in one widget that emits to another? And then have a function run whenever that signal is sent?
In PyQt4, is there a way to suspend resize of a window until a function is completed?
My problem is that I have created a window with a text edit that might contain large amounts of text. Since I switched to working with a grid layout, the text edit gets resized as well, and when there is a lot of text, the application hangs. I tried overriding resizeEvent to clear text edit text at resize but the application still hangs, since it is clearing the text only AFTER resizing.
Other solutions are welcomed as well.
The python code (and a link to the .ui file):
import sys
from PyQt4 import QtGui, uic, QtCore
from PyQt4.QtGui import QDesktopWidget
qtCreatorMainWindowFile = "mainwindow.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorMainWindowFile)
class MainWindow(QtBaseClass, Ui_MainWindow):
def __init__(self):
QtBaseClass.__init__(self)
self.setupUi(self)
# Set window size to 4/5 of the screen dimensions
sg = QDesktopWidget().screenGeometry()
self.resize(sg.width()*4/5, sg.height()*4/5)
self.clearTextBrowserButton.clicked.connect(self.ClearTextBrowsers)
#staticmethod
def WriteToTextBrowser(string, text_browser):
cursor = text_browser.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertText(string)
text_browser.setTextCursor(cursor)
text_browser.ensureCursorVisible()
def ClearTextBrowsers(self):
self.textBrowser.clear()
# def resizeEvent(self,event):
# print "resize"
# self.ClearTextBrowsers()
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
for i in range(1,100000):
window.WriteToTextBrowser("TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST\r\n",window.textBrowser)
sys.exit(app.exec_())
The ui. file:
https://www.dropbox.com/s/y3hxp6mjhfpv2hy/mainwindow.ui?dl=0
I found a workaround that seems to work so far. I added an event filter that catches "Move" or "WindowStateChange" QEvents. These seem to happen before the actual resize (the prior works for clicking and stretching and the latter for maximizing/minimizing). The downside is that simply moving the window clears the text edit, but it is a price I'm willing to pay.
The added code (inside MainWindow):
self.installEventFilter(self)
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.Move or event.type() == QtCore.QEvent.WindowStateChange):
self.file.write(self.textBrowser.toPlainText())
self.ClearTextBrowsers()
return QtBaseClass.eventFilter(self, source, event)
I have a main window, I use another window to get some values and i want to display those values in the main window, kinda like how an alarm clock would work. At first it will be empty and then second window lets you choose the time and then after that is done, I want these data to be displayed on the first window.
I want this to work similarly to how the Qmessagebox works.
def Add_new_schedule(self):
if(self.TABLE_LENGTH == 5):
self.TOAST_WARNING.setText("LIMIT REACHED!")
else:
from Clock import Ui_Clock
self.CLOCK_WINDOW = Ui_Clock()
self.CLOCK_WINDOW.show()
Here, the clock window is called, and after setting the values there, on clicking a button 'Ok' that signal connects to a function in the main window.
def Get_clock_values(self, TIME_DETAILS):
DATA = {}
DATA['index'] = len(self.DATA_FROM_DB)+1
DATA['start_time'] = TIME_DETAILS[0]
DATA['end_time'] = TIME_DETAILS[1]
DATA['mode'] = TIME_DETAILS[2]
DATA['node_1'] = True
DATA['node_2'] = True
DATA['node_3'] = True
DATA['node_4'] = True
self.DATA_FROM_DB.append(DATA)
self.Clear_table()
self.Set_table()
The DATA_FROM_DB is a list of dictionaries of the available schedules and I'm able to successfully append the new values inside this list.
The Clear_Table() clears the existing widgets to blank and the Set_table() is supposed to Create the new table with the newly modified list(DATA_FROM_DB).
I am able to modify the table with this logic as long as a second window is not called, i.e appending some hard coded values in the list and then modifying the table. However, with my current code, the table exists in its original state.
Since your question is too broad I'll be giving you an example that:
Have the main window with a button and a disabled line.
The button makes it shows a second window.
Put information inside the line of the 2nd window.
This line of the 2nd window updates the line in the main window in real time.
This is happening by signals emission.
So you have something like that:
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
class MainWidget(QWidget):
def __init__(self):
super(MainWidget, self).__init__()
self.setFixedSize(500,500)
self.window2 = Window2(self)
self.btn_show_window2 = QPushButton("Open Window 2")
self.btn_show_window2.clicked.connect(self.show_window2)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.text_from_window2 = QLineEdit()
self.text_from_window2.setStyleSheet("color: red;")
self.text_from_window2.setDisabled(True)
self.layout.addWidget(self.text_from_window2)
self.layout.addWidget(self.btn_show_window2)
def show_window2(self):
self.window2.show()
def close(self):
self.window2.close()
super(MainWidget, self).close()
#pyqtSlot(str)
def update_label(self, txt):
self.text_from_window2.setText(txt)
class Window2(QWidget):
def __init__(self, parent):
super(Window2, self).__init__()
self.setFixedSize(300,200)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.line_edit = QLineEdit()
self.line_edit.textChanged.connect(parent.update_label)
self.layout.addWidget(self.line_edit)
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWidget()
mw.show()
sys.exit(app.exec_())
Note: You have a 'million' ways to do that, this is just one of many approaches you can follow. For example instead of using the textChanged you could also have another button in the second window and only send the text back when clicking on it, in the same way the button from the first window makes the second appear.
I'm very new to Python and I have made a very simple countdown timer. The GUI was created in Qt Designer. There is a spin box for input of seconds, a start button and an LCD number counter. The counter counts down fine using the code below:
def start_btn_clicked(self):
x = self.Minute_spinBox.value()
for i in xrange(x,0,-1):
time.sleep(1)
print (i)
So that I could see what was happening as I played around with it, I added the print instruction so that it shows the countdown in the Python console as it runs. I then thought I could maybe quite easily have the LCD number display the countdown with something like:
self.lcdNumber.display(i)("%SS")
But no matter what I try, I cant get it to show. With the line above, I get the first number displayed, but then I get an error saying:
self.lcdNumber.display(i)("%SS")
TypeError: 'NoneType' object is not callable
I have tried so many variations that I no longer know where I started and here was me thinking it would be simple. I'd love to know why I cant get it to display the countdown.
Just adding one line of code to my original code will allow the lcdNumber to display the count...
def start_btn_clicked(self):
x = self.Minute_spinBox.value()
for i in xrange(x,0,-1):
time.sleep(1)
app.processEvents() # just this one line allows display of 'i'
self.lcdNumber.display(i)`
And works perfectly
The display function returns None, so doing None("%SS") obviously isn't allowed.
self.lcdNumber.display(i) is enough to show the countdown!
To let Qt paint the widgets while looping run the countdown from another thread. See an example.
import time
from threading import Thread
from PyQt4.QtGui import QApplication, QMainWindow, QLCDNumber
class Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.lcdnumber = QLCDNumber(self)
self.resize(400, 400)
t = Thread(target=self._countdown)
t.start()
def _countdown(self):
x = 10
for i in xrange(x,0,-1):
time.sleep(1)
self.lcdnumber.display(i)
if __name__ == "__main__":
app = QApplication([])
window = Window()
window.show()
app.exec_()
The for loop is blocking the GUI.
The slot connected to the button's clicked signal is processed synchronously. This means the event-loop must wait for the slot to return before it can process any more events (including the paint events needed for updating the GUI).
So you need to find a way to process these events whilst the for loop is running. There are various ways of doing this, such as using a QTimer or a QThread. But the simplest way of fixing your particular example would be to use QCoreApplication.processEvents.
Here's an example that shows how to do that:
import sys, time
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.spinbox = QtGui.QSpinBox(self)
self.spinbox.setValue(5)
self.lcdnumber = QtGui.QLCDNumber(self)
self.button = QtGui.QPushButton('Start', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.spinbox)
layout.addWidget(self.lcdnumber)
layout.addWidget(self.button)
def handleButton(self):
for tick in range(self.spinbox.value(), -1, -1):
self.lcdnumber.display(tick)
self.button.setEnabled(not tick)
# continually process events for one second
start = time.time()
while time.time() - start < 1:
QtGui.qApp.processEvents()
time.sleep(0.02)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 300, 200)
window.show()
sys.exit(app.exec_())