How to remove Item from QListWidget - python

I'm stuck using myItem.hide() method every time I need to remove Item from QListWidget list. Hiding an item instead of deleting/removing makes things unnecessary complex. I would appreciate if you show me how to delete Item from ListWidget permanently.
from PyQt4 import QtGui, QtCore
class MyApp(object):
def __init__(self):
super(MyApp, self).__init__()
self.mainWidget = QtGui.QWidget()
self.mainLayout = QtGui.QVBoxLayout()
self.mainWidget.setLayout(self.mainLayout)
self.hLayout = QtGui.QHBoxLayout()
self.mainLayout.insertLayout(0, self.hLayout)
self.listA=QtGui.QListWidget()
for i in range(3):
self.listA.addItem('Item '+str(i))
self.hLayout.addWidget(self.listA)
self.buttonGroupbox = QtGui.QGroupBox()
self.buttonlayout = QtGui.QVBoxLayout()
self.buttonGroupbox.setLayout(self.buttonlayout)
okButton = QtGui.QPushButton('Remove Selected')
okButton.clicked.connect(self.removeSel)
self.buttonlayout.addWidget(okButton)
self.mainLayout.addWidget(self.buttonGroupbox)
self.mainWidget.show()
sys.exit(app.exec_())
def removeSel(self):
listItems=self.listA.selectedItems()
if not listItems: return
for item in listItems:
print type(item), dir(item)

I don't know why but removeItemWidget don't work as expected. You have to use take item instead:
def removeSel(self):
listItems=self.listA.selectedItems()
if not listItems: return
for item in listItems:
self.listA.takeItem(self.listA.row(item))

Posting here an example showing how to implement same approach but now applied to QTreeWidget which a bit more involved than QListWidget.
from PyQt4 import QtGui, QtCore
class MyApp(object):
def __init__(self):
super(MyApp, self).__init__()
self.mainWidget = QtGui.QWidget()
self.mainLayout = QtGui.QVBoxLayout()
self.mainWidget.setLayout(self.mainLayout)
self.hLayout = QtGui.QHBoxLayout()
self.mainLayout.insertLayout(0, self.hLayout)
self.listA=QtGui.QTreeWidget()
self.listA.setColumnCount(3)
self.listA.setHeaderLabels(['Checkbox','Name','Data'])
for i in range(3):
item=QtGui.QTreeWidgetItem()
item.setCheckState(0,QtCore.Qt.Checked)
item.setText(1, 'Item '+str(i))
item.setData(2, QtCore.Qt.UserRole, id(item) )
item.setText(2, str(id(item) ) )
self.listA.addTopLevelItem(item)
self.hLayout.addWidget(self.listA)
self.buttonGroupbox = QtGui.QGroupBox()
self.buttonlayout = QtGui.QVBoxLayout()
self.buttonGroupbox.setLayout(self.buttonlayout)
okButton = QtGui.QPushButton('Remove Selected')
okButton.clicked.connect(self.removeSel)
self.buttonlayout.addWidget(okButton)
getDataButton = QtGui.QPushButton('Get Items Data')
getDataButton.clicked.connect(self.getItemsData)
self.buttonlayout.addWidget(getDataButton)
self.mainLayout.addWidget(self.buttonGroupbox)
self.mainWidget.show()
sys.exit(app.exec_())
def removeSel(self):
listItems=self.listA.selectedItems()
if not listItems: return
for item in listItems:
itemIndex=self.listA.indexOfTopLevelItem(item)
self.listA.takeTopLevelItem(itemIndex)
print '\n\t Number of items remaining', self.listA.topLevelItemCount()
def getItemsData(self):
for i in range(self.listA.topLevelItemCount()):
item=self.listA.topLevelItem(i)
itmData=item.data(2, QtCore.Qt.UserRole)
itemId=itmData.toPyObject()
print '\n\t Item Id Stored as Item Data:', itemId, 'Item Checkbox State:', item.checkState(0)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
MyApp()

A ListWidget is a list of ListWidgetItems. A ListWidgetItems can be assigned a custom widget to override the default, so removeItemWidget() only removes the custom widget. Hence the need for takeItem, which pops the item from the list and returns it (similar to how a python list works)

Related

QGroupBox buttons not showing

