The distances between the QPushButton in QGridLayout - python

I wrote the following program which draws a minefield for game the sapper
# -*- coding: utf-8 -*-
import mainw, sys
from PyQt4 import QtCore, QtGui
class WindowSapper(QtGui.QMainWindow):
buttons=[]
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self,parent)
self.ui=mainw.Ui_mainwin()
self.ui.setupUi(self)
for i in xrange(10):
l=[]
for j in xrange(10):
b=QtGui.QPushButton()
l.append(b)
self.ui.gridLayout.addWidget(b, i, j, 1, 1)
self.buttons.append(l)
def main():
app=QtGui.QApplication(sys.argv)
window=WindowSapper()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I apply also the form module
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mainw.ui'
#
# Created: Tue Nov 27 08:52:39 2012
# by: PyQt4 UI code generator 4.9.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_mainwin(object):
def setupUi(self, mainwin):
mainwin.setObjectName(_fromUtf8("mainwin"))
mainwin.resize(546, 530)
self.centralwidget = QtGui.QWidget(mainwin)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayoutWidget = QtGui.QWidget(self.centralwidget)
self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 30, 521, 461))
self.gridLayoutWidget.setObjectName(_fromUtf8("gridLayoutWidget"))
self.gridLayout = QtGui.QGridLayout(self.gridLayoutWidget)
self.gridLayout.setMargin(0)
self.gridLayout.setHorizontalSpacing(6)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
mainwin.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(mainwin)
self.menubar.setGeometry(QtCore.QRect(0, 0, 546, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
mainwin.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(mainwin)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
mainwin.setStatusBar(self.statusbar)
self.retranslateUi(mainwin)
QtCore.QMetaObject.connectSlotsByName(mainwin)
def retranslateUi(self, mainwin):
mainwin.setWindowTitle(QtGui.QApplication.translate("mainwin", "Сапер", None, QtGui.QApplication.UnicodeUTF8))
class mainwin(QtGui.QMainWindow, Ui_mainwin):
def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
QtGui.QMainWindow.__init__(self, parent, f)
self.setupUi(self)
But it did not meet my expectations: the buttons are not completely filled GridLayout, among them there are free spaces, that is, they are not completely filled cell GridLayout. How to get rid of these gaps?

The first reason you are seeing a ton of spacing is actually not because of the QGridLayout, but because nothing is constraining your layout objects to make them bunch up together. What you would need to do is add a stretch to the layout to eat up as much space as possible, forcing the rest of the items to push together.
QGridLayout does allow you to add stretch items to it, but I think that makes the grid more complicated to navigate later because you always have to account for that spacer row/col. So instead you can just wrap the grid layout in a vertical/horizontal layout and add spacers to those.
Once you do this, you will notice a tiny amount of space left between the rows. Apparently this is just a known thing with QGridLayout (see this other question). But you can play with the size of the buttons, and the min size of the row and columns to get it right:
Here is an example (standalone - not needing your UI module)
class WindowSapper(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self,parent)
self.resize(450,350)
self.centralwidget = QtGui.QWidget()
self.setCentralWidget(self.centralwidget)
self.vLayout = QtGui.QVBoxLayout(self.centralwidget)
self.hLayout = QtGui.QHBoxLayout()
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setSpacing(0)
# center the grid with stretch on both sides
self.hLayout.addStretch(1)
self.hLayout.addLayout(self.gridLayout)
self.hLayout.addStretch(1)
self.vLayout.addLayout(self.hLayout)
# push grid to the top of the window
self.vLayout.addStretch(1)
self.buttons = []
for i in xrange(10):
l=[]
for j in xrange(10):
b=QtGui.QPushButton()
b.setFixedSize(40,30)
l.append(b)
self.gridLayout.addWidget(b, i, j)
self.gridLayout.setColumnMinimumWidth(j, 40)
self.buttons.append(l)
self.gridLayout.setRowMinimumHeight(i, 26)

Related

Buggy MDIWindow in PySide6

I'm using PySide6 and am having some weird glitch in my MDI Area.
The image below shows only two spawned MDIsubwinows. When I go to drag the window, all historical positenter code hereions stay, even when I a move another menu after. Its also super laggy.
For context, I am using Qt Designer to generate .ui files then convert them to .py files.
Here is my code:
from PySide6.QtCore import QRect, QCoreApplication, QMetaObject
from PySide6.QtWidgets import QWidget, QHBoxLayout, QMainWindow, QMdiArea, QMenu, QMenuBar, QMdiSubWindow, QApplication
# Converted .ui file from Qt Designer
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(1920, 1080)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.horizontalLayoutWidget = QWidget(self.centralwidget)
self.horizontalLayoutWidget.setObjectName(u"horizontalLayoutWidget")
self.horizontalLayoutWidget.setGeometry(QRect(0, 0, 1920, 1054))
self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setSpacing(7)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.mdiArea = QMdiArea(self.horizontalLayoutWidget)
self.mdiArea.setObjectName(u"mdiArea")
self.horizontalLayout.addWidget(self.mdiArea)
MainWindow.setCentralWidget(self.centralwidget)
self.menuBar = QMenuBar(MainWindow)
self.menuBar.setObjectName(u"menuBar")
self.menuBar.setGeometry(QRect(0, 0, 1920, 26))
self.menuFile = QMenu(self.menuBar)
self.menuFile.setObjectName(u"menuFile")
self.menuEdit = QMenu(self.menuBar)
self.menuEdit.setObjectName(u"menuEdit")
self.menuView = QMenu(self.menuBar)
self.menuView.setObjectName(u"menuView")
self.menuPreferences = QMenu(self.menuBar)
self.menuPreferences.setObjectName(u"menuPreferences")
self.menuWindow = QMenu(self.menuBar)
self.menuWindow.setObjectName(u"menuWindow")
self.menuHelp = QMenu(self.menuBar)
self.menuHelp.setObjectName(u"menuHelp")
self.menuTools = QMenu(self.menuBar)
self.menuTools.setObjectName(u"menuTools")
MainWindow.setMenuBar(self.menuBar)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
# retranslateUi
# Converted .ui file from Qt Designer
# Custom class to house the application.
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.initialize_subwindows()
self.ui.mdiArea.tileSubWindows()
# build the menus in readable chunks
# ///////////////////////////////////////////////////////////////
def initialize_subwindows(self):
# Enables the windows to last longer than their create function calls.
self.subwindow_dict = {}
# Create all the subwindows. they should initialize into the subwindows_dict
self.create_build_overview_subwindow()
self.create_object_properties_subwindow()
for window in self.subwindow_dict.values():
self.ui.mdiArea.addSubWindow(window)
self.subwindow_dict.clear()
# the next two functions create subwindows and add them to the main collection of subwindows for the MDI area
def create_build_overview_subwindow(self):
build_overview_window = QMdiSubWindow()
build_overview_window.setWindowTitle('Build Overview')
build_overview_window.show()
self.subwindow_dict.update({'build_overview':build_overview_window})
def create_object_properties_subwindow(self):
object_properties_window = QMdiSubWindow()
object_properties_window.setWindowTitle('Object Properties')
object_properties_window.show()
# Return a dict to add to the subwindow list
# for object perminance
self.subwindow_dict.update({'object_properties':object_properties_window})
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec()
You should not call show on a QMdiSubWindow before adding it to the area (which automatically shows it anyway).
A QMdiSubWindow has some special flags set, if you try to call show() before adding it to the area it will theoretically be shown as a normal, independent window. show() also applies some changes to the widget since it's being initialized (and as a top level window, in this case), so what addSubWindow does becomes somehow inconsistent for that reason.
The solution is simple: remove all show() calls for sub windows.
Note that in your code you didn't set a proper layout for the central widget, but only for the horizontalLayoutWidget which then becomes "floating" inside the main window without being able to adapt its size accordingly. Move the MdiArea outside that widget, remove it since it's useless, right click on an empty space of the main window and select a proper layout from the "Lay out" context menu.

PyQt: Mouse events in QGraphicsView

I would like to write a simple program in Python with PyQt.
I have a QGraphicsScene and I would like to do the following:
There are 2 options using two RadioButtons:
For generating points. This way if someone clicks on the scene an ellipse will appear.
For selecting points. This way if someone clicks on a point the selected point will be returned.
I'm kinda new at PyQt and also at GUI programming. My main problem is that I don't really understand how mouse events work in Qt.
If someone was so kind and patient to explain me the basics of mouse events and gave me some tipps for the problem explained above, I would be very grateful.
I attach a picture too, to visualize the problem.
I was trying to do the problem. For placing the widgets I used the Qt Designer, and then created a subclass called SimpleWindow.
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QPen, QBrush
from PyQt5.QtWidgets import QGraphicsScene
import points
class SimpleWindow(QtWidgets.QMainWindow, points.Ui_Dialog):
def __init__(self, parent=None):
super(SimpleWindow, self).__init__(parent)
self.setupUi(self)
self.graphicsView.scene = QGraphicsScene()
self.graphicsView.setScene(self.graphicsView.scene)
self.graphicsView.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.graphicsView.mousePressEvent = self.pixelSelect
def pixelSelect(self, event):
pen = QPen(QtCore.Qt.black)
brush = QBrush(QtCore.Qt.black)
x = event.x()
y = event.y()
if self.radioButton.isChecked():
print(x, y)
self.graphicsView.scene.addEllipse(x, y, 4, 4, pen, brush)
if self.radioButton_2.isChecked():
print(x, y)
app = QtWidgets.QApplication(sys.argv)
form = SimpleWindow()
form.show()
app.exec_()
This is the class generated by the Designer:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(538, 269)
self.graphicsView = QtWidgets.QGraphicsView(Dialog)
self.graphicsView.setGeometry(QtCore.QRect(130, 10, 371, 221))
self.graphicsView.setObjectName("graphicsView")
self.radioButton = QtWidgets.QRadioButton(Dialog)
self.radioButton.setGeometry(QtCore.QRect(20, 30, 82, 31))
self.radioButton.setObjectName("radioButton")
self.radioButton_2 = QtWidgets.QRadioButton(Dialog)
self.radioButton_2.setGeometry(QtCore.QRect(20, 80, 82, 17))
self.radioButton_2.setObjectName("radioButton_2")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.radioButton.setText(_translate("Dialog", "Generate"))
self.radioButton_2.setText(_translate("Dialog", "Select"))
Thank you.
In a QGraphicsView a QGraphicsScene is added, each one manages a system of different coordinates. the QGraphicsView is similar to a camera and a QGraphicsScene is similar to the world, when one adds an item to the scene it must be in its coordinate system.
As you want to add items when you click, it is better to overwrite the mousePressEvent method of QGraphicsScene, and get the position in the coordinates of the scene for which the scenePos() method is used.
Another thing to do is to initialize the attribute setSceneRect() which is the space that QGraphicsView can see.
A recommendation if several buttons are used use a QButtonGroup that maps the buttons making easy the easy handling of the signals.
class GraphicsScene(QGraphicsScene):
def __init__(self, parent=None):
QGraphicsScene.__init__(self, parent)
self.setSceneRect(-100, -100, 200, 200)
self.opt = ""
def setOption(self, opt):
self.opt = opt
def mousePressEvent(self, event):
pen = QPen(QtCore.Qt.black)
brush = QBrush(QtCore.Qt.black)
x = event.scenePos().x()
y = event.scenePos().y()
if self.opt == "Generate":
self.addEllipse(x, y, 4, 4, pen, brush)
elif self.opt == "Select":
print(x, y)
class SimpleWindow(QtWidgets.QMainWindow, points.Ui_Dialog):
def __init__(self, parent=None):
super(SimpleWindow, self).__init__(parent)
self.setupUi(self)
self.scene = GraphicsScene(self)
self.graphicsView.setScene(self.scene)
self.graphicsView.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
group = QButtonGroup(self)
group.addButton(self.radioButton)
group.addButton(self.radioButton_2)
group.buttonClicked.connect(lambda btn: self.scene.setOption(btn.text()))
self.radioButton.setChecked(True)
self.scene.setOption(self.radioButton.text())

Getting widgets nested in QHBoxLayout and QVBoxLayout

I am trying to access all the buttons, labels, text widgets, etc inside nested QVBoxLayout and QHBoxLayout layouts using the children() method. But I am not getting the results I expect: I am only getting the layouts but not the buttons, labels, etc.
Is there a Pythonic way of iterating through all the nested layouts to obtain the buttons, labels, textedit, etc.?
Here is the part where I am having trouble:
for child in self.ui.gridLayout.children():
print "child_name:%s - type:%s" %(child.objectName(),type(child))
for grand_child in child.children():
print "gc_name:%s - type:%s" %(grand_child.objectName(),type(grand_child))
# never prints the buttons, labels, etc
for ggc in grand_child.children():
print "ggc_name:%s - type:%s" %(ggc.objectName(),type(ggc))
# never finds the QLabels
qreg = QRegExp('.+')
widgets = grand_child.findChildren(QLabel,qreg)
print widgets # prints None
Here is the whole code:
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from mygui import Ui_Form
class MyApp(QtGui.QWidget):
def __init__(self,parent=None):
super(MyApp, self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.pushButton_test.clicked.connect(self.click_button)
def click_button(self):
print "Printing layouts and widgets"
for child in self.ui.gridLayout.children():
print "child_name:%s - type:%s" %(child.objectName(),type(child))
for grand_child in child.children():
print "gc_name:%s - type:%s" %(grand_child.objectName(),type(grand_child))
# never prints
for ggc in grand_child.children():
print "ggc_name:%s - type:%s" %(ggc.objectName(),type(ggc))
qreg = QRegExp('.+')
widgets = grand_child.findChildren(QLabel,qreg)
print widgets # prints None
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyApp()
myapp.show()
sys.exit(app.exec_())
And here's mygui.py:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mygui.ui'
#
# Created: Thu Mar 28 14:07:12 2013
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(454, 323)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.lineEdit = QtGui.QLineEdit(Form)
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.horizontalLayout.addWidget(self.lineEdit)
self.pushButton_2 = QtGui.QPushButton(Form)
self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
self.horizontalLayout.addWidget(self.pushButton_2)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtGui.QHBoxLayout()
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
self.label_2 = QtGui.QLabel(Form)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.horizontalLayout_2.addWidget(self.label_2)
self.label = QtGui.QLabel(Form)
self.label.setObjectName(_fromUtf8("label"))
self.horizontalLayout_2.addWidget(self.label)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.textEdit = QtGui.QTextEdit(Form)
self.textEdit.setObjectName(_fromUtf8("textEdit"))
self.verticalLayout.addWidget(self.textEdit)
self.pushButton_test = QtGui.QPushButton(Form)
self.pushButton_test.setObjectName(_fromUtf8("pushButton_test"))
self.verticalLayout.addWidget(self.pushButton_test)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton_2.setText(QtGui.QApplication.translate("Form", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Form", "TextLabel", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "TextLabel", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton_test.setText(QtGui.QApplication.translate("Form", "Print All Widgets", None, QtGui.QApplication.UnicodeUTF8))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Form = QtGui.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
I appreciate your help and input.
Paul
I realized that all the widgets can be accessed from self. Here is the final code I used:
wtypes = [QPushButton,QLabel,QTextEdit]
qreg = QRegExp(r'.*')
mywidgets = {}
for t in wtypes:
mywidgets[t] = self.findChildren(t,qreg)
for button in mywidgets[QPushButton]:
print "button:", button.objectName()
for label in mywidgets[QLabel]:
print "label:", label.objectName()

Python Timer with Qt Design Button and LCD number

Using Qt Designer, and python2.7. I am trying to create a "count up" timer out of a Qt Designer button and LCD number. I would like a single button to start and reset the timer and the LCD number to display the amount of time that has passed with hh:mm:ss format. I am also trying to have a window "pop-up" at 40 minutes, and display a message "Good Job You Made It!"
I have searched for answers, tried many different combinations of google searches... and now all my results are showing up purple (I've already followed the link)! LOL I see many examples in other languages and for countdown timers and for, what seems like, any other and all other combinations of timers and languages... but none for python! Seriously, I've been trying to figure this out for days, and just haven't got anywhere with it.
Below is the code that I do have. I'm thinking the part I need is the rest of the "def doStartReset(self):" function/method.
Hope I am clear enough. Thanks!
#!/usr/bin/python2.7
import sys
from PyQt4 import QtGui,QtCore
from timer_ui import *
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
#build parent user interface
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.btnStartReset, QtCore.SIGNAL('clicked()'), self.doStartReset)
def doStartReset(self):
if __name__ == "__main__":
#This function means this was run directly, not called from another python file.
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
Here is the code for the GUI in _ui.py format if you need it.
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8 except AttributeError:
_fromUtf8 = lambda s: s
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(340, 205)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(40, 50, 261, 81))
self.widget.setObjectName(_fromUtf8("widget"))
self.gridLayout = QtGui.QGridLayout(self.widget)
self.gridLayout.setMargin(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.btnStartReset = QtGui.QPushButton(self.widget)
self.btnStartReset.setObjectName(_fromUtf8("btnStartReset"))
self.gridLayout.addWidget(self.btnStartReset, 0, 0, 1, 1)
self.lcd40MinTimer = QtGui.QLCDNumber(self.widget)
self.lcd40MinTimer.setObjectName(_fromUtf8("lcd40MinTimer"))
self.gridLayout.addWidget(self.lcd40MinTimer, 0, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.btnStartReset.setText(QtGui.QApplication.translate("MainWindow", "Start / Reset", None, QtGui.QApplication.UnicodeUTF8))
Thank you in advance.
Hey Guys.. here is some progress that i've made... sad that its taken me three days to accomplish this much, but hey, none the less it is progress! Now i am going to work on setting format to hh:mm:ss and have button function include start, stop, and reset... Maybe this will help some people and maybe someone can help me! Together I am convinced that we can make it happen! CHEERS!!!
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.lcd = QtGui.QLCDNumber(self)
self.lcd.setGeometry(30, 40, 200, 25)
self.btn = QtGui.QPushButton('Start', self)
self.btn.move(40, 80)
self.btn.clicked.connect(self.doAction)
self.timer = QtCore.QBasicTimer()
self.step = 0
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('QtGui.QLCDNumber')
self.show()
def timerEvent(self, e):
if self.step >= 100:
self.timer.stop()
self.btn.setText('Finished')
return
self.step = self.step + 1
self.lcd.display(self.step)
def doAction(self):
if self.timer.isActive():
self.timer.stop()
self.btn.setText('Start')
else:
self.timer.start(100, self)
self.btn.setText('Stop')
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
xopenex, some time ago I've coded a count-up timer in Python using Qt. Could this be what you've been looking for?
https://github.com/twigmac/count-up-timer

Destructor isn't called after adding a qmenubar

I have the following files (Main window/UI):
files
UI:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created: Sat Apr 23 15:53:12 2011
# by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(object):
### Presetting Model ###
model = QtGui.QFileSystemModel()
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1000, 600)
self.centralWidget = QtGui.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.horizontalLayout_2 = QtGui.QHBoxLayout(self.centralWidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.treeView = QtGui.QTreeView(self.centralWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(2)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.treeView.sizePolicy().hasHeightForWidth())
self.treeView.setSizePolicy(sizePolicy)
self.treeView.setHeaderHidden(True)
self.treeView.setObjectName("treeView")
self.horizontalLayout.addWidget(self.treeView)
self.plainTextEdit = QtGui.QPlainTextEdit(self.centralWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(4)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.plainTextEdit.sizePolicy().hasHeightForWidth())
self.plainTextEdit.setSizePolicy(sizePolicy)
self.plainTextEdit.setObjectName("plainTextEdit")
self.horizontalLayout.addWidget(self.plainTextEdit)
self.horizontalLayout_2.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralWidget)
### MENU ###
self.menuBar = QtGui.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 600, 27))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
### Setting up tree view model ###
self.treeView.setModel(self.model)
self.treeView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
# self.treeView.setRootIndex(self.model.setRootPath(Xmldocument.directorypath))
### Hiding additional info in treeview ###
hHeader = self.treeView.header()
hHeader.hideSection(1)
hHeader.hideSection(2)
hHeader.hideSection(3)
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "VeloCondDB Browser", None, QtGui.QApplication.UnicodeUTF8))
QtCore.QMetaObject.connectSlotsByName(MainWindow)
##############################################################
def __del__(self):
print "DESTRUCTOR"
Main Window:
import sys
import os
from browserclass_UI import Ui_MainWindow
from PyQt4 import QtCore, QtGui
class Browser(QtGui.QMainWindow):
#############################################################################################
def __init__(self, parent=None):
"""Constructor for the main window."""
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
menuitems = ["Open", "Close"]
menu = self.ui.menuBar.addMenu('File')
for item in menuitems:
entry = menu.addAction(item)
self.connect(entry, QtCore.SIGNAL('triggered()'), lambda item=item: self.doStuff(item))
#############################################################################################
def doStuff(self, item):
print item
#############################################################################################
if __name__ == "__main__":
browser = QtGui.QApplication(sys.argv)
myapp = Browser()
myapp.show()
sys.exit(browser.exec_())
When lines from:
menuitems...
to
self.connect...
are not commented, destructor from UI is never being called. If they are commented everything works fine. Any ideas?
You can't rely on __del__ being called for all of your objects, especially when your program is ending (see that other answer)
According to PyQt documentation:
However, if a slot is a lambda function or a partial function then
its reference count is automatically incremented to prevent it from
being immediately garbage collected.
Some circular references to your Browser object might be created when you connect the signal the lambda functions, and that is what keeps it from being destroyed. As ui is referenced by Browser, it doesn't get destroyed either.
So, you have to disconnect the slots manually when these slots are lambda functions. or use another method than lambda to bind an extra parameters to the slot (e.g. QSignalMapper, or the signal QMenu.triggered that has the QAction as parameter):
def __init__(self, parent):
...
for item in menuitems:
entry = menu.addAction(item)
menu.triggered.connect(self.doStuff)
def doStuff(self, entry):
print entry.text()

Categories