I am new to Python GUI programming and Qt. I have learnt that if I create a GUI app in Qt Designer (with extension .ui), I need to convert it. But What if I write an app like the following one in, suppose, Notepad++ , then how can I run the file?
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Message box')
self.show()
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
How can I run this script and get the GUI ?
Thanks
just save it as a ".py" file and run it the same way that you run all of your normal python scripts. Just because it imports the qt libraries does not change that.
Related
I'm trying to make an application but I keep getting punched by the "simple" things like this one, how do I open a new window though a button click? I tried using new_lib_btn.clicked.connect(newlib), newlib is the file that contains my second window and new_lib_btn is the button that should open the window, it's in my main window as you can see down here:
mainwindow.py
from PyQt4 import QtCore, QtGui
import newlib
import sys
# Main Window
class Window (QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
centralwidget = QtGui.QWidget(self)
self.mainLayout = QtGui.QVBoxLayout(centralwidget)
self.mainLayout.setAlignment(QtCore.Qt.AlignCenter)
self.setCentralWidget(centralwidget)
self.resize(800, 600)
self.setWindowTitle("Virtual Library")
self.setStyleSheet("Window {border-image: url(lib.jpg);}")
# ExitOption
menu_action1 = QtGui.QAction("Exit", self)
menu_action1.setShortcut("Ctrl+Q")
menu_action1.setStatusTip('Exit The App')
menu_action1.triggered.connect(self.close_application)
self.statusBar()
# MenuBar
main_menu = self.menuBar()
file_menu = main_menu.addMenu('Options')
file_menu.addAction(menu_action1)
self.home()
def home(self):
# NewLibrary btn
new_lib_btn = QtGui.QPushButton("New Library", self)
new_lib_btn.setGeometry(QtCore.QRect(310, 180, 141, 41))
new_lib_btn.setStyleSheet("color: black;")
# AccessLibrary btn
access_lib_btn = QtGui.QPushButton("Access Library", self)
access_lib_btn.setGeometry(QtCore.QRect(310, 250, 141, 41))
access_lib_btn.setStyleSheet("color: black;")
# FindNewBooks btn
find_nbooks = QtGui.QPushButton("Find New Books*", self)
find_nbooks.setGeometry(QtCore.QRect(310, 320, 141, 41))
find_nbooks.setStyleSheet("color: black;")
self.mainLayout.addWidget(new_lib_btn)
self.mainLayout.addWidget(access_lib_btn)
self.mainLayout.addWidget(find_nbooks_btn)
self.show()
def close_application(self):
choice = QtGui.QMessageBox.question(self, 'Exit',
"Close the application?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
sys.exit()
else:
pass
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
And here's my second window, the one I want to open with the new_lib_btn
newlib.py
class NewLibrary (QtGui.QMainWindow):
def __init__(self):
super(NewLibrary, self).__init__()
self.resize(800,600)
self.setWindowTitle("New Library")
self.setStyleSheet("NewLibrary {border-image: url(wood.jpg);}")
# File Options
file_action1 = QtGui.QAction("New Library", self)
file_action1.setShortcut("Ctrl+N")
file_action1.setStatusTip("Creates a new library")
file_action2 = QtGui.QAction("Exit this!", self)
file_action2.setShortcut("Ctrl+Q")
file_action2.setStatusTip("Closes The App")
file_action2.triggered.connect(self.close_application)
#File Menu
main_menu = self.menuBar()
file_menu = main_menu.addMenu("File")
file_menu.addAction(file_action1)
file_menu.addAction(file_action2)
self.newLib()
self.newLib()
def newLib(self):
centralwidget = QtGui.QWidget(self)
self.mainLayout = QtGui.QVBoxLayout(centralwidget)
self.mainLayout.setAlignment(QtCore.Qt.AlignCenter)
#some useful buttons in the future
self.setCentralWidget(centralwidget)
self.show()
def close_application(self):
choice = QtGui.QMessageBox.question(self, 'Exit',
"Close the application?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
sys.exit()
else:
pass
def runNewLib():
app = QtGui.QApplication(sys.argv)
gui = NewLibrary()
sys.exit(app.exec_())
runNewLib()
I searched a lot about this but I couldn't understand the few ones that were somewhat close to my situation, so I'm asking for help, It seems so simple but I'm not getting it :/, what should I do to open the second window by clicking new_lib_btn? pls help.
I think there are several issues with the code that you've posted. First, there are two calls to self.newLib() in the NewLibrary constructor. Second, you probably want to put that call to runNewLib() at the bottom of newlib.py behind an if __name__... block, like so:
if __name__ == '__main__':
runNewLib()
Otherwise, every time you try to import newlib.py, it will attempt to run NewLibrary as a separate application.
Getting to the question you asked, I don't think you actually want to call self.show() in either Window.home() or NewLibrary.newLib(). A more typical pattern would be to create an instance of either Window or NewLibrary and then call show() on that instance. So, in your Window class, you'd add a function to create an instance of NewLibrary and then call show on it, like this
def create_new_library_window(self):
self.new_lib = newlib.NewLibrary()
self.new_lib.show()
Note that, as ekhumoro points out, you have to keep a reference to new_lib around, otherwise it will get garbage collected when the function exits. Then in NewLibrary.home() after you've created the new_lib_btn connect it to this new function:
new_lib_btn.clicked.connect(self.create_new_library_window)
Working example
This example creates a main window with one big button that, when clicked will open a second window. It uses two classes that inherit from QMainWindow, as in your question. First, in main.py:
from PyQt4 import QtGui
from new_window import NewWindow
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self._new_window = None
self._button = QtGui.QPushButton('New Window', self)
self._button.clicked.connect(self.create_new_window)
self.setCentralWidget(self._button)
def create_new_window(self):
self._new_window = NewWindow()
self._new_window.show()
if __name__ == '__main__':
app = QtGui.QApplication([])
gui = Window()
gui.show()
app.exec_()
The __init__ function creates a button and connects it to the create_new_window function. When the button is clicked, create_new_window will be called. Inside of create_new_window, we create an instance of NewWindow and assign it to a class member to maintain a reference to the window and prevent it from being garbage collected. We then call show on this new window to display it.
At the bottom, we use the usual if __name__ == '__main__': pattern to control whether this file runs the application or not. If this file is executed from the command line (like python main.py) __name__ == '__main__' evaluates to true and the GUI application will be started. This has the advantage of allowing the file to serve a dual purpose: it can be imported as a standard python package, or executed as an application, all using the same file.
Then in new_window.py:
from PyQt4 import QtGui
class NewWindow(QtGui.QMainWindow):
def __init__(self):
super(NewWindow, self).__init__()
self._new_window = None
self._label = QtGui.QLabel('Hello, is it me you\'re looking for?')
self.setCentralWidget(self._label)
if __name__ == '__main__':
app = QtGui.QApplication([])
gui = NewWindow()
gui.show()
app.exec_()
This file defines a second QMainWindow that uses a label as its central widget. It also uses the __name__ == '__main__' pattern; this file can also be executed as a standalone application or imported as in main.py above.
I use KDE on Manjaro linux. I have this script in python to turn off touchpad:
#!/usr/bin/python
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication
from subprocess import call
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
qbtn = QPushButton('On', self)
qbtn.clicked.connect(self.handleButtonOn)
qbtn.resize(qbtn.sizeHint())
qbtn.move(25, 50)
qbtn = QPushButton('Off', self)
qbtn.clicked.connect(self.handleButtonOff)
qbtn.resize(qbtn.sizeHint())
qbtn.move(125, 50)
self.setGeometry(300, 300, 250, 100)
self.setWindowTitle('Touchpad On/Off')
self.show()
def handleButtonOn(self, event):
print ('On')
call(["synclient", "touchpadoff=0"])
call(["notify-send", "Your touchpad is set to ON"])
self.destroy()
def handleButtonOff(self, event):
print ('Off')
call(["synclient", "touchpadoff=1"])
call(["notify-send", "Your touchpad is set to OFF"])
self.destroy()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
It's works almost perfect (turn off my touchpad) but when I start script it's turn off my power button so I can't turn off computer by this button.
There is a problem with Yakuake too, can't write in this terminal. Finally i've start some other terminal for example "konsole" and turn off computer by shutdown command.
I'm new in python. How to make this work OK. I need turn off my touchpad, I use external mouse.
I can't reproduce your issue with power button, but I found out that self.destroy() is causing your script to freeze in some corrupted-not-responding-to-SIGINT state. Replacing self.destroy() with self.close() makes it work on my machine.
Please try replacing self.destroy() with self.close().
I am building a simple GUI for selecting files using PYQT, and I am working with the Spyder IDE. When I try to close the GUI with the red "X" button and run the file again, a warning message pops up that says:
No Python shell is currently selected to run **readFile.py**
Please select or open a new Python interpreter and try again
How can I make the red X button reinitialize the interpreter and console without having to manually do it every time? Here is my code:
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
vbox = QtGui.QVBoxLayout()
lbl = QtGui.QLabel('Please Choose Excel File',self)
openButton = QtGui.QPushButton('Choose File')
openButton.clicked.connect(self.showDialog)
vbox.addWidget(lbl)
vbox.addWidget(openButton)
self.setLayout(vbox)
self.setGeometry(300,300,350,300)
self.setWindowTitle('file Dialog')
self.show()
def showDialog(self):
fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file', '/home')
print(fname)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I'm a total newbie in PyQt trying to develop simple application. I have designed simple ui with Qt-designer. I want extra confirmation if the user really want to exit application when clicking X or ,,Exit'' button or choosing Exit from menu.
Here's the code:
import sys
from PyQt4 import QtGui, QtCore, uic
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = uic.loadUi('main_window.ui')
self.ui.show()
self.ui.btnExit.clicked.connect(self.close)
self.ui.actionExit.triggered.connect(self.close)
def closeEvent(self, event):
print("event")
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
The problem is that:
When I click X on main window the closeEvent function doesn't trigger
When I click Exit button or choose ,,Exit'' from menu, the function
is called, but clicking Yes doesn't close application.
I have found some questions on SO and searched for tutorials, but nothing covered such problem. What am I doing wrong?
Note that you're doing:
self.ui = uic.loadUi('main_window.ui')
self.ui.show()
Your actual window is an instance attribute (ui) inside win. Not the win itself. And it doesn't have closeEvent implemented.
loadUi can load the .ui file inside an instance.
PyQt4.uic.loadUi(uifile[, baseinstance=None[, package='']])
You should use that. With that, your code would be:
import sys
from PyQt4 import QtGui, QtCore, uic
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
uic.loadUi('main_window.ui', self)
self.btnExit.clicked.connect(self.close)
self.actionExit.triggered.connect(self.close)
def closeEvent(self, event):
print("event")
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Note: I'm not a fan of showing the window in __init__. Explicit is better. So, I moved that to main. Feel free to modify it.
it works for me, just adding this line
self.ui.closeEvent = self.closeEvent
so your code would be:
import sys
from PyQt4 import QtGui, QtCore, uic
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = uic.loadUi('main_window.ui')
self.ui.closeEvent = self.closeEvent
self.ui.show()
self.ui.btnExit.clicked.connect(self.close)
self.ui.actionExit.triggered.connect(self.close)
def closeEvent(self, event):
print("event")
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Another simple solution for this is using the app.aboutToQuit.connect(self.close_event) to run the code in the closeEvent function whenever the user clicks the close button.
Sample code here
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
#--------------------------------------------------------------------------------
app.aboutToQuit.connect(self.closeEvent) #this line is what ur looking for !!!!!!
#--------------------------------------------------------------------------------
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle('Demo')
#{______________________________________
def closeEvent(self):
#Your code here
print('User has pressed the close button')
import sys
sys.exit(0)
#}______________________________________
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
From the designer you can connect events to the main window, and add new slots to it in the designer, then just implement the methods in python and the event->slot connection will be done automatically.
Is there a way to minimize to tray in PyQt4? I've already worked with the QSystemTrayIcon class, but now I would like to minimize or "hide" my app window, and show only the tray icon.
Has anybody done this? Any direction would be appreciated.
Using Python 2.5.4 and PyQt4 on Window XP Pro
It's pretty straightforward once you remember that there's no way to actually minimize to the system tray.
Instead, you fake it by doing this:
Catch the minimize event on your window
In the minimize event handler, create and show a QSystemTrayIcon
Also in the minimize event handler, call hide() or setVisible(false) on your window
Catch a click/double-click/menu item on your system tray icon
In your system tray icon event handler, call show() or setVisible(true) on your window, and optionally hide your tray icon.
Code helps, so here's something I wrote for an application, except for the closeEvent instead of the minimize event.
Notes:
"closeEvent(event)" is an overridden Qt event, so it must be put in the class that implements the window you want to hide.
"okayToClose()" is a function you might consider implementing (or a boolean flag you might want to store) since sometimes you actually want to exit the application instead of minimizing to systray.
There is also an example of how to show() your window again.
def __init__(self):
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
QtCore.QObject.connect(self.trayIcon, QtCore.SIGNAL(traySignal), self.__icon_activated)
def closeEvent(self, event):
if self.okayToClose():
#user asked for exit
self.trayIcon.hide()
event.accept()
else:
#"minimize"
self.hide()
self.trayIcon.show() #thanks #mojo
event.ignore()
def __icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.show()
Just to add to the example by Chris:
It is crucial that you use the Qt notation when declaring the signal, i.e.
correct:
self.connect(self.icon, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.iconClicked)
and not the PyQt one
incorrect and won't work:
self.connect(self.icon, SIGNAL("activated(QSystemTrayIcon.ActivationReason)"), self.iconClicked)
Note the :: in the signal string. This took me about three hours to figure out.
Here's working code..Thanks Matze for Crucial, the SIGNAL took me more hours of curiosity.. but doing other things. so ta for a #! moment :-)
def create_sys_tray(self):
self.sysTray = QtGui.QSystemTrayIcon(self)
self.sysTray.setIcon( QtGui.QIcon('../images/corp/blip_32.png') )
self.sysTray.setVisible(True)
self.connect(self.sysTray, QtCore.SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.on_sys_tray_activated)
self.sysTrayMenu = QtGui.QMenu(self)
act = self.sysTrayMenu.addAction("FOO")
def on_sys_tray_activated(self, reason):
print "reason-=" , reason
This was an edit of vzades response, but it was rejected on a number of grounds. It does the exact same thing as their code but will also obey the minimize event (and run without syntax errors/missing icons).
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
style = self.style()
# Set the window and tray icon to something
icon = style.standardIcon(QtGui.QStyle.SP_MediaSeekForward)
self.tray_icon = QtGui.QSystemTrayIcon()
self.tray_icon.setIcon(QtGui.QIcon(icon))
self.setWindowIcon(QtGui.QIcon(icon))
# Restore the window when the tray icon is double clicked.
self.tray_icon.activated.connect(self.restore_window)
def event(self, event):
if (event.type() == QtCore.QEvent.WindowStateChange and
self.isMinimized()):
# The window is already minimized at this point. AFAIK,
# there is no hook stop a minimize event. Instead,
# removing the Qt.Tool flag should remove the window
# from the taskbar.
self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.Tool)
self.tray_icon.show()
return True
else:
return super(Example, self).event(event)
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(
self,
'Message',"Are you sure to quit?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
self.tray_icon.show()
self.hide()
event.ignore()
def restore_window(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.tray_icon.hide()
# self.showNormal will restore the window even if it was
# minimized.
self.showNormal()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This is the correct way to handle double click on a tray icon for PyQt5.
def _create_tray(self):
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.activated.connect(self.__icon_activated)
def __icon_activated(self, reason):
if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
pass
This is the code and it does help i believe in show me the code
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QDialog, QApplication, QPushButton, QLineEdit, QFormLayout, QSystemTrayIcon
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.icon = QSystemTrayIcon()
r = self.icon.isSystemTrayAvailable()
print r
self.icon.setIcon(QtGui.QIcon('/home/vzades/Desktop/web.png'))
self.icon.show()
# self.icon.setVisible(True)
self.setGeometry(300, 300, 250, 150)
self.setWindowIcon(QtGui.QIcon('/home/vzades/Desktop/web.png'))
self.setWindowTitle('Message box')
self.show()
self.icon.activated.connect(self.activate)
self.show()
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message', "Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
self.icon.show()
self.hide()
event.ignore()
def activate(self, reason):
print reason
if reason == 2:
self.show()
def __icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()