So basically I'm trying to make an updating QGroupBox with some QPushButtons inside of it, here's the "updating" method and it is always called right after the list is changed:
def repaintList(self):
btn_ls = []
for i in range(len(self.list)):
btn_ls.append(buttons.QPushButton("t"))
layout = QVBoxLayout()
for i in range(len(btn_ls)):
layout.addWidget(btn_ls[i])
it's pretty simple, I have a method that updates the list for me and I've tested the functionality with print(len(self.list)) and print(btn_ls) enough to know that the list updating works, and that the btn_ls is made properly, but I'm not sure why it's not updating on the actual screen.
I've made an example of a simplified version of what I'm trying to accomplish:
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class TestWindow(QWidget):
def __init__(self):
super(TestWindow,self).__init__()
self.list = []
self.cont = TestContainer(self.list, "Test Box", self)
self.adder = AdderButton("Add one", self, self.list, self.cont)
layout = QVBoxLayout()
layout.addWidget(self.cont)
self.setLayout(layout)
self.setGeometry(200,200,200,200)
class TestContainer(QGroupBox):
def __init__(self,ls,ttl,pare):
super(TestContainer,self).__init__(ttl,pare)
self.list = ls
self.repaintButtons()
def repaintButtons(self):
btn_ls = []
for i in range(len(self.list)):
btn_ls.append(QPushButton(str(i),self))
print(self.list)
layout = QVBoxLayout()
for i in range(len(btn_ls)):
layout.addWidget(btn_ls[i])
self.setLayout(layout)
class AdderButton(QPushButton):
def __init__(self,txt,pare,ls,displ):
super(AdderButton,self).__init__(txt,pare)
self.disp = displ
self.list = ls
self.clicked.connect(self.addOne)
def addOne(self):
self.list.append(1)
self.disp.repaintButtons()
def main():
app = QApplication(sys.argv)
tw = TestWindow()
tw.show()
app.exec()
if __name__ == "__main__":
main()
The desired result is that every time I press the button a new QPushButton would appear on the screen...
After doing more research, I came across the update() function which basically repaints the QGroupBox. It works in the sense that it adds one button at a time and updates each time a button is added.
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class TestWindow(QWidget):
def __init__(self):
super(TestWindow,self).__init__()
self.list = []
self.cont = TestContainer(self.list, "Test Box", self)
self.adder = AdderButton("Add one", self, self.list, self.cont)
layout = QVBoxLayout()
layout.addWidget(self.cont)
self.setLayout(layout)
self.setGeometry(200,200,200,200)
class TestContainer(QGroupBox):
def __init__(self,ls,ttl,pare):
super(TestContainer,self).__init__(ttl,pare)
self.list = ls
self.layout = QVBoxLayout()
self.setLayout(self.layout)
def addButton(self):
self.layout.addWidget(QPushButton("thing"))
class AdderButton(QPushButton):
def __init__(self,txt,pare,ls,displ):
super(AdderButton,self).__init__(txt,pare)
self.disp = displ
self.list = ls
self.clicked.connect(self.addOne)
def addOne(self):
self.list.append(1)
self.disp.addButton()
self.disp.update()
def main():
app = QApplication(sys.argv)
tw = TestWindow()
tw.show()
app.exec()
if __name__ == "__main__":
main()
I has to use self.layout() instead of layout to see widgets.
def repaintButtons(self):
btn_ls = []
for i in range(len(self.list)):
btn_ls.append(QPushButton(str(i),self))
print(self.list)
layout = QVBoxLayout()
self.setLayout(layout) # it has to be before `self.layout()`
for i in range(len(btn_ls)):
self.layout().addWidget(btn_ls[i])
BTW: self.setLayout() has to be before self.layout()
But there is other problem.
Using again
layout = QVBoxLayout()
self.setLayout(layout)
doesn't remove previous layout and it doesn't remove previous buttons and finally it adds again the same buttons to layout.
You would need add only new buttons to layout instead of adding all buttons again.
Or you would have to remove widgets from layout before adding them again.
EDIT:
Code which adds new button without removing previous buttons
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class TestWindow(QWidget):
def __init__(self):
super(TestWindow,self).__init__()
self.list = []
self.container = TestContainer("Test Box", self, self.list)
self.adder = AdderButton("Add one", self, self.container)
layout = QVBoxLayout()
layout.addWidget(self.container)
self.setLayout(layout)
self.setGeometry(200,200,200,200)
class TestContainer(QGroupBox):
def __init__(self, title, parent, lst):
super(TestContainer,self).__init__(title, parent)
self.list = lst
layout = QVBoxLayout()
self.setLayout(layout)
# create buttons at start using `self.list`
for item in self.list:
self.layout().addWidget(QPushButton(str(item), self))
def addButton(self, item):
# add new item to `self.list` and create new button
self.list.append(item)
self.layout().addWidget(QPushButton(str(item), self))
class AdderButton(QPushButton):
def __init__(self, text, parent, target):
super(AdderButton,self).__init__(text, parent)
self.target = target
self.clicked.connect(self.addOne)
def addOne(self):
self.target.addButton(1)
def main():
app = QApplication(sys.argv)
tw = TestWindow()
tw.show()
app.exec()
if __name__ == "__main__":
main()
There are examples how to remove items but they don't work for me
Clear all widgets in a layout in pyqt
PyQt How to remove a layout from a layout

