I enjoy working with PyQt. Here are several tips I use often to build applications.
Some of them uses the excellent book from Mark Summerfield :
Suppose you've ui_myfile.ui. You want to build an Python executable with it. Open a command line and type in :
pyuic4 -o ui_myfile.py -x ui_myfile.ui
As Mark Summerfield said
Often your program assumes that the application directory is the directory where it is located. But if your program is executed from a different directory, it won't work as expected.
So how to solve this problem ?
So, what's your choice here ? :)
To produce a ressource module, we must do two things :
Suppose you have done a resources.qrc file, you generate a ressources module (here qrc_resources_rc.py ) by :
pyrcc4 -o qrc_resources_rc.py resources.qrc
Suppose you've generated a ui_myfile.py file , create a main.py file with the following contents :
import sys
from PyQt4 import QtGui, QtCore
from ui_myfile import Ui_MainWindow
class MyApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
Inside main.py, and in the if \name\ == "\main\":, put the following lines to ie use the predefined Cleanlooks style.
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
QtGui.QApplication.setPalette(QtGui.QApplication.style().standardPalette())
Doing all this is painfull. I've made a little script wich generates a .py file from a given .ui one, then it creates a 'main.py' file with all you need.
Beware, I'm using Python 2.6 new feature (the with statement). Here it is : 'make.py'.
Launch it with :
python make.py myfile.ui
But be aware to launch this script only one time, otherwise the 'main.py' script will be overwritten and you'll lost all of your code !
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
template = """#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
from %(name)s import Ui_MainWindow
class MyApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
# Setup the ui.
self.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
## Look and feel changed to CleanLooks
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
QtGui.QApplication.setPalette(QtGui.QApplication.style().standardPalette())
window = MyApp()
window.show()
sys.exit(app.exec_())"""
def main(filename):
os.system('pyuic4 -o %(name)s.py -x %(name)s.ui'%{'name': filename})
with open('main.py', 'w') as f:
f.write(template%{'name': filename})
if __name__ == "__main__":
filename = sys.argv[1]
main(filename)
If you read Qt4's doc, you may find some signals like this in C++:
void itemDoubleClicked ( QTableWidgetItem * item )
In PyQt4, you'll have to use the following signal (don't forget the star char !) :
QtCore.SIGNAL("itemDoubleClicked (QTableWidgetItem*)")
Another one, a QComboBox signal:
void currentIndexChanged ( const QString & text )
it has to be translated like this (the string is a constant here, so you'll have to tell it to PyQt):
QtCore.SIGNAL("currentIndexChanged(const QString)")
You can catch any wheel event by defining a wheelEvent method on your widget, ie :
def wheelEvent(self, event):
if event.delta() > 0 :
print "delta positive"
else:
print "delta negative"
You can show a widget in fullscreen mode by using the showFullScreen () method of the widget. Note that this apply only to windows. If you have a toolbar, it will be invisible in fullscreen mode.
Here's a sample of a method I've used inside a MainWindow (in wich self.fullScreen = False by default):
class MonAppli(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.fullScreen = False
QtGui.QShortcut(QtGui.QKeySequence("Ctrl+Shift+W"), self, self.toogleFullScreen )
def toogleFullScreen(self):
if not self.fullScreen :
self.showFullScreen()
else:
self.showNormal()
self.fullScreen = not (self.fullScreen)
This snippet will show you how to handle QScintilla basically (it prints out all the lexers and the editor methods):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Basic use of the QScintilla2 widget
Note : name this file "qt4_sci_test.py"
"""
import PyQt4.Qsci
langs = [i for i in dir(PyQt4.Qsci) if i.startswith('QsciLexer')]
for i,l in enumerate(langs):
print i,l[9:] # we don't need to print "QsciLexer" before each name
import sys
from PyQt4.QtGui import QApplication
from PyQt4 import QtCore, QtGui
from PyQt4.Qsci import QsciScintilla, QsciScintillaBase, QsciLexerPython
if __name__ == "__main__":
app = QApplication(sys.argv)
editor = QsciScintilla()
## define the font to use
font = QtGui.QFont()
font.setFamily("Consolas")
font.setFixedPitch(True)
font.setPointSize(12)
# the font metrics here will help
# building the margin width later
fm = QtGui.QFontMetrics(font)
## set the default font of the editor
## and take the same font for line numbers
editor.setFont(font)
editor.setMarginsFont(font)
## Line numbers
# conventionnaly, margin 0 is for line numbers
editor.setMarginWidth(0, fm.width( "00000" ) + 5)
editor.setMarginLineNumbers(0, True)
## Edge Mode shows a red vetical bar at 80 chars
editor.setEdgeMode(QsciScintilla.EdgeLine)
editor.setEdgeColumn(80)
editor.setEdgeColor(QtGui.QColor("#FF0000"))
## Folding visual : we will use boxes
editor.setFolding(QsciScintilla.BoxedTreeFoldStyle)
## Braces matching
editor.setBraceMatching(QsciScintilla.SloppyBraceMatch)
## Editing line color
editor.setCaretLineVisible(True)
editor.setCaretLineBackgroundColor(QtGui.QColor("#F5F5DC"))
## Margins colors
# line numbers margin
editor.setMarginsBackgroundColor(QtGui.QColor("#333333"))
editor.setMarginsForegroundColor(QtGui.QColor("#CCCCCC"))
# folding margin colors (foreground,background)
editor.setFoldMarginColors(QtGui.QColor("#99CC66"),QtGui.QColor("#333300"))
## Choose a lexer
lexer = QsciLexerPython()
lexer.setDefaultFont(font)
editor.setLexer(lexer)
## Render on screen
editor.show()
## Show this file in the editor
editor.setText(open("test_sci_qt4.py").read())
# Show all the methods of the editor
methods = sorted(QsciScintilla.__dict__.keys())
for m in methods :
print m
sys.exit(app.exec_())
... to be continued
Comments Back to index