├── README.md ├── command_runner ├── command_runner.py ├── command_runner.ui └── command_runner_progressbar.py ├── my_gui ├── my_gui.py ├── my_gui.ui ├── my_gui_class.py └── my_gui_from_pyuic.py ├── other_examples ├── choose_file.py ├── choose_folder.py ├── error_window.py └── generate_dropdown.py └── screenshots ├── choose_file.png ├── choose_folder.png ├── command_runner.png ├── command_runner_progressbar.png ├── dropdown.png ├── error_window.png ├── my_gui.png ├── qtdesigner1.png └── qtdesigner2.png /README.md: -------------------------------------------------------------------------------- 1 | # How to quickly make a Qt GUI with Python 2 | 3 | ## Requirements 4 | Qt designer and python Qt bindings: 5 | 6 | sudo apt-get install qt4-designer python-qt4 7 | 8 | iPython is optional but recommended: 9 | 10 | sudo apt-get install ipython 11 | 12 | You may want a proper editor for Python, here you have a guide on how to setup **Sublime Text** or **PyCharm** [My development environment](https://gist.github.com/awesomebytes/c932b2502fab32d0c8bb). 13 | 14 | ## Design the GUI 15 | Fire up Qt designer 16 | 17 | designer-qt4 18 | 19 | Choose `Main Window` on the New form dialogue (File > New...). 20 | 21 | ![New form dialogue](screenshots/qtdesigner1.png) 22 | 23 | Add a `PushButton` and a `Label` from the left column menu (Widget Box). Change the name of the elements on the top right menu (Object Inspector), `my_button` and `my_label` are good enough names. 24 | 25 | ![Add elements](screenshots/qtdesigner2.png) 26 | 27 | Save the file as `my_gui.ui`. 28 | 29 | ## Script the behaviour 30 | Open your favorite editor (I recommend Sublime Text with Anaconda IDE plugin) and paste: 31 | 32 | ````python 33 | #!/usr/bin/env python 34 | 35 | import sys 36 | from PyQt4 import QtGui, uic 37 | 38 | 39 | class MyWindow(QtGui.QMainWindow): 40 | def __init__(self): 41 | super(MyWindow, self).__init__() 42 | uic.loadUi('my_gui.ui', self) 43 | self.show() 44 | 45 | 46 | if __name__ == '__main__': 47 | app = QtGui.QApplication(sys.argv) 48 | myWindow = MyWindow() 49 | app.exec_() 50 | 51 | ```` 52 | 53 | Give the file executable permissions: 54 | 55 | chmod +x my_gui.py 56 | 57 | And we can execute it 58 | 59 | ./my_gui.py 60 | 61 | and you have a GUI showing stuff! 62 | 63 | ![First GUI](screenshots/my_gui.png) 64 | 65 | But we want the GUI to do stuff. So we need to connect buttons to actions. 66 | 67 | Once you learn how Qt works you can just google for methods (the [official Qt4 documentation](http://doc.qt.io/qt-4.8/) is for C++ but the methods are the same in Python) and so and you'll end up with something like: 68 | 69 | ````python 70 | #!/usr/bin/env python 71 | 72 | import sys 73 | from PyQt4 import QtGui, uic 74 | 75 | 76 | class MyWindow(QtGui.QMainWindow): 77 | def __init__(self): 78 | super(MyWindow, self).__init__() 79 | uic.loadUi('my_gui.ui', self) 80 | self.my_button.clicked.connect(self.on_my_button_push) 81 | self.show() 82 | 83 | def on_my_button_push(self): 84 | self.my_label.setText("Button Pushed!") 85 | 86 | 87 | if __name__ == '__main__': 88 | app = QtGui.QApplication(sys.argv) 89 | myWindow = MyWindow() 90 | app.exec_() 91 | ```` 92 | 93 | But if you want autocompletion to know what methods and properties has every element you can either: 94 | * Use iPython, load the code and use the dynamic introspection to check stuff (my preferred option) 95 | * Generate a Python class using `pyuic.py` and load it in your code instead of using `uic.loadUi` (a bit cumbersome) 96 | 97 | See `Extras` for more on that. 98 | 99 | # Examples 100 | 101 | ## Run a shell command and retrieve its output 102 | See `command_runner/command_runner.py`. 103 | 104 | ![Command runner](screenshots/command_runner.png) 105 | 106 | ## Show a loading bar meanwhile doing something 107 | See `command_runner/command_runner_progressbar.py` for an extension of `command_runner/command_runner.py` that shows a progress bar while running a command. 108 | 109 | ![Command runner progressbar](screenshots/command_runner_progressbar.png) 110 | 111 | ## Show Error/Warning popup 112 | See `other_examples/error_window.py`. 113 | 114 | ![Error window](screenshots/error_window.png) 115 | 116 | ## Choose a file 117 | See `other_examples/choose_file.py`. 118 | 119 | ![Choose file](screenshots/choose_file.png) 120 | 121 | ## Choose a folder 122 | See `other_examples/choose_folder.py`. 123 | 124 | ![Choose folder](screenshots/choose_folder.png) 125 | 126 | ## Using a dropdown/combo_box 127 | See `other_examples/generate_dropdown.py`. 128 | 129 | ![Dropdown example](screenshots/dropdown.png) 130 | 131 | ## Generate dynamically GUI fields 132 | See `other_examples` folder, they aren't using any .ui file. 133 | 134 | ## Real time plot 135 | TODO 136 | 137 | ## Create a rqt_gui plugin 138 | TODO 139 | 140 | 141 | # Extras 142 | Sublime Text with Anaconda plugin or PyCharm (and probably other editors) will autocomplete for you some stuff but anything that is dynamically generated will not be able to autocomplete it (for example whatever you loaded from a .ui file). Here I present a couple of ways of getting autocompletion on that. 143 | 144 | ## Use iPython for autocompletion 145 | Fire up iPython 146 | 147 | ipython 148 | 149 | You must take into account that you want to remain in the iPython shell so you must comment the line `app.exec_()` (or in the next step deleting it). 150 | 151 | And load your file 152 | 153 | %load my_gui.py 154 | 155 | And after hitting enter again, you'll see the window and you'll be able to do introspection about everything available. 156 | 157 | A trick for not needing to do this commenting/deleting line is to modify the code with: 158 | ````python 159 | #!/usr/bin/env python 160 | 161 | import sys 162 | from PyQt4 import QtGui, uic 163 | 164 | 165 | def running_in_ipython(): 166 | """Check if the interpreter is iPython as when debugging we don't want to 167 | execute app.exec_() to remain in the shell to do dynamic introspection""" 168 | try: 169 | __IPYTHON__ 170 | return True 171 | except NameError: 172 | return False 173 | 174 | 175 | class MyWindow(QtGui.QMainWindow): 176 | def __init__(self): 177 | super(MyWindow, self).__init__() 178 | uic.loadUi('my_gui.ui', self) 179 | self.my_button.clicked.connect(self.on_my_button_push) 180 | self.show() 181 | 182 | def on_my_button_push(self): 183 | self.my_label.setText("Button Pushed!") 184 | 185 | 186 | if __name__ == '__main__': 187 | app = QtGui.QApplication(sys.argv) 188 | myWindow = MyWindow() 189 | if not running_in_ipython(): 190 | app.exec_() 191 | 192 | ```` 193 | 194 | 195 | ## Generate a Python class to help on autocompletion 196 | First locate your `pyuic.py` file 197 | 198 | locate pyuic.py 199 | 200 | In my case it's at `/usr/lib/python2.7/dist-packages/PyQt4/uic/pyuic.py`. 201 | 202 | Execute it with your ui file 203 | 204 | python /usr/lib/python2.7/dist-packages/PyQt4/uic/pyuic.py my_gui.ui > my_gui_class.py 205 | 206 | And now your code should be changed to: 207 | 208 | ````python 209 | #!/usr/bin/env python 210 | 211 | import sys 212 | from PyQt4 import QtGui 213 | from my_gui_class import Ui_MainWindow 214 | 215 | 216 | class MyWindow(QtGui.QMainWindow): 217 | def __init__(self): 218 | super(MyWindow, self).__init__() 219 | self.ui = Ui_MainWindow() 220 | self.ui.setupUi(self) 221 | self.ui.my_button.clicked.connect(self.on_my_button_push) 222 | self.show() 223 | 224 | def on_my_button_push(self): 225 | self.ui.my_label.setText("Button pushed!") 226 | 227 | 228 | if __name__ == '__main__': 229 | app = QtGui.QApplication(sys.argv) 230 | myWindow = MyWindow() 231 | app.exec_() 232 | 233 | ```` 234 | 235 | Now you'll get all the possible autocompletion and documentation available (won't be everything). 236 | 237 | You'll need to recreate the `my_gui_class.py` every time you change the `my_gui.ui` file. 238 | -------------------------------------------------------------------------------- /command_runner/command_runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from PyQt4 import QtGui, uic 5 | import subprocess 6 | 7 | 8 | def running_in_ipython(): 9 | """Check if the interpreter is iPython as when debugging we don't want to 10 | execute app.exec_() to remain in the shell to do dynamic introspection""" 11 | try: 12 | __IPYTHON__ 13 | return True 14 | except NameError: 15 | return False 16 | 17 | 18 | class MyWindow(QtGui.QMainWindow): 19 | def __init__(self): 20 | super(MyWindow, self).__init__() 21 | uic.loadUi('command_runner.ui', self) 22 | self.run_b.clicked.connect(self.run_command) 23 | self.show() 24 | 25 | def run_command(self): 26 | # Note: toPlainText returns a QString which you cannot feed the shell 27 | # with it or you'll get the error: 28 | # CalledProcessError: Command 'XXX' returned non-zero exit status 127 29 | command = str(self.cmd_pte.toPlainText()) 30 | # Note that shell=True is a very unsafe thing to do, but also easy 31 | try: 32 | output = subprocess.check_output(command, shell=True) 33 | self.output_te.setText(output) 34 | except subprocess.CalledProcessError as e: 35 | self.output_te.setText("Error:" + str(e)) 36 | 37 | 38 | if __name__ == '__main__': 39 | app = QtGui.QApplication(sys.argv) 40 | myWindow = MyWindow() 41 | if not running_in_ipython(): 42 | app.exec_() 43 | -------------------------------------------------------------------------------- /command_runner/command_runner.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1146 10 | 842 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 40 21 | 30 22 | 1091 23 | 721 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 16777215 34 | 40 35 | 36 | 37 | 38 | your awesome command here 39 | 40 | 41 | 42 | 43 | 44 | 45 | Run command 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Qt::Horizontal 55 | 56 | 57 | 58 | 40 59 | 20 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 68 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 69 | p, li { white-space: pre-wrap; } 70 | </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> 71 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Output</p></body></html> 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 0 82 | 0 83 | 1146 84 | 42 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /command_runner/command_runner_progressbar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from PyQt4 import QtGui, uic, QtCore 5 | import subprocess 6 | import tempfile 7 | import os 8 | import signal 9 | 10 | 11 | # Helper class to run commands 12 | class ShellCmd: 13 | 14 | def __init__(self, cmd): 15 | self.outf = tempfile.NamedTemporaryFile(mode="w") 16 | self.errf = tempfile.NamedTemporaryFile(mode="w") 17 | self.inf = tempfile.NamedTemporaryFile(mode="r") 18 | self.process = subprocess.Popen(cmd, shell=True, stdin=self.inf, 19 | stdout=self.outf, stderr=self.errf, 20 | preexec_fn=os.setsid, close_fds=True) 21 | 22 | def __del__(self): 23 | if not self.is_done(): 24 | self.kill() 25 | self.outf.close() 26 | self.errf.close() 27 | self.inf.close() 28 | 29 | def get_stdout(self): 30 | with open(self.outf.name, "r") as f: 31 | return f.read() 32 | 33 | def get_stderr(self): 34 | with open(self.errf.name, "r") as f: 35 | return f.read() 36 | 37 | def get_retcode(self): 38 | """get retcode or None if still running""" 39 | return self.process.poll() 40 | 41 | def is_done(self): 42 | return self.process.poll() is not None 43 | 44 | def kill(self): 45 | os.killpg(self.process.pid, signal.SIGTERM) 46 | self.process.wait() 47 | 48 | 49 | class MyWindow(QtGui.QMainWindow): 50 | def __init__(self): 51 | super(MyWindow, self).__init__() 52 | uic.loadUi('command_runner.ui', self) 53 | self.run_b.clicked.connect(self.run_command_with_progressbar) 54 | self.show() 55 | 56 | def run_command_with_progressbar(self): 57 | # Note: toPlainText returns a QString which you cannot feed the shell 58 | # with it or you'll get the error: 59 | # CalledProcessError: Command 'XXX' returned non-zero exit status 127 60 | command = str(self.cmd_pte.toPlainText()) 61 | 62 | feedback_msg = "Command '" + command + "' is being executed..." 63 | cancel_button_text = "Cancel" 64 | self.progressbar = QtGui.QProgressDialog(feedback_msg, 65 | cancel_button_text, 66 | # min 0, max 0 makes 67 | # progressbar just move from 68 | # left to right 69 | 0, 0) 70 | self.timer = QtCore.QTimer() 71 | # For a one time timer use 72 | # QTimer.singleShot(200, self.do_this_thing) 73 | self.timer.timeout.connect(self.progressbar_update) 74 | self.progressbar.canceled.connect(self.progressbar_cancel) 75 | self.timer.start(1000) 76 | self.progressbar.show() 77 | 78 | self.process = ShellCmd(command) 79 | 80 | def progressbar_update(self): 81 | # If using a progressbar with max and min (0-100 for example) 82 | # Use setValue to set the progressbar 83 | # self.progressbar.setValue() 84 | if not self.process.is_done(): 85 | self.progressbar.show() 86 | else: 87 | output = self.process.get_stdout() 88 | err_output = self.process.get_stderr() 89 | self.output_te.setText(output + err_output) 90 | self.timer.stop() 91 | self.progressbar.hide() 92 | 93 | def progressbar_cancel(self): 94 | self.timer.stop() 95 | 96 | 97 | if __name__ == '__main__': 98 | app = QtGui.QApplication(sys.argv) 99 | myWindow = MyWindow() 100 | app.exec_() 101 | -------------------------------------------------------------------------------- /my_gui/my_gui.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from PyQt4 import QtGui, uic 5 | 6 | 7 | def running_in_ipython(): 8 | """Check if the interpreter is iPython as when debugging we don't want to 9 | execute app.exec_() to remain in the shell to do dynamic introspection""" 10 | try: 11 | __IPYTHON__ 12 | return True 13 | except NameError: 14 | return False 15 | 16 | 17 | class MyWindow(QtGui.QMainWindow): 18 | def __init__(self): 19 | super(MyWindow, self).__init__() 20 | uic.loadUi('my_gui.ui', self) 21 | self.my_button.clicked.connect(self.on_my_button_push) 22 | self.show() 23 | 24 | def on_my_button_push(self): 25 | self.my_label.setText("Button Pushed!") 26 | 27 | 28 | if __name__ == '__main__': 29 | app = QtGui.QApplication(sys.argv) 30 | myWindow = MyWindow() 31 | if not running_in_ipython(): 32 | app.exec_() 33 | -------------------------------------------------------------------------------- /my_gui/my_gui.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 818 10 | 600 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 150 21 | 190 22 | 176 23 | 44 24 | 25 | 26 | 27 | PushButton 28 | 29 | 30 | 31 | 32 | 33 | 450 34 | 200 35 | 131 36 | 34 37 | 38 | 39 | 40 | TextLabel 41 | 42 | 43 | 44 | 45 | 46 | 47 | 0 48 | 0 49 | 818 50 | 42 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /my_gui/my_gui_class.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'my_gui.ui' 4 | # 5 | # Created: Fri Jan 29 11:50:48 2016 6 | # by: PyQt4 UI code generator 4.10.4 7 | # 8 | # WARNING! All changes made in this file will be lost! 9 | 10 | from PyQt4 import QtCore, QtGui 11 | 12 | try: 13 | _fromUtf8 = QtCore.QString.fromUtf8 14 | except AttributeError: 15 | def _fromUtf8(s): 16 | return s 17 | 18 | try: 19 | _encoding = QtGui.QApplication.UnicodeUTF8 20 | def _translate(context, text, disambig): 21 | return QtGui.QApplication.translate(context, text, disambig, _encoding) 22 | except AttributeError: 23 | def _translate(context, text, disambig): 24 | return QtGui.QApplication.translate(context, text, disambig) 25 | 26 | class Ui_MainWindow(object): 27 | def setupUi(self, MainWindow): 28 | MainWindow.setObjectName(_fromUtf8("MainWindow")) 29 | MainWindow.resize(818, 600) 30 | self.centralwidget = QtGui.QWidget(MainWindow) 31 | self.centralwidget.setObjectName(_fromUtf8("centralwidget")) 32 | self.my_button = QtGui.QPushButton(self.centralwidget) 33 | self.my_button.setGeometry(QtCore.QRect(150, 190, 176, 44)) 34 | self.my_button.setObjectName(_fromUtf8("my_button")) 35 | self.my_label = QtGui.QLabel(self.centralwidget) 36 | self.my_label.setGeometry(QtCore.QRect(450, 200, 131, 34)) 37 | self.my_label.setObjectName(_fromUtf8("my_label")) 38 | MainWindow.setCentralWidget(self.centralwidget) 39 | self.menubar = QtGui.QMenuBar(MainWindow) 40 | self.menubar.setGeometry(QtCore.QRect(0, 0, 818, 42)) 41 | self.menubar.setObjectName(_fromUtf8("menubar")) 42 | MainWindow.setMenuBar(self.menubar) 43 | self.statusbar = QtGui.QStatusBar(MainWindow) 44 | self.statusbar.setObjectName(_fromUtf8("statusbar")) 45 | MainWindow.setStatusBar(self.statusbar) 46 | 47 | self.retranslateUi(MainWindow) 48 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 49 | 50 | def retranslateUi(self, MainWindow): 51 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) 52 | self.my_button.setText(_translate("MainWindow", "PushButton", None)) 53 | self.my_label.setText(_translate("MainWindow", "TextLabel", None)) 54 | 55 | 56 | if __name__ == "__main__": 57 | import sys 58 | app = QtGui.QApplication(sys.argv) 59 | MainWindow = QtGui.QMainWindow() 60 | ui = Ui_MainWindow() 61 | ui.setupUi(MainWindow) 62 | MainWindow.show() 63 | sys.exit(app.exec_()) 64 | 65 | -------------------------------------------------------------------------------- /my_gui/my_gui_from_pyuic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from PyQt4 import QtGui 5 | from my_gui_class import Ui_MainWindow 6 | 7 | 8 | class MyWindow(QtGui.QMainWindow): 9 | def __init__(self): 10 | super(MyWindow, self).__init__() 11 | self.ui = Ui_MainWindow() 12 | self.ui.setupUi(self) 13 | self.ui.my_button.clicked.connect(self.on_my_button_push) 14 | self.show() 15 | 16 | def on_my_button_push(self): 17 | self.ui.my_label.setText("Button pushed!") 18 | 19 | 20 | if __name__ == '__main__': 21 | app = QtGui.QApplication(sys.argv) 22 | myWindow = MyWindow() 23 | app.exec_() 24 | -------------------------------------------------------------------------------- /other_examples/choose_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Choose file example. 4 | Author: Sammy Pfeiffer 5 | """ 6 | 7 | from PyQt4 import QtGui 8 | import sys 9 | 10 | 11 | class Main(QtGui.QMainWindow): 12 | 13 | def __init__(self, parent=None): 14 | super(Main, self).__init__(parent) 15 | 16 | self.execute_button = QtGui.QPushButton('Choose file') 17 | self.execute_button.clicked.connect(self.choose_file) 18 | 19 | self.path_text = QtGui.QLineEdit("") 20 | 21 | self.layout = QtGui.QHBoxLayout() 22 | self.layout.addWidget(self.execute_button) 23 | self.layout.addWidget(self.path_text) 24 | 25 | self.central_widget = QtGui.QWidget() 26 | self.central_widget.setLayout(self.layout) 27 | 28 | self.setCentralWidget(self.central_widget) 29 | 30 | def choose_file(self): 31 | # TODO: Filter by something? http://doc.qt.io/qt-4.8/qfiledialog.html#filter 32 | # QFileDialog(QWidget parent=None, QString caption=QString(), QString directory=QString(), QString filter=QString()) 33 | path = QtGui.QFileDialog.getOpenFileName() 34 | if path != '': 35 | self.path_text.setText(path) 36 | 37 | if __name__ == '__main__': 38 | app = QtGui.QApplication(sys.argv) 39 | myWidget = Main() 40 | myWidget.show() 41 | app.exec_() 42 | -------------------------------------------------------------------------------- /other_examples/choose_folder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Choose folder example. 4 | Author: Sammy Pfeiffer 5 | """ 6 | 7 | from PyQt4 import QtGui 8 | import sys 9 | 10 | 11 | class Main(QtGui.QMainWindow): 12 | 13 | def __init__(self, parent=None): 14 | super(Main, self).__init__(parent) 15 | 16 | self.execute_button = QtGui.QPushButton('Choose folder') 17 | self.execute_button.clicked.connect(self.choose_folder) 18 | 19 | self.path_text = QtGui.QLineEdit("") 20 | 21 | self.layout = QtGui.QHBoxLayout() 22 | self.layout.addWidget(self.execute_button) 23 | self.layout.addWidget(self.path_text) 24 | 25 | self.central_widget = QtGui.QWidget() 26 | self.central_widget.setLayout(self.layout) 27 | 28 | self.setCentralWidget(self.central_widget) 29 | 30 | def choose_folder(self): 31 | path = QtGui.QFileDialog.getExistingDirectory() 32 | if path != '': 33 | self.path_text.setText(path) 34 | 35 | if __name__ == '__main__': 36 | app = QtGui.QApplication(sys.argv) 37 | myWidget = Main() 38 | myWidget.show() 39 | app.exec_() 40 | -------------------------------------------------------------------------------- /other_examples/error_window.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Error showing example. 4 | Author: Sammy Pfeiffer 5 | """ 6 | 7 | from PyQt4 import QtGui 8 | import sys 9 | 10 | 11 | class Main(QtGui.QMainWindow): 12 | 13 | def __init__(self, parent=None): 14 | super(Main, self).__init__(parent) 15 | 16 | self.execute_button = QtGui.QPushButton('Show error window') 17 | self.execute_button.clicked.connect(self.show_error) 18 | 19 | self.layout = QtGui.QVBoxLayout() 20 | self.layout.addWidget(self.execute_button) 21 | 22 | self.central_widget = QtGui.QWidget() 23 | self.central_widget.setLayout(self.layout) 24 | 25 | self.setCentralWidget(self.central_widget) 26 | 27 | def show_error(self): 28 | QtGui.QMessageBox.warning( 29 | self, "Error", "Showing an error window is simple.") 30 | 31 | if __name__ == '__main__': 32 | app = QtGui.QApplication(sys.argv) 33 | myWidget = Main() 34 | myWidget.show() 35 | app.exec_() 36 | -------------------------------------------------------------------------------- /other_examples/generate_dropdown.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Playing with a dropdown / combo_box. 4 | Author: Sammy Pfeiffer 5 | """ 6 | 7 | from PyQt4 import QtGui 8 | import sys 9 | 10 | 11 | class Main(QtGui.QMainWindow): 12 | 13 | def __init__(self, parent=None): 14 | super(Main, self).__init__(parent) 15 | 16 | options = ['First option', 'Second option', 'Third option'] 17 | default_option = 0 18 | self.combo_box = QtGui.QComboBox() 19 | for idx, option in enumerate(options): 20 | self.combo_box.insertItem(idx, option) 21 | if option == default_option: 22 | self.combo_box.setCurrentIndex(idx) 23 | 24 | # From http://doc.qt.io/qt-4.8/qcombobox.html#signals 25 | self.combo_box.currentIndexChanged.connect(self.on_dropdown_change) 26 | self.text_dropdown = QtGui.QLineEdit("") 27 | 28 | self.layout = QtGui.QHBoxLayout() 29 | self.layout.addWidget(self.combo_box) 30 | self.layout.addWidget(self.text_dropdown) 31 | 32 | self.central_widget = QtGui.QWidget() 33 | self.central_widget.setLayout(self.layout) 34 | 35 | self.setCentralWidget(self.central_widget) 36 | 37 | def on_dropdown_change(self): 38 | option_text = self.combo_box.currentText() 39 | option_index = self.combo_box.currentIndex() 40 | self.text_dropdown.setText(str(option_index) + " " + option_text) 41 | 42 | if __name__ == '__main__': 43 | app = QtGui.QApplication(sys.argv) 44 | myWidget = Main() 45 | myWidget.show() 46 | app.exec_() 47 | -------------------------------------------------------------------------------- /screenshots/choose_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/choose_file.png -------------------------------------------------------------------------------- /screenshots/choose_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/choose_folder.png -------------------------------------------------------------------------------- /screenshots/command_runner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/command_runner.png -------------------------------------------------------------------------------- /screenshots/command_runner_progressbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/command_runner_progressbar.png -------------------------------------------------------------------------------- /screenshots/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/dropdown.png -------------------------------------------------------------------------------- /screenshots/error_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/error_window.png -------------------------------------------------------------------------------- /screenshots/my_gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/my_gui.png -------------------------------------------------------------------------------- /screenshots/qtdesigner1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/qtdesigner1.png -------------------------------------------------------------------------------- /screenshots/qtdesigner2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesomebytes/python_qt_tutorial/c2c455864aca692fdeaf612200e0d6efc845a7ff/screenshots/qtdesigner2.png --------------------------------------------------------------------------------