Removing dynamically created Qmenu items

I have a Qmenu that I am creating by loading a list with Qsettings and I am trying to be able to remove items from the menu by loading the list in a QListQWidget and deleting the selected items. Currently I am able to delete the menu items in the list widget and it removes them from qsettings as well but I can't figure out how to remove the items from the menu without restarting. I have tried various things such as removeAction etc but haven't been able to figure it out.
Here is my code:
import functools
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QWidget, QPushButton, QHBoxLayout, \
QApplication, QAction, QMenu, QListWidgetItem, \
QListWidget, QGridLayout
class MainWindow(QWidget):
settings = QtCore.QSettings('test_org', 'my_app')
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.layout = QHBoxLayout()
self.menu_btn = QPushButton()
self.menu = QMenu()
self.add_menu = self.menu.addMenu("Menu")
self.menu_btn.setMenu(self.menu)
self.open_list_btn = QPushButton('open list')
self.load_items = self.settings.value('menu_items', [])
for item in self.load_items:
self.action = QAction(item[0], self)
self.action.setData(item)
self.add_menu.addAction(self.action)
self.action.triggered.connect(functools.partial(self.menu_clicked, self.action))
self.layout.addWidget(self.menu_btn)
self.layout.addWidget(self.open_list_btn)
self.setLayout(self.layout)
self.open_list_btn.clicked.connect(self.open_window)
def open_window(self):
self.create_menu_item = List()
self.create_menu_item.show()
def menu_clicked(self, item):
itmData = item.data()
print(itmData)
class List(QWidget):
settings = QtCore.QSettings('test_org', 'my_app')
def __init__(self, parent=None):
super(List, self).__init__(parent)
self.menu_items = self.settings.value('menu_items', [])
self.layout = QGridLayout()
self.list = QListWidget()
self.remove_btn = QPushButton('Remove')
self.layout.addWidget(self.list, 1, 1, 1, 1)
self.layout.addWidget(self.remove_btn, 2, 1, 1, 1)
self.setLayout(self.layout)
self.remove_btn.clicked.connect(self.remove_items)
for item in self.menu_items:
self.item = QListWidgetItem()
self.item.setText(str(item[0]))
self.list.addItem(self.item)
def remove_items(self):
self.menu_items = self.settings.value('menu_items', [])
del self.menu_items[self.list.currentRow()]
self.settings.setValue('menu_items', self.menu_items)
listItems = self.list.selectedItems()
if not listItems: return
for item in listItems:
self.list.takeItem(self.list.row(item))
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
Does anyone have any ideas?
EDIT:
This is the structure of the list in QSettings. I load the menu with this and I load the QlistWidget with this. I am trying to get the menu to remove the items as well when I remove them for the QListWidget.
mylist = ['item_name',['itemdata1', 'itemdata2', 'itemdata3'],
'item_name2',['itemdata1', 'itemdata2', 'itemdata3'],
'item_name3',['itemdata1', 'itemdata2', 'itemdata3']]
I think the data structure that you are using is incorrect because when I execute your code it generates twice as many QActions, the structure I propose is a dictionary where the keys are the name of the QAction and the value of the list of data:
{
'item0': ['itemdata00', 'itemdata01', 'itemdata02'],
'item1': ['itemdata10', 'itemdata11', 'itemdata12'],
...
}
To build the initial configuration use the following script:
create_settings.py
from PyQt5 import QtCore
if __name__ == '__main__':
settings = QtCore.QSettings('test_org', 'my_app')
d = {}
for i in range(5):
key = "item{}".format(i)
value = ["itemdata{}{}".format(i, j) for j in range(3)]
d[key] = value
settings.setValue('menu_items', d)
print(d)
settings.sync()
On the other hand I think that the widget that you want to handle the destruction of QActions should take over the corresponding QMenu as I show below:
import sys
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
layout = QtWidgets.QHBoxLayout(self)
menu_btn = QtWidgets.QPushButton()
open_list_btn = QtWidgets.QPushButton('open list')
layout.addWidget(menu_btn)
layout.addWidget(open_list_btn)
menu = QtWidgets.QMenu()
menu_btn.setMenu(menu)
self.menu_manager = MenuManager("menu_items", "Menu")
menu.addMenu(self.menu_manager.menu)
self.menu_manager.menu.triggered.connect(self.menu_clicked)
open_list_btn.clicked.connect(self.menu_manager.show)
def menu_clicked(self, action):
itmData = action.data()
print(itmData)
class MenuManager(QtWidgets.QWidget):
def __init__(self, key, menuname, parent=None):
super(MenuManager, self).__init__(parent)
self.settings = QtCore.QSettings('test_org', 'my_app')
self.key = key
self.layout = QtWidgets.QVBoxLayout(self)
self.listWidget = QtWidgets.QListWidget()
self.remove_btn = QtWidgets.QPushButton('Remove')
self.layout.addWidget(self.listWidget)
self.layout.addWidget(self.remove_btn)
self.remove_btn.clicked.connect(self.remove_items)
self.menu = QtWidgets.QMenu(menuname)
load_items = self.settings.value(self.key, [])
for name, itemdata in load_items.items():
action = QtWidgets.QAction(name, self.menu)
action.setData(itemdata)
self.menu.addAction(action)
item = QtWidgets.QListWidgetItem(name)
item.setData(QtCore.Qt.UserRole, action)
self.listWidget.addItem(item)
def remove_items(self):
for item in self.listWidget.selectedItems():
it = self.listWidget.takeItem(self.listWidget.row(item))
action = it.data(QtCore.Qt.UserRole)
self.menu.removeAction(action)
self.sync_data()
def sync_data(self):
save_items = {}
for i in range(self.listWidget.count()):
it = self.listWidget.item(i)
action = it.data(QtCore.Qt.UserRole)
save_items[it.text()] = action.data()
self.settings.setValue(self.key, save_items)
self.settings.sync()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I got it figured out. I am not sure of a better way but I did it using object names.
In the MainWindow I set objectNames to self.action using the first item of each list in the list of lists inside the for loop like this:
self.action.setObjectName(item[0])
Then I created this function in the MainWindow class:
def remove_menu_item(self, value):
self.add_menu.removeAction(self.findChild(QAction, value))
Then I added this:
w.remove_menu_item(item.text())
To the remove function in the List class to get the same first item in the list of lists which is now the objectName for the QActions.

