I'm trying to make a GUI in Qt Designer that has one text entry box and a button off to the side that inserts another text entry box below the first. I would potentially need to do this a dozen times or more.
This is my example code from Qt Designer:
from PySide import QtCore, QtGui
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(247, 300)
self.pushButton = QtGui.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(110, 10, 75, 23))
self.pushButton.setObjectName("pushButton")
self.lineEdit1 = QtGui.QLineEdit(Dialog)
self.lineEdit1.setGeometry(QtCore.QRect(20, 10, 31, 20))
self.lineEdit1.setObjectName("lineEdit1")
self.lineEdit2 = QtGui.QLineEdit(Dialog)
self.lineEdit2.setGeometry(QtCore.QRect(60, 10, 31, 20))
self.lineEdit2.setObjectName("lineEdit2")
self.retranslateUi(Dialog)
# QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), Dialog.add_wells) #
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("Dialog", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
and this is the code to run the GUI:
from PySide.QtGui import *
from PySide.QtCore import *
import sys
import addentryexample
class MainWindow(QDialog, addentryexample.Ui_Dialog):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.connect(self.pushButton, SIGNAL("clicked()"), self.add_entry)
def add_entry(self):
pass
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
I'm struggling on how to iterate each name of the text box entry so I can pick the values from them later on. I think placing them should just require adding a certain amount to each 'setGeometry' attribute.
Any help would be appreciated!
You can use findChildren:
lineEdits = form.findChildren(QLineEdit)
for lineEdit in lineEdits:
print lineEdit.objectName()
Related
This question already has answers here:
PyQT button clicked name
(2 answers)
PyQt: Getting which button called a specific function
(2 answers)
Closed 2 months ago.
In PySide6, how to identify the objectName of a button when clicked?
I have a screen with several buttons and I need to identify the objectName of the clicked button.
If you need all buttons connect to same slot, just use self.sender() to identify which button is clicked. Easy example as below, you can copy it and run for test, enjoy it~
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import sys
class Main(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MyWidget_TestButton()
self.ui.setupUi(self)
self.ui.pushButton_A.clicked.connect(self.button_clicked_slot)
self.ui.pushButton_B.clicked.connect(self.button_clicked_slot)
def button_clicked_slot(self, clicked):
# get clicked button and do anything you need.
sender = self.sender()
self.ui.label.setText(f"{sender.objectName()} is clicked ~")
class Ui_MyWidget_TestButton(object):
def setupUi(self, MyWidget_TestButton):
if not MyWidget_TestButton.objectName():
MyWidget_TestButton.setObjectName(u"MyWidget_TestButton")
MyWidget_TestButton.resize(369, 178)
self.pushButton_A = QPushButton(MyWidget_TestButton)
self.pushButton_A.setObjectName(u"pushButton_A")
self.pushButton_A.setGeometry(QRect(80, 70, 75, 24))
self.pushButton_B = QPushButton(MyWidget_TestButton)
self.pushButton_B.setObjectName(u"pushButton_B")
self.pushButton_B.setGeometry(QRect(210, 70, 75, 24))
self.label = QLabel(MyWidget_TestButton)
self.label.setObjectName(u"label")
self.label.setGeometry(QRect(100, 130, 171, 20))
self.label.setStyleSheet(u"color: rgb(0, 85, 255);")
self.retranslateUi(MyWidget_TestButton)
QMetaObject.connectSlotsByName(MyWidget_TestButton)
# setupUi
def retranslateUi(self, MyWidget_TestButton):
MyWidget_TestButton.setWindowTitle(QCoreApplication.translate("MyWidget_TestButton", u"TestButton", None))
self.pushButton_A.setText(QCoreApplication.translate("MyWidget_TestButton", u"Button_A", None))
self.pushButton_B.setText(QCoreApplication.translate("MyWidget_TestButton", u"Button_B", None))
self.label.setText("")
# retranslateUi
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Main()
win.show()
sys.exit(app.exec())
I am trying to develop a python app for a RaspberryPi on a PC. In order to test one aspect, I have written an object class to emulate an OLED display device (hardware) that the PC cannot use (no I2C). The Wdisp class is simply loaded in place of the hardware driver when using the PC.
I have another class that wraps up the few OLED functions I need ( write text , draw progressbar etc. )
# OLED display object
import os
Win = False
if os.name == 'nt':
Win=True
from WindowsOLED import Wdisp
else:
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
class OLEDDisplay(object):
def __init__(self):
# Raspberry Pi pin configuration:
RST = 24
if Win:
self.disp = Wdisp()
else:
self.disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
# Initialize library.
self.disp.begin()
# Create blank image for drawing.
self.width = 128 #self.disp.width
self.height = 64 #self.disp.height
self._image = Image.new('1', (self.width, self.height))
self.draw = ImageDraw.Draw(self._image)
# Load default font.
self.font = ImageFont.load_default()
self.clear()
def __del__(self):
self.clear()
def __repr__(self):
return 'OLED display object for SSD1306 I2C'
def clear(self):
# Clear display
self.disp.clear()
self.disp.display()
def write(self, text):
self.draw.text((0, 2), text, font=self.font, fill=255)
self._show()
def progressbar(self, percent):
#draw a progress bar on top half of screen
shape_width = self.width * (percent/100)
padding =2
top = padding
bottom = (self.height/2) - padding
x = padding
self.draw.rectangle((x, top, self.width-padding, bottom), outline=255, fill=0)
self.draw.rectangle((x, top, x+shape_width, bottom), outline=255, fill=255)
self._show()
def loadimage(self, imagefile):
#open, convert and display an image
self._image = Image.open(imagefile).resize((self.disp.width,
self.disp.height),
Image.ANTIALIAS).convert('1')
self._show()
def _show(self):
# Display image.
self.disp.image(self._image)
self.disp.display()
If I test this class at the command line
Example:
>>> from OLEDDisplay import*
>>> OD = OLEDDisplay()
>>> OD.progressbar(50)
Its works fine - the OLEDDisplay object draws on a PIL image object, passes the image to the Wdisp object and the Wdisp object converts the image to a BitMapImage and displays in on a Tkinter Label ( self.L ).
#Windows subsitute OLED display class
#displays a label image for testing
from tkinter import *
from PIL import Image, ImageTk
from tkinter import filedialog, messagebox
from tkinter.constants import *
class Wdisp(object):
i=None
width = 128
height =64
_image = None
def __init__(self):
self.master = Tk()
self._image = Image.new('1', (self.width, self.height))
self.i = ImageTk.PhotoImage(self._image)
self.L= Label(self.master, text="label place holder", image=self.i)
self.L.pack(expand=YES, fill=BOTH)
def begin(self):
pass
def image(self, newimage):
self._image = newimage
def display(self):
#display the image
self.i = ImageTk.BitmapImage(self._image)
self.L.config(image=self.i)
However, if I use this in my app or test it in a small app:
from tkinter import *
from PIL import Image, ImageTk
from tkinter import filedialog, messagebox
from tkinter.constants import *
from OLEDDisplay import*
def updateOLED():
text = E.get
print(text)
OD.write(text)
master = Tk()
OD = OLEDDisplay()
E = Entry(master)
B = Button(master, text="update OLED", command = updateOLED)
E.pack()
B.pack()
It fails with a tkinter.TclError: image "pyimage4" doesn't exist:
Traceback (most recent call last):
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\OLEDDisplay test.py", line 19, in <module>
OD = OLEDDisplay()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\OLEDDisplay.py", line 42, in __init__
self.clear()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\OLEDDisplay.py", line 52, in clear
self.disp.clear()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\WindowsOLED.py", line 45, in clear
self.display()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\WindowsOLED.py", line 36, in display
self.L.config(image=self.i)
File "C:\Python34\lib\tkinter\__init__.py", line 1324, in configure
return self._configure('configure', cnf, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 1315, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage4" doesn't exist
I have no idea why : perhaps variable scope? perhaps something weird with PIL , so any suggestions welcome.
Cheers Bill
I'm working on a GUI that basically hold multiple widgets that each contain a figure as well as a few buttons/whatever. One of the figures is supposed to be interactive, calling a function whenever the user clicks on any part of the plot. Yet I can't get the function to fire using mpl_connect, even after playing with focus and whatnot. I'm somewhat new to PySide/Qt, so I don't exactly understand why my code is behaving like this (I've been searching for days for a solution, but haven't found anything about it).
I used Qt Designer to create the layout for the GUI. I'm using Spyder from Anaconda 2.2.0 (32-bit), Python 2.7, and PySide to develop the GUI. If it's any help, I come from more of a MATLAB background where I developed a full version of the GUI I'm trying to make in Python.
Below is the relevant code (scroll down a bit to see where the problem is):
from PySide import QtCore, QtGui
from PySide.QtCore import *
from PySide.QtGui import *
import numpy as np
import matplotlib
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
import matplotlib.pyplot as plt
from PySide.QtGui import QPalette, QCursor
import matplotlib.colors as colors
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1316, 765)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(75, 40, 375, 490))
self.widget.setObjectName("widget")
color = self.centralwidget.palette().color(QPalette.Window)
self.leftPlot = MatplotlibWidget(None,'','','',False,color)
self.setupPlot(self.widget,self.leftPlot)
self.leftPlot.figure.tight_layout()
self.leftImage = self.leftPlot.axes.imshow(self.defaultSlide, cmap = mymap)
Snippet of interest:
self.leftPlot.figure.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
self.leftPlot.figure.canvas.setFocus()
cid = self.leftPlot.figure.canvas.mpl_connect('button_release_event', self.getCoordinates) # doesn't get called
plt.show()
def getCoordinates(self, event):
print 'dasdsadadsa'
print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(event.button, event.x, event.y, event.xdata, event.ydata)
The rest:
class MatplotlibWidget(FigureCanvas):
def __init__(self, parent=None,xlabel='x',ylabel='y',title='Title',showTicks=False,color=None):
super(MatplotlibWidget, self).__init__(Figure())
self.setParent(parent)
if color != None:
self.figure = Figure(facecolor=(color.red()/256.0,color.green()/256.0,color.blue()/256.0),frameon=0)
else:
self.figure = Figure(frameon=0)
self.canvas = FigureCanvas(self.figure)
self.axes = self.figure.add_subplot(111)
self.axes.set_xlabel(xlabel)
self.axes.set_ylabel(ylabel)
self.axes.set_title(title)
self.axes.get_xaxis().set_visible(showTicks)
self.axes.get_yaxis().set_visible(showTicks)
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
plt.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
I'm aware the code is messy, but any input is greatly appreciated.
Update (2015-09-04) : I've updated the MWE I provided as part of my original answer to use instead the approach that is suggested in the matplotlib documentation to embed a mpl figure in an application. This approach does not use the pyplot interface (as in my original answer) and use the Object Oriented API of mpl instead. Also, since all the mpl artists (figure, axes, etc.) know each other, there is no need to explicitly create new class variables. This allows a structure of code that is, IMO, easier to read and to maintain.
The problem comes from the fact that you are not connecting correctly your event to self.leftPlot (FigureCanvasQTAgg), but to self.leftPlot.figure.canvas (FigureCanvasQTAgg.figure.FigureCanvasQTAgg) instead. You are creating a canvas within a canvas in the MatplotlibWidget class (which is already a subclass of FigureCanvasQTAgg). You only need to create one mpl canvas, pass a figure to it, and then connect the event to it directly.
I've put together a MWE to demonstrate how this can be done using the Object Oriented API of Matplotlib as suggested in the documentation:
from PySide import QtGui
import numpy as np
import sys
import matplotlib as mpl
mpl.use('Qt4Agg')
mpl.rcParams['backend.qt4']='PySide'
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.setupUi()
def setupUi(self):
figure = mpl.figure.Figure(figsize=(5, 5))
leftPlot = MatplotlibWidget(figure)
self.setCentralWidget(leftPlot)
class MatplotlibWidget(FigureCanvasQTAgg):
def __init__(self, fig):
super(MatplotlibWidget, self).__init__(fig)
#-- set up an axe artist --
ax = fig.add_axes([0.1, 0.1, 0.85, 0.85])
ax.plot(np.arange(15), np.arange(15))
self.draw()
#---- setup event ----
self.mpl_connect('button_press_event', self.onclick)
def onclick(self, event):
x, y = event.x, event.y
print(x, y)
if x != None and y != None:
ax = self.figure.axes[0]
ax.plot(event.xdata, event.ydata, 'ro')
self.draw()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
The code above results in:
I want to run my app in different tabs. Rightnow, it is running in main window. I have done some search work on how to create tabs. I found this to be useful, but not sufficient to meet my requirements
Create TAB and create textboxes that take data in the TAB-page
I want to have a feature of adding a new tab (like new tab in chrome)
Below is my code sample. I described what i require in the comments.
from PyQt4 import Qt, QtCore, QtGui
import sys
class Map(QtGui.QMainWindow):
def __init__(self,parentQExampleScrollArea=None,parentQWidget = None):
super(Map,self).__init__()
self.initUI()
#Initialize the UI
def initUI(self):
#Initilizing Menus toolbars
#This must be maintained in all tabbed panes
filename = ""
#Filename is obtained through open file button in file menu
self.filename = filename
def paintEvent(self, e):
qp = QtGui.QPainter()
qp.begin(self)
self.drawPoints(qp,self.filename)
qp.end()
def drawPoints(self, qp,FILENAME=""):
#Read contents in file
#Get the necessary coordinates
#A separate class for storing the info of all the coordinates
#Run a for loop for all the coordinates in the list
#Actually, object is created here and image of that object is set
# as a square using the coordinates
qp.setBrush(QtGui.QColor(255, 0, 20, 200))
qp.drawRect(20,20,75,75)
qp.drawRect(100,20,75,75)
self.update()
#There are many functions to handle keyboard and mouse events
def main():
#How do I modify so that I can have multiple tabs
#And show images of the coordinates in files
#Basically I want to have the feature of opening many files
# and displaying them in UI
#Basically a feature to add a new tab
#like that of in eclipse netbeans sublime etc
app = QtGui.QApplication(sys.argv)
myQExampleScrollArea = Map()
myQExampleScrollArea.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Thanks in advance.. :)
It's simply to use method int QTabWidget.addTab (self, QWidget widget, QString) to create widget in tab. In each tab, I suggest use QtGui.QWidget more than QtGui.QMainWindow;
Example;
import sys
from PyQt4 import QtGui
class QCustomWidget (QtGui.QWidget):
# Your widget to implement
# Put your override method here
def paintEvent (self, eventQPaintEvent):
currentQPainter = QtGui.QPainter()
currentQPainter.begin(self)
currentQPainter.setBrush(QtGui.QColor(255, 0, 20, 200))
currentQPainter.drawRect(20, 20, 75, 75)
currentQPainter.drawRect(100, 20, 75, 75)
self.update()
currentQPainter.end()
class QCustomTabWidget (QtGui.QTabWidget):
def __init__ (self, parent = None):
super(QCustomTabWidget, self).__init__(parent)
self.addTab(QtGui.QPushButton('Test'), 'Tab 1')
self.addTab(QCustomWidget(), 'Tab 2')
myQApplication = QtGui.QApplication([])
myQCustomTabWidget = QCustomTabWidget()
myQCustomTabWidget.show()
sys.exit(myQApplication.exec_())
So handle with more tab, It's bad to create many line call int QTabWidget.addTab (self, QWidget widget, QString). Anyway, All widget has add in QTabWidget is can reference in ifself. So, your can control element in it by call QWidget QTabWidget.widget (self, int index).
Example to call widget in tab widget;
import os
import sys
from PyQt4 import QtCore, QtGui
class QCustomLabel (QtGui.QLabel):
def __init__(self, imagePath, parentQWidget = None):
super(QCustomLabel, self).__init__(parentQWidget)
self.setPixmap(QtGui.QPixmap(imagePath))
class QCustomWidget (QtGui.QWidget):
def __init__ (self, parentQWidget = None):
super(QCustomWidget, self).__init__(parentQWidget)
self.addQPustButton = QtGui.QPushButton('Open image')
self.addQPustButton.setMaximumWidth(120)
self.addQPustButton.released.connect(self.openImage)
self.workSpaceQTabWidget = QtGui.QTabWidget()
self.workSpaceQTabWidget.setTabsClosable(True)
self.workSpaceQTabWidget.tabCloseRequested.connect(self.closeImage)
allQVBoxLayout = QtGui.QVBoxLayout()
allQVBoxLayout.addWidget(self.addQPustButton)
allQVBoxLayout.addWidget(self.workSpaceQTabWidget)
self.setLayout(allQVBoxLayout)
def openImage (self):
path = QtGui.QFileDialog.getOpenFileName(self, 'Open image')
if not path.isEmpty():
self.workSpaceQTabWidget.addTab(QCustomLabel(path), QtCore.QString(os.path.basename(str(path))))
def closeImage (self, currentIndex):
currentQWidget = self.workSpaceQTabWidget.widget(currentIndex)
currentQWidget.deleteLater()
self.workSpaceQTabWidget.removeTab(currentIndex)
myQApplication = QtGui.QApplication([])
myQCustomWidget = QCustomWidget()
myQCustomWidget.show()
sys.exit(myQApplication.exec_())
How can I put stuff in the main window? I want to create a line edit in the main window(beneath the menu bar, maybe with some decription laber in front of it). How is this done? I used grid layout and this box layout, nothing works.
(sry for another trivial question, there are only few tutorials on pyside out there, and most of them only cover how to create single windows with buttons ect.)
import sys
from PySide import QtGui, QtCore, QtWebKit
class FirstClass(QtGui.QMainWindow, QtGui.QWidget):
def __init__(self):
super(FirstClass, self).__init__()
self.startingUI()
def startingUI(self):
self.setWindowTitle('Hauptfenster')
self.resize(800, 400)
self.statusBar()
#Menueinstellungen an sich
menue = self.menuBar()
#Actions des Menues:
#datei menue
menuleiste_datei = menue.addMenu('File')
datei_exit = QtGui.QAction('Exit', self)
datei_exit.setStatusTip('Close the programm')
menuleiste_datei.addAction(datei_exit)
datei_exit.triggered.connect(self.close)
#Einstellungen menue
menuleiste_configurations = menue.addMenu('Configurations')
configurations_settings = QtGui.QAction('Settings', self)
configurations_settings.setStatusTip('Configurations(Settings)')
menuleiste_configurations.addAction(configurations_settings)
configurations_settings.triggered.connect(self.newwindow)
self.lineedit = QtGui.QLineEdit()
self.layout = QtGui.QHBoxLayout()
self.layout.addWidget(self.lineedit)
self.setLayout(self.layout)
self.show()
def newwindow(self):
self.wid = QtGui.QWidget()
self.wid.resize(250, 150)
self.setWindowTitle('NewWindow')
self.wid.show()
def main():
app = QtGui.QApplication(sys.argv)
start = FirstClass()
sys.exit(app.exec_())
if __name__== '__main__':
main()
I do not believe creating a class with a multiple inheritance is recommended best practice. If an attribute is not found in FirstClass, then it searches left to right (QtGui.QMainWindow to QtGui.QWidget). From my perspective, this would turn into a nightmare to support and debug. My guess this is why the self.layout is not working properly.
I made separate classes for QtGui.QMainWindow and QtGui.QWidget. FirstWindowClass sets the central widget as FirstWidgetClass. FirstWidgetClass has your QLineEdit and I went ahead and inserted a label. I changed QHBoxLayout to QGridLayout to help you understand how it works.
Some tips from my learning experiences with Python and Pyside these past couple months:
Remember you can always look at PyQt examples and majority will work directly with PySide modules.
I recommend looking over http://srinikom.github.io/pyside-docs/index.html as a lot of the modules have simple examples.
For my personal project, a lot of the solutions to my Qt questions were in C++ so do not be afraid to convert it to python.
import sys
from PySide import QtGui, QtCore, QtWebKit
class FirstWindowClass(QtGui.QMainWindow):
def __init__(self):
super(FirstWindowClass, self).__init__()
self.setWindowTitle('Hauptfenster')
self.resize(800, 400)
self.statusBar()
# Set central widget that expands to fill your window
self.main_widget = FirstWidgetClass(self)
self.setCentralWidget(self.main_widget)
#Menueinstellungen an sich
menue = self.menuBar()
#Actions des Menues:
#datei menue
menuleiste_datei = menue.addMenu('File')
datei_exit = QtGui.QAction('Exit', self)
datei_exit.setStatusTip('Close the programm')
menuleiste_datei.addAction(datei_exit)
datei_exit.triggered.connect(self.close)
#Einstellungen menue
menuleiste_configurations = menue.addMenu('Configurations')
configurations_settings = QtGui.QAction('Settings', self)
configurations_settings.setStatusTip('Configurations(Settings)')
menuleiste_configurations.addAction(configurations_settings)
configurations_settings.triggered.connect(self.newwindow)
# Open the window
self.show()
def newwindow(self):
self.wid = QtGui.QWidget()
self.wid.resize(250, 150)
self.wid.setWindowTitle('NewWindow')
self.wid.show()
class FirstWidgetClass(QtGui.QWidget):
def __init__(self, parent=None):
super(FirstWidgetClass, self).__init__()
self.label_example = QtGui.QLabel('Enter Data:')
self.lineedit = QtGui.QLineEdit()
self.layout = QtGui.QGridLayout()
self.layout.addWidget(self.label_example, 0, 0)
self.layout.addWidget(self.lineedit, 0, 1)
self.setLayout(self.layout)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
start = FirstWindowClass()
sys.exit(app.exec_())
if __name__== '__main__':
main()