Buggy MDIWindow in PySide6 - python

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.

Related

Python Widget with SizePolicy

Why the sizePolicy doesn't affect on widgets that aren't in layout?
here is an example:
from PyQt5 import QtWidgets
app = QtWidgets.QApplication([])
window = QtWidgets.QWidget()
window.setGeometry(50, 50, 500, 300)
test_widget = QtWidgets.QWidget(window)
test_widget.setMinimumSize(100, 100)
test_widget.setStyleSheet("background-color:red")
size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
test_widget.setSizePolicy(size_policy)
window.show()
app.exec()
But that doesn't work, if you changed the main window size the red box still has the same size.
So how can I make that red box resizeable when the parent (main window) is changing.
NOTE: I don't want to use Layouts for some reason.
I'm not sure I completely understand your GUI design but you should note that a single cell (as defined by a row/column pair) in a QGridLayout can be occupied by more than a single widget. A (very) simple example demonstrates this...
#!/usr/local/bin/python3
import os
import sys
from PySide2.QtWidgets import QApplication, QGridLayout, QLabel, QPushButton, QWidget
from PySide2.QtCore import Qt
class widget(QWidget):
def __init__ (self, parent = None):
super(widget, self).__init__(parent)
gl = QGridLayout(self)
pb = QPushButton("Show/Hide Menu")
self.menu = QLabel("Menu goes here...")
self.menu.setAlignment(Qt.AlignCenter)
self.menu.setStyleSheet("background-color: #40800000;")
canvas = QLabel("Canvas")
canvas.setAlignment(Qt.AlignCenter)
canvas.setStyleSheet("background-color: #40000080;")
gl.addWidget(pb, 0, 0)
gl.addWidget(canvas, 0, 0, 2, 2)
pb.raise_()
pb.clicked.connect(self.toggle_menu)
gl.addWidget(self.menu, 1, 0)
self.menu.hide()
def toggle_menu (self, checked):
self.menu.setVisible(not self.menu.isVisible())
if __name__ == '__main__':
app = QApplication([])
w = widget()
w.show()
app.exec_()
[I've used PySide2 as I don't have PyQt5 installed.]
So if I have understood correctly then I don't see why you can't make use of a QGridLayout. Could save you a lot of work.

PyQt5 QPushButton