How to get currently selected item from QListWidget and not what it remembers

QListWidget returns on .selectedItems() even if there are no items currently selected (it remembers last item clicked or selected. So even if all its items were deselected it still returns what it remembers). But I need QListWidget to return ONLY that item that is currently selected.
.hasFocus() trick is not reliable since all the items could get hidden, QListWidget would be in focus. But it still will go ahead and return an item while nothing is selected.
I'm not sure why you don't think that .selectedItems() doesn't work. I just tried this with the code below and it's working correctly.
import sys
from PySide import QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super().__init__()
self.resize(720, 480)
central_widget = QtGui.QWidget(self)
self.setCentralWidget(central_widget)
layout = QtGui.QHBoxLayout(central_widget)
self.text_edit = QtGui.QTextEdit(central_widget)
layout.addWidget(self.text_edit)
self.drop_list = QtGui.QListWidget(central_widget)
self.drop_list.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
self.drop_list.addItems(['one', 'two', 'three', 'four'])
self.drop_list.itemSelectionChanged.connect(self.show_List)
layout.addWidget(self.drop_list)
statusbar = QtGui.QStatusBar(self)
self.setStatusBar(statusbar)
action_ShowList = QtGui.QAction(self)
action_ShowList.triggered.connect(self.show_List)
self.show()
def show_List(self):
self.text_edit.setText(repr(self.drop_list.selectedItems()))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
frame = MainWindow()
sys.exit(app.exec_())
Everything selected:
Nothing selected:
I ended up using this approach:
def getSelectedItem(self):
if not self.myTreeWidget.hasFocus(): return
for selectedItem in self.myTreeWidget.selectedItems():
if not selectedItem: continue
if selectedItem.isHidden(): continue
return selectedItem
Edited later:
Here is his code (edited) showing the problem I've mentioned.
First select an item, then hide all the items by hitting 'Hide-Unhide' button. Click anywhere inside of now being empty listView (just to make sure everything is deselected). Click "Print Selected" button. Here is the image of the result:
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.resize(720, 480)
central_widget = QtGui.QWidget(self)
self.setCentralWidget(central_widget)
layout = QtGui.QHBoxLayout(central_widget)
self.text_edit = QtGui.QTextEdit(central_widget)
layout.addWidget(self.text_edit)
self.drop_list = QtGui.QListWidget(central_widget)
self.drop_list.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
self.drop_list.addItems(['one', 'two', 'three', 'four'])
layout.addWidget(self.drop_list)
self.show()
self.button1=QtGui.QPushButton("Hide-Unhide Items")
self.button1.clicked.connect(self.hideUnhideItems)
layout.addWidget(self.button1)
self.button2=QtGui.QPushButton("Print Selected")
self.button2.clicked.connect(self.getSelected)
layout.addWidget(self.button2)
def getSelected(self):
self.text_edit.clear()
self.text_edit.setText(repr(self.drop_list.selectedItems()))
def hideUnhideItems(self):
for i in range(self.drop_list.count()):
item=self.drop_list.item(i)
if not item.isHidden():
item.setHidden(True)
else:
item.setHidden(False)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
frame = MainWindow()
sys.exit(app.exec_())

