【发布时间】:2015-06-14 22:31:41
【问题描述】:
编辑:PyQt4 进度条上有许多类似的帖子没有更新。他们都关注线程问题以及程序实际更新窗口的位置。尽管有帮助,但我的代码结构如此复杂,以至于回复不实用。此处给出的公认答案很简单,而且很有效。
我在 Win 7 x64 机器上使用 Python 2.7 和 PyQT 4。
我正在尝试清除我的窗口中的一个小部件、一个“接受”按钮、查看代码并将其替换为进度条。
即使我关闭“接受”按钮并在进入处理循环之前添加进度条。窗口仅在循环完成且进度条直接跳转到 100% 后更新。
我的代码,
from PyQt4 import QtCore, QtGui
import sys
import time
class CentralWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(CentralWidget, self).__init__(parent)
# set layouts
self.layout = QtGui.QVBoxLayout(self)
# Poly names
self.pNames = QtGui.QLabel("Import file name", self)
self.polyNameInput = QtGui.QLineEdit(self)
# Polytype selection
self.polyTypeName = QtGui.QLabel("Particle type", self)
polyType = QtGui.QComboBox(self)
polyType.addItem("")
polyType.addItem("Random polyhedra")
polyType.addItem("Spheres")
polyType.addItem("Waterman polyhedra")
polyType.activated[str].connect(self.onActivated)
# Place widgets in layout
self.layout.addWidget(self.pNames)
self.layout.addWidget(self.polyNameInput)
self.layout.addWidget(self.polyTypeName)
self.layout.addWidget(polyType)
self.layout.addStretch()
# Combobox choice
def onActivated(self, text):
if text=="Random polyhedra":
self.randomPolyhedra(text)
if text=="Spheres": # not implementaed yet
self.polyTypeName.setText("Not implemented yet.")
self.polyTypeName.adjustSize()
if text=="Waterman polyhedra": # not implementaed yet
self.polyTypeName.setText("Not implemented yet.")
self.polyTypeName.adjustSize()
# New options for random polyhedra choice
def randomPolyhedra(self, text):
self.polyNumberLbl = QtGui.QLabel("How many: ", self)
self.polyNumber = QtGui.QLineEdit(self)
self.acceptSeed = QtGui.QPushButton('Accept') # Accept button created
self.acceptSeed.clicked.connect(lambda: self.ranPolyGen())
self.layout.addWidget(self.polyNumberLbl)
self.layout.addWidget(self.polyNumber)
self.layout.addWidget(self.acceptSeed) # Accept button in layout
self.randFlag = True
self.polyTypeName.setText(text)
self.polyTypeName.adjustSize()
# Act on option choices for random polyhedra
def ranPolyGen(self):
polyCount = int(self.polyNumber.text())
self.progressBar = QtGui.QProgressBar() # Progress bar created
self.progressBar.setMinimum(1)
self.progressBar.setMaximum(polyCount)
self.acceptSeed.close() # Accept button closed
self.layout.addWidget(self.progressBar) # Add progressbar to layout
for poly in range(1, polyCount+1):
time.sleep(1) # Calls to main polyhedral generating code go here
print poly
self.progressBar.setValue(poly)
self.doneLbl = QtGui.QLabel("Done", self)
self.layout.addWidget(self.doneLbl)
# Creates GUI
class Polyhedra(QtGui.QMainWindow):
def __init__(self):
super(Polyhedra, self).__init__()
# Place central widget in layout
self.central_widget = CentralWidget(self)
self.setCentralWidget(self.central_widget)
# Set up window
self.setGeometry(500, 500, 300, 300)
self.setWindowTitle('Pyticle')
self.show()
# Combo box
def onActivated(self, text):
self.central_widget.onActivated(text)
def main():
app = QtGui.QApplication(sys.argv)
poly = Polyhedra()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
下面是循环执行期间和完成后的图片。
我认为我没有理解 addWidget() 方法。我的印象是,这会在当前布局中添加另一个小部件(此处为 vbox 布局),并且 .close() 方法会在指示这样做时删除一个小部件。
我错过了什么?
【问题讨论】:
-
从按下
Accept按钮到出现完整的进度条需要多长时间?您确定计算不是很快就完成了,所以您看不到进度条在前进吗? -
它冻结了,因为在达到 100% 之前没有任何更新,请尝试在循环中添加
QApplication.processEvents() -
PyQt GUI order of operations 的可能重复项
-
@three_pineapples:我读了那篇文章,但我并没有真正理解它(以及许多类似的文章),但 Padraic 在这里给出的解决方案实际上解决了这个问题,我还没有在网站的其他地方遇到过。
-
虽然答案可能会解决问题,但我不会说这是一个好的解决方案。任何长时间运行的代码都会使 Qt 无法正常运行(例如重绘 GUI 或响应鼠标点击)。
processEvents()确实有助于 Qt 保持响应,但我认为让 Qt 手动处理事件而不是让事件循环自然运行是有风险的。我见过有人因为使用processEvents()而导致内存泄漏或应用程序崩溃。一般来说,长时间运行的代码应该移到线程中。