Python 编程/PyQt4
警告:本页面上的示例混合了 PyQt3 和 PyQt4 - 请谨慎使用!
本教程旨在提供一个动手指南,教你学习用 Python 构建小型 Qt4 应用程序的基础知识。
要学习本教程,你需要具备基本的 Python 知识。然而,不需要 Qt4 方面的知识。我在这些示例中使用的是 Linux,并假设你已经安装了 Python 和 PyQt4。为了测试这一点,打开一个 Python shell(在控制台中输入“Python”以启动交互式解释器)并输入
>>> import PyQt4
如果没有出现错误消息,说明你已经准备就绪。
本教程中的示例尽可能简单,展示了编写和构建程序的实用方法。阅读示例文件中的源代码非常重要,大部分解释都在代码中。熟悉 PyQt 的最佳方法是玩示例并尝试更改它们。
让我们从一个简单的例子开始:弹出一个窗口并显示一些内容。以下小程序将弹出一个显示“你好,世界!”的窗口。
#!/usr/bin/env python
import sys
from PyQt4 import Qt
# We instantiate a QApplication passing the arguments of the script to it:
a = Qt.QApplication(sys.argv)
# Add a basic widget to this application:
# The first argument is the text we want this QWidget to show, the second
# one is the parent widget. Since Our "hello" is the only thing we use (the
# so-called "MainWidget", it does not have a parent.
hello = Qt.QLabel("Hello, World")
# ... and that it should be shown.
hello.show()
# Now we can start it.
a.exec_()
大约 7 行代码,这就是最简单的实现方式。
让我们添加一些交互性!我们将用一个按钮替换显示“你好,世界!”的标签,并为其分配一个操作。这个分配是通过将一个信号(按钮被按下时发送的事件)连接到一个槽(一个操作,通常是一个在事件发生时运行的函数)来实现的。
#!/usr/bin/env python
import sys
from PyQt4 import Qt
a = Qt.QApplication(sys.argv)
# Our function to call when the button is clicked
def sayHello():
print ("Hello, World!")
# Instantiate the button
hellobutton = Qt.QPushButton("Say 'Hello world!'")
# And connect the action "sayHello" to the event "button has been clicked"
hellobutton.clicked.connect(sayHello)
# The rest is known already...
#a.setMainWidget(hellobutton)
hellobutton.show()
a.exec_()
你可以想象,用这种方式编码不可扩展,也不是你想要继续使用的方式。因此,让我们使它更 Pythonic,添加结构并实际使用面向对象编程。我们创建自己的应用程序类,继承自 QApplication,并将应用程序的自定义内容放到它的方法中:一个方法来构建小部件,一个槽,它包含在接收到信号时执行的代码。
#!/usr/bin/env python
import sys
from PyQt4 import Qt
class HelloApplication(Qt.QApplication):
def __init__(self, args):
""" In the constructor we're doing everything to get our application
started, which is basically constructing a basic QApplication by
its __init__ method, then adding our widgets and finally starting
the exec_loop."""
Qt.QApplication.__init__(self, args)
self.addWidgets()
def addWidgets(self):
""" In this method, we're adding widgets and connecting signals from
these widgets to methods of our class, the so-called "slots"
"""
self.hellobutton = Qt.QPushButton("Say 'Hello world!'")
self.hellobutton.clicked.connect(self.slotSayHello)
self.hellobutton.show()
def slotSayHello(self):
""" This is an example slot, a method that gets called when a signal is
emitted """
print ("Hello, World!")
# Only actually do something if this script is run standalone, so we can test our
# application, but we're also able to import this program without actually running
# any code.
if __name__ == "__main__":
app = HelloApplication(sys.argv)
app.exec_()
… 所以我们想要使用 Qt3 Designer 来创建我们的 GUI。在图片中,你可以看到一个简单的 GUI,其中用绿色字母标注了小部件的名称。我们要做的是:我们将 Qt Designer 中的 .ui 文件编译成一个 Python 类,我们继承该类并将其用作我们的 mainWidget。这样,我们就能从 Qt Designer 中更改用户界面,而不用担心代码中的更改。
pyuic4 testapp_ui.ui -o testapp_ui.py
生成一个我们可以使用的 Python 文件。
程序的工作方式可以描述如下:我们填写 lineedit,点击添加按钮将连接到一个方法,该方法从 lineedit 中读取文本,用它创建一个 listviewitem 并将其添加到 listview。点击删除按钮将从 listview 中删除当前选定的项目。以下是包含大量注释的代码(仅在 PyQt3 中有效)
#!/usr/bin/env python
from testapp_ui import TestAppUI
from qt import *
import sys
class HelloApplication(QApplication):
def __init__(self, args):
""" In the constructor we're doing everything to get our application
started, which is basically constructing a basic QApplication by
its __init__ method, then adding our widgets and finally starting
the exec_loop."""
QApplication.__init__(self, args)
# We pass None since it's the top-level widget, we could in fact leave
# that one out, but this way it's easier to add more dialogs or widgets.
self.maindialog = TestApp(None)
self.setMainWidget(self.maindialog)
self.maindialog.show()
self.exec_loop()
class TestApp(TestAppUI):
def __init__(self, parent):
# Run the parent constructor and connect the slots to methods.
TestAppUI.__init__(self, parent)
self._connectSlots()
# The listview is initially empty, so the deletebutton will have no effect,
# we grey it out.
self.deletebutton.setEnabled(False)
def _connectSlots(self):
# Connect our two methods to SIGNALS the GUI emits.
self.addbutton.clicked.connect(self._slotAddClicked)
self.deletebutton.clicked.connect(self._slotDeleteClicked)
def _slotAddClicked(self):
# Read the text from the lineedit,
text = self.lineedit.text()
# if the lineedit is not empty,
if len(text):
# insert a new listviewitem ...
lvi = QListViewItem(self.listview)
# with the text from the lineedit and ...
lvi.setText(0,text)
# clear the lineedit.
self.lineedit.clear()
# The deletebutton might be disabled, since we're sure that there's now
# at least one item in it, we enable it.
self.deletebutton.setEnabled(True)
def _slotDeleteClicked(self):
# Remove the currently selected item from the listview.
self.listview.takeItem(self.listview.currentItem())
# Check if the list is empty - if yes, disable the deletebutton.
if self.listview.childCount() == 0:
self.deletebutton.setEnabled(False)
if __name__ == "__main__":
app = HelloApplication(sys.argv)
这段代码也非常有用,它可以在 PyQt4 上运行,并且有很多有用的选项
#!/usr/bin/env python
# Copyright (c) 2008-10 Qtrac Ltd. All rights reserved.
# This program or module is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 2 of the License, or
# version 3 of the License, or (at your option) any later version. It is
# provided for educational purposes and is distributed in the hope that
# it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
# the GNU General Public License for more details.
#
#
# Versions
#
# 1.0.1 Fixed bug reported by Brian Downing where paths that contained
# spaces were not handled correctly.
# 1.0.2 Fixed bug reported by Ben Thompson that if the UIC program
# fails, no problem was reported; I try to report one now.
# 1.1.0 Added Remember path option; if checked the program starts with
# the last used path, otherwise with the current directory, unless
# overridden on the command line
# 1.1.1 Changed default path on Windows to match PyQt 4.4
# 1.2.1 Changed import style + bug fixes
# 1.2.2 Added stderr to error message output as per Michael Jackson's
# suggestion
# 1.2.3 Tried to make the paths work on Mac OS X
# 1.2.4 Added more options
# 1.2.5 Use "new-style" connections (src.signal.connect(target.slot) instead of
# src.connect(src, SIGNAL("signal()"), target.slot)) and improve PEP-8
# compliance
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future_builtins import *
import os
import platform
import stat
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
__version__ = "1.2.5"
Windows = sys.platform.lower().startswith(("win", "microsoft"))
class OptionsForm(QDialog):
def __init__(self, parent=None):
super(OptionsForm, self).__init__(parent)
settings = QSettings()
if sys.platform.startswith("darwin"):
pyuic4Label = QLabel("pyuic4 (pyuic.py)")
else:
pyuic4Label = QLabel("pyuic4")
self.pyuic4Label = QLabel(settings.value("pyuic4",
QVariant(PYUIC4)).toString())
self.pyuic4Label.setFrameStyle(QFrame.StyledPanel|
QFrame.Sunken)
pyuic4Button = QPushButton("py&uic4...")
pyrcc4Label = QLabel("pyrcc4")
self.pyrcc4Label = QLabel(settings.value("pyrcc4",
QVariant(PYRCC4)).toString())
self.pyrcc4Label.setFrameStyle(QFrame.StyledPanel|
QFrame.Sunken)
pyrcc4Button = QPushButton("p&yrcc4...")
pylupdate4Label = QLabel("pylupdate4")
self.pylupdate4Label = QLabel(settings.value("pylupdate4",
QVariant(PYLUPDATE4)).toString())
self.pylupdate4Label.setFrameStyle(QFrame.StyledPanel|
QFrame.Sunken)
pylupdate4Button = QPushButton("&pylupdate4...")
lreleaseLabel = QLabel("lrelease")
self.lreleaseLabel = QLabel(settings.value("lrelease",
QVariant("lrelease")).toString())
self.lreleaseLabel.setFrameStyle(QFrame.StyledPanel|
QFrame.Sunken)
lreleaseButton = QPushButton("&lrelease...")
toolPathGroupBox = QGroupBox("Tool Paths")
pathsLayout = QGridLayout()
pathsLayout.addWidget(pyuic4Label, 0, 0)
pathsLayout.addWidget(self.pyuic4Label, 0, 1)
pathsLayout.addWidget(pyuic4Button, 0, 2)
pathsLayout.addWidget(pyrcc4Label, 1, 0)
pathsLayout.addWidget(self.pyrcc4Label, 1, 1)
pathsLayout.addWidget(pyrcc4Button, 1, 2)
pathsLayout.addWidget(pylupdate4Label, 2, 0)
pathsLayout.addWidget(self.pylupdate4Label, 2, 1)
pathsLayout.addWidget(pylupdate4Button, 2, 2)
pathsLayout.addWidget(lreleaseLabel, 3, 0)
pathsLayout.addWidget(self.lreleaseLabel, 3, 1)
pathsLayout.addWidget(lreleaseButton, 3, 2)
toolPathGroupBox.setLayout(pathsLayout)
resourceModuleNamesGroupBox = QGroupBox(
"Resource Module Names")
qrcFiles = bool(int(settings.value("qrc_resources", "1").toString()))
self.qrcRadioButton = QRadioButton("&qrc_file.py")
self.qrcRadioButton.setChecked(qrcFiles)
self.rcRadioButton = QRadioButton("file_&rc.py")
self.rcRadioButton.setChecked(not qrcFiles)
radioLayout = QHBoxLayout()
radioLayout.addWidget(self.qrcRadioButton)
radioLayout.addWidget(self.rcRadioButton)
resourceModuleNamesGroupBox.setLayout(radioLayout)
self.pyuic4xCheckBox = QCheckBox("Run pyuic4 with -&x "
" to make forms stand-alone runable")
x = bool(int(settings.value("pyuic4x", "0").toString()))
self.pyuic4xCheckBox.setChecked(x)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
QDialogButtonBox.Cancel)
layout = QVBoxLayout()
layout.addWidget(toolPathGroupBox)
layout.addWidget(resourceModuleNamesGroupBox)
layout.addWidget(self.pyuic4xCheckBox)
layout.addWidget(buttonBox)
self.setLayout(layout)
pyuic4Button.clicked.connect(lambda: self.setPath("pyuic4"))
pyrcc4Button.clicked.connect(lambda: self.setPath("pyrcc4"))
pylupdate4Button.clicked.connect(lambda: self.setPath("pylupdate4"))
lreleaseButton.clicked.connect(lambda: self.setPath("lrelease"))
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
self.setWindowTitle("Make PyQt - Options")
def accept(self):
settings = QSettings()
settings.setValue("pyuic4", QVariant(self.pyuic4Label.text()))
settings.setValue("pyrcc4", QVariant(self.pyrcc4Label.text()))
settings.setValue("pylupdate4",
QVariant(self.pylupdate4Label.text()))
settings.setValue("lrelease", QVariant(self.lreleaseLabel.text()))
settings.setValue("qrc_resources",
"1" if self.qrcRadioButton.isChecked() else "0")
settings.setValue("pyuic4x",
"1" if self.pyuic4xCheckBox.isChecked() else "0")
QDialog.accept(self)
def setPath(self, tool):
if tool == "pyuic4":
label = self.pyuic4Label
elif tool == "pyrcc4":
label = self.pyrcc4Label
elif tool == "pylupdate4":
label = self.pylupdate4Label
elif tool == "lrelease":
label = self.lreleaseLabel
path = QFileDialog.getOpenFileName(self,
"Make PyQt - Set Tool Path", label.text())
if path:
label.setText(QDir.toNativeSeparators(path))
class Form(QMainWindow):
def __init__(self):
super(Form, self).__init__()
pathLabel = QLabel("Path:")
settings = QSettings()
rememberPath = settings.value("rememberpath",
QVariant(True if Windows else False)).toBool()
if rememberPath:
path = (unicode(settings.value("path").toString()) or
os.getcwd())
else:
path = (sys.argv[1] if len(sys.argv) > 1 and
QFile.exists(sys.argv[1]) else os.getcwd())
self.pathLabel = QLabel(path)
self.pathLabel.setFrameStyle(QFrame.StyledPanel|
QFrame.Sunken)
self.pathLabel.setToolTip("The relative path; all actions will "
"take place here,<br>and in this path's subdirectories "
"if the Recurse checkbox is checked")
self.pathButton = QPushButton("&Path...")
self.pathButton.setToolTip(self.pathLabel.toolTip().replace(
"The", "Sets the"))
self.recurseCheckBox = QCheckBox("&Recurse")
self.recurseCheckBox.setToolTip("Clean or build all the files "
"in the path directory,<br>and all its subdirectories, "
"as deep as they go.")
self.transCheckBox = QCheckBox("&Translate")
self.transCheckBox.setToolTip("Runs <b>pylupdate4</b> on all "
"<tt>.py</tt> and <tt>.pyw</tt> files in conjunction "
"with each <tt>.ts</tt> file.<br>Then runs "
"<b>lrelease</b> on all <tt>.ts</tt> files to produce "
"corresponding <tt>.qm</tt> files.<br>The "
"<tt>.ts</tt> files must have been created initially by "
"running <b>pylupdate4</b><br>directly on a <tt>.py</tt> "
"or <tt>.pyw</tt> file using the <tt>-ts</tt> option.")
self.debugCheckBox = QCheckBox("&Dry Run")
self.debugCheckBox.setToolTip("Shows the actions that would "
"take place but does not do them.")
self.logBrowser = QTextBrowser()
self.logBrowser.setLineWrapMode(QTextEdit.NoWrap)
self.buttonBox = QDialogButtonBox()
menu = QMenu(self)
optionsAction = menu.addAction("&Options...")
self.rememberPathAction = menu.addAction("&Remember path")
self.rememberPathAction.setCheckable(True)
self.rememberPathAction.setChecked(rememberPath)
aboutAction = menu.addAction("&About")
moreButton = self.buttonBox.addButton("&More",
QDialogButtonBox.ActionRole)
moreButton.setMenu(menu)
moreButton.setToolTip("Use <b>More->Tool paths</b> to set the "
"paths to the tools if they are not found by default")
self.buildButton = self.buttonBox.addButton("&Build",
QDialogButtonBox.ActionRole)
self.buildButton.setToolTip("Runs <b>pyuic4</b> on all "
"<tt>.ui</tt> "
"files and <b>pyrcc4</b> on all <tt>.qrc</tt> files "
"that are out-of-date.<br>Also runs <b>pylupdate4</b> "
"and <b>lrelease</b> if the Translate checkbox is "
"checked.")
self.cleanButton = self.buttonBox.addButton("&Clean",
QDialogButtonBox.ActionRole)
self.cleanButton.setToolTip("Deletes all <tt>.py</tt> files that "
"were generated from <tt>.ui</tt> and <tt>.qrc</tt> "
"files,<br>i.e., all files matching <tt>qrc_*.py</tt>, "
"<tt>*_rc.py</tt> and <tt>ui_*.py.")
quitButton = self.buttonBox.addButton("&Quit",
QDialogButtonBox.RejectRole)
topLayout = QHBoxLayout()
topLayout.addWidget(pathLabel)
topLayout.addWidget(self.pathLabel, 1)
topLayout.addWidget(self.pathButton)
bottomLayout = QHBoxLayout()
bottomLayout.addWidget(self.recurseCheckBox)
bottomLayout.addWidget(self.transCheckBox)
bottomLayout.addWidget(self.debugCheckBox)
bottomLayout.addStretch()
bottomLayout.addWidget(self.buttonBox)
layout = QVBoxLayout()
layout.addLayout(topLayout)
layout.addWidget(self.logBrowser)
layout.addLayout(bottomLayout)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
aboutAction.triggered.connect(self.about)
optionsAction.triggered.connect(self.setOptions)
self.pathButton.clicked.connect(self.setPath)
self.buildButton.clicked.connect(self.build)
self.cleanButton.clicked.connect(self.clean)
quitButton.clicked.connect(self.close)
self.setWindowTitle("Make PyQt")
def closeEvent(self, event):
settings = QSettings()
settings.setValue("rememberpath",
QVariant(self.rememberPathAction.isChecked()))
settings.setValue("path", QVariant(self.pathLabel.text()))
event.accept()
def about(self):
QMessageBox.about(self, "About Make PyQt",
"""<b>Make PyQt</b> v {0}
<p>Copyright © 2007-10 Qtrac Ltd.
All rights reserved.
<p>This application can be used to build PyQt
applications.
It runs pyuic4, pyrcc4, pylupdate4, and lrelease as
required, although pylupdate4 must be run directly to
create the initial .ts files.
<p>Python {1} - Qt {2} - PyQt {3} on {4}""".format(
__version__, platform.python_version(),
QT_VERSION_STR, PYQT_VERSION_STR,
platform.system()))
def setPath(self):
path = QFileDialog.getExistingDirectory(self,
"Make PyQt - Set Path", self.pathLabel.text())
if path:
self.pathLabel.setText(QDir.toNativeSeparators(path))
def setOptions(self):
dlg = OptionsForm(self)
dlg.exec_()
def build(self):
self.updateUi(False)
self.logBrowser.clear()
recurse = self.recurseCheckBox.isChecked()
path = unicode(self.pathLabel.text())
self._apply(recurse, self._build, path)
if self.transCheckBox.isChecked():
self._apply(recurse, self._translate, path)
self.updateUi(True)
def clean(self):
self.updateUi(False)
self.logBrowser.clear()
recurse = self.recurseCheckBox.isChecked()
path = unicode(self.pathLabel.text())
self._apply(recurse, self._clean, path)
self.updateUi(True)
def updateUi(self, enable):
for widget in (self.buildButton, self.cleanButton,
self.pathButton, self.recurseCheckBox,
self.transCheckBox, self.debugCheckBox):
widget.setEnabled(enable)
if not enable:
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
else:
QApplication.restoreOverrideCursor()
self.buildButton.setFocus()
def _apply(self, recurse, function, path):
if not recurse:
function(path)
else:
for root, dirs, files in os.walk(path):
for dir in sorted(dirs):
function(os.path.join(root, dir))
def _make_error_message(self, command, process):
err = ""
ba = process.readAllStandardError()
if not ba.isEmpty():
err = ": " + str(QString(ba))
return "<span style="color:red;">FAILED: %s%s</span>" % (command, err)
def _build(self, path):
settings = QSettings()
pyuic4 = unicode(settings.value("pyuic4",
QVariant(PYUIC4)).toString())
pyrcc4 = unicode(settings.value("pyrcc4",
QVariant(PYRCC4)).toString())
prefix = unicode(self.pathLabel.text())
pyuic4x = bool(int(settings.value("pyuic4x", "0").toString()))
if not prefix.endswith(os.sep):
prefix += os.sep
failed = 0
process = QProcess()
for name in os.listdir(path):
source = os.path.join(path, name)
target = None
if source.endswith(".ui"):
target = os.path.join(path,
"ui_" + name.replace(".ui", ".py"))
command = pyuic4
elif source.endswith(".qrc"):
if bool(int(settings.value("qrc_resources", "1").toString())):
target = os.path.join(path,
"qrc_" + name.replace(".qrc", ".py"))
else:
target = os.path.join(path, name.replace(".qrc", "_rc.py"))
command = pyrcc4
if target is not None:
if not os.access(target, os.F_OK) or (
os.stat(source)[stat.ST_MTIME] >
os.stat(target)[stat.ST_MTIME]):
args = ["-o", target, source]
if command == PYUIC4 and pyuic4x:
args.insert(0, "-x")
if (sys.platform.startswith("darwin") and
command == PYUIC4):
command = sys.executable
args = [PYUIC4] + args
msg = ("converted <span style="color:darkblue;">" + source +
"</span> to <span style="color:blue;">" + target +
"</span>")
if self.debugCheckBox.isChecked():
msg = "<span style="color:green;"># " + msg + "</span>"
else:
process.start(command, args)
if (not process.waitForFinished(2 * 60 * 1000) or
not QFile.exists(target)):
msg = self._make_error_message(command,
process)
failed += 1
self.logBrowser.append(msg.replace(prefix, ""))
else:
self.logBrowser.append("<span style="color:green;">"
"# {0} is up-to-date</span>".format(
source.replace(prefix, "")))
QApplication.processEvents()
if failed:
QMessageBox.information(self, "Make PyQt - Failures",
"Try manually setting the paths to the tools "
"using <b>More->Options</b>")
def _clean(self, path):
prefix = unicode(self.pathLabel.text())
if not prefix.endswith(os.sep):
prefix += os.sep
deletelist = []
for name in os.listdir(path):
target = os.path.join(path, name)
source = None
if (target.endswith(".py") or target.endswith(".pyc") or
target.endswith(".pyo")):
if name.startswith("ui_") and not name[-1] in "oc":
source = os.path.join(path, name[3:-3] + ".ui")
elif name.startswith("qrc_"):
if target[-1] in "oc":
source = os.path.join(path, name[4:-4] + ".qrc")
else:
source = os.path.join(path, name[4:-3] + ".qrc")
elif name.endswith(("_rc.py", "_rc.pyo", "_rc.pyc")):
if target[-1] in "oc":
source = os.path.join(path, name[:-7] + ".qrc")
else:
source = os.path.join(path, name[:-6] + ".qrc")
elif target[-1] in "oc":
source = target[:-1]
if source is not None:
if os.access(source, os.F_OK):
if self.debugCheckBox.isChecked():
self.logBrowser.append("<span style="color:green;">"
"# delete {0}</span>".format(
target.replace(prefix, "")))
else:
deletelist.append(target)
else:
self.logBrowser.append("<span style="color:darkred;">"
"will not remove "
"'{0}' since `{1}' not found</span>"
.format(target.replace(prefix, ""),
source.replace(prefix, "")))
if not self.debugCheckBox.isChecked():
for target in deletelist:
self.logBrowser.append("deleted "
"<span style="color:red;">{0}</span>".format(
target.replace(prefix, "")))
os.remove(target)
QApplication.processEvents()
def _translate(self, path):
prefix = unicode(self.pathLabel.text())
if not prefix.endswith(os.sep):
prefix += os.sep
files = []
tsfiles = []
for name in os.listdir(path):
if name.endswith((".py", ".pyw")):
files.append(os.path.join(path, name))
elif name.endswith(".ts"):
tsfiles.append(os.path.join(path, name))
if not tsfiles:
return
settings = QSettings()
pylupdate4 = unicode(settings.value("pylupdate4",
QVariant(PYLUPDATE4)).toString())
lrelease = unicode(settings.value("lrelease",
QVariant(LRELEASE)).toString())
process = QProcess()
failed = 0
for ts in tsfiles:
qm = ts[:-3] + ".qm"
command1 = pylupdate4
args1 = files + ["-ts", ts]
command2 = lrelease
args2 = ["-silent", ts, "-qm", qm]
msg = "updated <span style="color:blue;">{0}</span>".format(
ts.replace(prefix, ""))
if self.debugCheckBox.isChecked():
msg = "<span style="color:green;"># {0}</span>".format(msg)
else:
process.start(command1, args1)
if not process.waitForFinished(2 * 60 * 1000):
msg = self._make_error_message(command1, process)
failed += 1
self.logBrowser.append(msg)
msg = "generated <span style="color:blue;">{0}</span>".format(
qm.replace(prefix, ""))
if self.debugCheckBox.isChecked():
msg = "<span style="color:green;"># {0}</span>".format(msg)
else:
process.start(command2, args2)
if not process.waitForFinished(2 * 60 * 1000):
msg = self._make_error_message(command2, process)
failed += 1
self.logBrowser.append(msg)
QApplication.processEvents()
if failed:
QMessageBox.information(self, "Make PyQt - Failures",
"Try manually setting the paths to the tools "
"using <b>More->Options</b>")
app = QApplication(sys.argv)
PATH = unicode(app.applicationDirPath())
if Windows:
PATH = os.path.join(os.path.dirname(sys.executable),
"Lib/site-packages/PyQt4")
if os.access(os.path.join(PATH, "bin"), os.R_OK):
PATH = os.path.join(PATH, "bin")
if sys.platform.startswith("darwin"):
i = PATH.find("Resources")
if i > -1:
PATH = PATH[:i] + "bin"
PYUIC4 = os.path.join(PATH, "pyuic4")
if sys.platform.startswith("darwin"):
PYUIC4 = os.path.dirname(sys.executable)
i = PYUIC4.find("Resources")
if i > -1:
PYUIC4 = PYUIC4[:i] + "Lib/python2.6/site-packages/PyQt4/uic/pyuic.py"
PYRCC4 = os.path.join(PATH, "pyrcc4")
PYLUPDATE4 = os.path.join(PATH, "pylupdate4")
LRELEASE = "lrelease"
if Windows:
PYUIC4 = PYUIC4.replace("/", "\\") + ".bat"
PYRCC4 = PYRCC4.replace("/", "\\") + ".exe"
PYLUPDATE4 = PYLUPDATE4.replace("/", "\\") + ".exe"
app.setOrganizationName("Qtrac Ltd.")
app.setOrganizationDomain("qtrac.eu")
app.setApplicationName("Make PyQt")
if len(sys.argv) > 1 and sys.argv[1] == "-c":
settings = QSettings()
settings.setValue("pyuic4", QVariant(PYUIC4))
settings.setValue("pyrcc4", QVariant(PYRCC4))
settings.setValue("pylupdate4", QVariant(PYLUPDATE4))
settings.setValue("lrelease", QVariant(LRELEASE))
form = Form()
form.show()
app.exec_()
在 Qt Designer 中创建 GUI 不仅使创建 GUI 更容易,而且也是一个很好的学习工具。你可以测试小部件的外观,查看 Qt 中有哪些可用的小部件,以及查看你可能想要使用的属性。
C++ API 文档也是在使用 PyQt 时非常有用(必须使用)的工具。API 翻译非常直接,使用一段时间后,你会发现开发者 API 文档是你真正需要的工具之一。在 KDE 环境中,konqueror 的默认快捷键是 qt:[widgetname],因此使用 [alt]+[F2],输入“qt:qbutton”会直接带你到正确的 API 文档页面。Trolltech 的文档部分还有更多文档,你可能想看看。
本教程中的前 3 个示例是使用 PyQt4 创建的,最后一个示例使用了仅在 PyQt3 中有效的语法。
注意:本页面的先前版本(适用于 pyqt3)在 http://vizzzion.org/?id=pyqt 中可用。
本文档是在 GNU 自由文档许可证 下发布的。