How to identify QListWidget in Python/Qt

With a row of QListWidgets I wonder if there is a simple way to label each so the user would be able to say which List is which.
Here is a dialog's screenshot a code posted below results.
I avoid using any widgets outside of QListWidgets(). Ideal solution would be solved utilizing QListWidgets itself. It would be great if there is a way to place a text line-label similar to those available for QGroupBox with .setTitle('myString'). At very least an ability to place a label as a first list item would be sufficient too...
from PyQt4 import QtGui, QtCore
class MyApp(object):
def __init__(self):
super(MyApp, self).__init__()
app = QtGui.QApplication(sys.argv)
self.mainWidget = QtGui.QWidget()
self.mainLayout = QtGui.QVBoxLayout()
self.mainWidget.setLayout(self.mainLayout)
self.groupbox = QtGui.QGroupBox()
self.groupbox.setTitle('My Groupbox')
self.layout = QtGui.QVBoxLayout()
self.groupbox.setLayout(self.layout)
self.listGroupbox = QtGui.QGroupBox()
self.listLayout = QtGui.QHBoxLayout()
self.listGroupbox.setLayout(self.listLayout)
self.listA=QtGui.QListWidget()
self.listB=QtGui.QListWidget()
self.listLayout.addWidget(self.listA)
self.listLayout.addWidget(self.listB)
self.layout.addWidget(self.listGroupbox)
self.okButton = QtGui.QPushButton('OK')
self.okButton.clicked.connect(self.OK)
self.layout.addWidget(self.okButton)
self.mainLayout.addWidget(self.groupbox)
self.mainWidget.show()
sys.exit(app.exec_())
def OK(self):
print 'Ok'
if __name__ == '__main__':
MyApp()
Unfortunately there's no (Qt-native) way to label a QListView (on which QListWidget is based). If your really don't want additional widgets, I would instead use a single-column QTableWidget, and put the list title in the column header. QTableWidget and QListWidget work pretty similarly, so this probably won't break too much of your existing code.
An example based on yours:
class MyApp(object):
def __init__(self):
# snipped
self.listA = self.prepareTableWidget('List A')
self.listB = self.prepareTableWidget('List B')
# snipped
def prepareTableWidget(self, name):
table = QtGui.QTableWidget()
table.setColumnCount(1)
table.setHorizontalHeaderLabels([name])
table.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
return table
# snipped
Here is my attempt to achieve it without abandoning QListWidget()... utilizing layout's .insertLayout() method to attach QLabel without losing GUI space usually taken by QGroupBox()...
from PyQt4 import QtGui, QtCore
class MyApp(object):
def __init__(self):
super(MyApp, self).__init__()
app = QtGui.QApplication(sys.argv)
self.mainWidget = QtGui.QWidget()
self.mainLayout = QtGui.QVBoxLayout()
self.mainWidget.setLayout(self.mainLayout)
self.groupbox = QtGui.QGroupBox()
self.groupbox.setTitle('My Groupbox')
self.layout = QtGui.QVBoxLayout()
self.groupbox.setLayout(self.layout)
self.listGroupbox = QtGui.QGroupBox()
self.listLayout = QtGui.QHBoxLayout()
self.listGroupbox.setLayout(self.listLayout)
self.listA=QtGui.QListWidget()
self.listB=QtGui.QListWidget()
self.subLayoutA=QtGui.QVBoxLayout()
self.listLayout.insertLayout(0,self.subLayoutA)
self.subLayoutA.addWidget(QtGui.QLabel('Label A') )
self.subLayoutA.addWidget(self.listA)
self.subLayoutB=QtGui.QVBoxLayout()
self.listLayout.insertLayout(1,self.subLayoutB)
self.subLayoutB.addWidget(QtGui.QLabel('Label B') )
self.subLayoutB.addWidget(self.listB)
self.layout.addWidget(self.listGroupbox)
self.okButton = QtGui.QPushButton('OK')
self.okButton.clicked.connect(self.OK)
self.layout.addWidget(self.okButton)
self.mainLayout.addWidget(self.groupbox)
self.mainWidget.show()
sys.exit(app.exec_())
def OK(self):
print 'Ok'
if __name__ == '__main__':
MyApp()