I want to make Pushbutton show me the text like this
1 You clicked
2 PushButton
not in the same line.
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
Class Ui_MainWindow (object):
def setupUi(self, MainWindow):
MainWindow.resize(506, 312)
self.centralwidget = QtWidgets.QWidget(MainWindow)
# adding pushbutton
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(200, 150, 93, 28))
# adding signal and slot
self.pushButton.clicked.connect(self.changelabeltext)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(140, 90, 221, 20))
# keeping the text of label empty before button get clicked
self.label.setText("")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "Push Button"))
def changelabeltext(self):
# changing the text of label after button get clicked
self.label.setText("You clicked PushButton")
# Hiding pushbutton from the main window
# after button get clicked.
self.pushButton.hide()
If __name__ == "__main__":
app = QtWidgets.QApplication (sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
if I understand you correctly, you want the text to be displayed as follows:
You clicked
PushButton
To achieve this, try placing a newline character in between the words like this:
"You clicked \nPushButton"
Alternatively, if this does not display correctly, try adding a new label with the second half of the text to it, or increase the size of the rectangle in which you placed the text.
Although you technically only asked how to place "You clicked" below "Pushbutton" (which can be done by putting a newline in the string "You clicked \nPushButton"), when you do this you will run into another fundamental problem with your code, mainly that you are positioning widgets by drawing them inside a QRect with a static position.
This will produce problems when you change the text or window size, since you will have to manually change the coordinates of the QRect to place then in the correct position.
I took the liberty of rewriting your setupUi to use layouts (which I recommend you research) instead of QRect's. Hope this helps, it should be a drop in replacement:
def setupUi(self, MainWindow):
MainWindow.resize(506, 312)
self.mainWidget = QtWidgets.QWidget(MainWindow)
self.pushButton = QtWidgets.QPushButton()
self.pushButton.clicked.connect(self.changelabeltext)
self.label = QtWidgets.QLabel()
self.label.setText("")
self.hbox = QtWidgets.QHBoxLayout()
self.hbox.addWidget(self.pushButton)
self.hbox.addWidget(self.label)
self.vbox = QtWidgets.QVBoxLayout()
self.vbox.addLayout(self.hbox)
self.hbox.setAlignment(QtCore.Qt.AlignCenter)
self.vbox.setAlignment(QtCore.Qt.AlignCenter)
self.mainWidget.setLayout(self.vbox)
MainWindow.setCentralWidget(self.mainWidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

Select a text in PYQT to copy

I designed a windows desktop app with QT Designer and PYQT5. The problem is that, I can not select any item, text on main window, or on qtablewidget to paste it manually somewhere else. It will make things easier for users not for me. `
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(260, 160, 256, 192))
self.tableWidget.setRowCount(3)
self.tableWidget.setColumnCount(2)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 0, item)
self.input_gunduz = QtWidgets.QLineEdit(self.centralwidget)
self.input_gunduz.setGeometry(QtCore.QRect(370, 70, 71, 20))
self.input_gunduz.setObjectName("input_gunduz")
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setGeometry(QtCore.QRect(220, 70, 101, 21))
font = QtGui.QFont()
font.setPointSize(9)
font.setBold(True)
font.setWeight(75)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
item = self.tableWidget.item(1, 0)
item.setText(_translate("MainWindow", "trial"))
self.tableWidget.setSortingEnabled(__sortingEnabled)
self.label_5.setText(_translate("MainWindow", "Gündüz (kWhr):"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
`
The code is as seen above. Please help me make the main window selectable
Copying of text does not work in the same way for every widget, because each widget type uses even radically different way to show or interact with text.
If you want to copy the text of a QLabel, you have to make it selectable (by using label.setTextInteractionFlags(Qt.TextSelectableByMouse)).
But if you want to copy the text from QTableWidget, things are very different, since a table allows interaction with their items that prevent a simple text selection.
Obviously, the most simple method would be to start editing the item (assuming it's editable) and select its text, but if you want other ways to do that, it depends on how you want to be able to copy the text.
A possibility is to use the ctrl+c keyboard shortcut. To do so, we need to install an event filter on the table widget:
from PyQt5 import QtCore, QtGui, QtWidgets
from mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
# install an event filter on the table widget, so that we can filter all
# its event, including keyboard presses
self.tableWidget.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.KeyPress and event == QtGui.QKeySequence.Copy:
# check if an index is currently selected and it has text
text = self.tableWidget.currentIndex().data()
if text:
# copy that text to the clipboard
QtWidgets.QApplication.clipboard().setText(text)
return super().eventFilter(source, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Note that in the example above I used the multiple inheritance method explained in the documentation about using Designer with ui files. You should never edit the files created by pyuic.
It's also possible to set a menu for the table widget and copy the text from there:
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
# ...
# use the custom context menu policy for the table widget, so that we can
# connect the menu request to a slot
self.tableWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tableWidget.customContextMenuRequested.connect(self.showTableMenu)
def showTableMenu(self, pos):
# get the text of the index at the mouse cursor (if any)
text = self.tableWidget.indexAt(pos).data()
menu = QtWidgets.QMenu()
copyAction = menu.addAction('Copy')
if not text:
copyAction.setEnabled(False)
# show the menu
res = menu.exec_(QtGui.QCursor.pos())
if res == copyAction:
# if the menu has been triggered by the action, copy to the clipboard
QtWidgets.QApplication.clipboard().setText(text)

The distances between the QPushButton in QGridLayout

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)

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