What is best way to remove items from layout in pyqt

I am having some issue with layout in pyqt. After closing the items from the layout still if layout.count() returns the old item count. So I think .close() not really removing items from the layout. Here is a full working example.
import sys
from PyQt4 import QtGui,QtCore
class LayoutTest(QtGui.QWidget):
def __init__(self):
super(LayoutTest, self).__init__()
self.vvbox = QtGui.QVBoxLayout()
self.dvbox = QtGui.QVBoxLayout()
vbox = QtGui.QVBoxLayout()
vbox.addLayout(self.vvbox)
vbox.addLayout(self.dvbox)
self.setLayout(vbox)
self.add_button = QtGui.QPushButton("Add Items")
self.edit_button = QtGui.QPushButton("Remove Items")
self.chk_button = QtGui.QPushButton("Check Items")
self.vvbox.addWidget(self.add_button)
self.vvbox.addWidget(self.edit_button)
self.vvbox.addWidget(self.chk_button)
self.connect(self.add_button, QtCore.SIGNAL("clicked()"), self.addButtons)
self.connect(self.edit_button, QtCore.SIGNAL("clicked()"), self.removeButtons)
self.connect(self.chk_button, QtCore.SIGNAL("clicked()"), self.checkItems)
self.setGeometry(300, 200, 400, 300)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Escape:
self.close()
def addButtons(self):
for i in range(0, 5):
self.r_button = QtGui.QPushButton("Button %s " % i)
self.dvbox.addWidget(self.r_button)
def removeButtons(self):
for cnt in range(self.dvbox.count()):
self.dvbox.itemAt(cnt).widget().close()
def checkItems(self):
QtGui.QMessageBox.information(self, 'Count',"You have %s Items in Layout" % self.dvbox.count(), QtGui.QMessageBox.Ok)
def run():
app = QtGui.QApplication(sys.argv)
ex = LayoutTest()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
run()
Just click two times in add button and after that delete the buttons. Then just check for the items. After closing also you will get you have n items in layout.
So what is the best way to remove widget from a layout other than closing ?
Your comment is indeed a solution but rather than close use deleteLater. It is safer. With a bit of modification, I'd rewrite your method as:
def removeButtons(self):
for cnt in reversed(range(self.dvbox.count())):
# takeAt does both the jobs of itemAt and removeWidget
# namely it removes an item and returns it
widget = self.dvbox.takeAt(cnt).widget()
if widget is not None:
# widget will be None if the item is a layout
widget.deleteLater()

Categories

Resources