I have a simple .xlsx file and I load its content to my qtableview. My code likes this:
import xlrd
from PyQt5 import QtCore, QtGui, QtWidgets, uic
form_class = uic.loadUiType("SearchView.ui")[0] # Load the UI
app = None
myWindow = None
dic_messages = dict()
class MyWindowClass(QtWidgets.QMainWindow, form_class):
def __init__(self, fileName, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.gui = form_class
self.fileName = fileName
self.model = QtGui.QStandardItemModel(self)
self.tableView.setModel(self.model)
self.fn_load_messages()
def fn_load_messages(self):
workbook = xlrd.open_workbook('sample.xlsx')
worksheet = workbook.sheet_by_name('sample_sheet')
for i in range(0, worksheet.nrows):
dic_messages[i + 1] = (worksheet.cell(i, 0).value, worksheet.cell(i, 1).value, worksheet.cell(i, 2).value, worksheet.cell(i, 3).value, worksheet.cell(i, 4).value)
i += 1
rowPosition = self.tbl_messages.rowCount()
self.tbl_messages.insertRow(rowPosition)
return
def main():
global app, myWindow
app = QtWidgets.QApplication(sys.argv)
myWindow = MyWindowClass('sample.xlsx')
myWindow.show()
app.exec_()
if __name__ == '__main__':
main()
i want to add a checkbox column in each row and then i want to check or unchecked each row i want. i added below part to my code but the checkboxes are not active:
self.tableView.setItemDelegateForColumn(0 , CheckBoxDelegate(self))
class CheckBoxDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter, option, index):
check_box_style_option = QtWidgets.QStyleOptionButton()
check_box_style_option.rect = self.getCheckBoxRect(option)
check_box_style_option.state = QtWidgets.QStyle.State_Enabled
QtWidgets.QApplication.style().drawControl(QtWidgets.QStyle.CE_CheckBox,
check_box_style_option, painter)
def getCheckBoxRect(self, option):
check_box_style_option = QtWidgets.QStyleOptionButton()
check_box_rect = QtWidgets.QApplication.style().subElementRect(QtWidgets.QStyle.SE_CheckBoxIndicator, check_box_style_option, None)
check_box_point = QtCore.QPoint (option.rect.x() +
option.rect.width() / 2 -
check_box_rect.width() / 2,
option.rect.y() +
option.rect.height() / 2 -
check_box_rect.height() / 2)
return QtCore.QRect(check_box_point, check_box_rect.size())
how can I do this?
Thanks.
You don't set it in the view but in the items and model. Like this:
#!/usr/bin/env python
from PyQt5 import QtWidgets, QtGui
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.tableModel = QtGui.QStandardItemModel(self)
self.tableModel.itemChanged.connect(self.itemChanged)
item = QtGui.QStandardItem("Click me")
item.setCheckable(True)
self.tableModel.appendRow(item)
self.mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(self.mainLayout)
self.tableView = QtWidgets.QTableView()
self.tableView.setModel(self.tableModel)
self.mainLayout.addWidget(self.tableView)
def itemChanged(self, item):
print("Item {!r} checkState: {}".format(item.text(), item.checkState()))
def main():
app = QtWidgets.QApplication([])
win = MyWidget()
win.show()
win.raise_()
app.exec_()
if __name__ == "__main__":
main()
Related
I am trying to add 'Share' and 'Delete' buttons to each row of the table using "table View" class of PySide.
But I am unable to do since I don't have much knowledge of PySide. Can any one please guide me how to add buttons to table view.
Expected Output:
My code:
import sys
import os
import csv
from PySide import QtGui, QtCore
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.dirPath = "/home/cioc/Documents/GPR/GRP"
self.filePath = ""
self.fileName =""
self.lay1 = QtGui.QVBoxLayout()
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setBackgroundRole(QtGui.QPalette.Light)
self.scrollArea.setWidgetResizable(True)
self.mainLayout =QtGui. QGridLayout()
self.mainLayout.addWidget(self.scrollArea,0,1)
self.setCentralWidget(QtGui.QWidget(self))
self.centralWidget().setLayout(self.mainLayout)
self.setGeometry(100,100,800,500)
self.w = QtGui.QWidget()
self.lay = QtGui.QVBoxLayout()
self.model =QtGui. QStandardItemModel(self)
self.tableView = QtGui.QTableView(self)
self.tableView.setModel(self.model)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.clicked[QtCore.QModelIndex].connect(self.onClick)
self.tableView.verticalHeader().setVisible(False)
self.appendRowItems(self.dirPath)
self.lay.addWidget(self.tableView)
self.w.setLayout(self.lay)
self.scrollArea.setWidget(self.w)
# self.btn_sell = QtGui.QPushButton('Delete')
# self.btn_sell.clicked.connect(self.delete)
def appendRowItems(self, dir):
for root, dirs, files in os.walk(dir):
if root == dir:
for file in files:
self.model.appendRow(QtGui.QStandardItem(file))
# def delete(self,index):
# self.model.clear()
def onClick(self, ind):
self.filePath = self.dirPath +"/"+ self.model.item(ind.row(), ind.column()).text()
print(self.filePath)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
eg = Example()
eg.show()
app.exec_()
One option is to implement a delegate:
import os
import sys
from PySide import QtGui, QtCore
class ViewWidget(QtGui.QWidget):
def __init__(self, x, index, parent=None):
super(ViewWidget, self).__init__(parent)
self.p_index = QtCore.QPersistentModelIndex(index)
self.content_button = QtGui.QWidget(self)
lay = QtGui.QHBoxLayout(self.content_button)
lay.setContentsMargins(0, 0, 0,0)
self.share_btn = QtGui.QPushButton("share")
self.share_btn.clicked.connect(self.share_clicked)
self.delete_btn = QtGui.QPushButton("delete")
self.delete_btn.clicked.connect(self.delete_clicked)
lay.addWidget(self.share_btn)
lay.addWidget(self.delete_btn)
self.content_button.move(x, 0)
#QtCore.Slot()
def delete_clicked(self):
model = self.p_index.model()
model.removeRow(self.p_index.row())
#QtCore.Slot()
def share_clicked(self):
text = self.p_index.data()
full_path = self.p_index.data(QtCore.Qt.UserRole+1)
print(text, full_path)
class ButtonsDelegate(QtGui.QStyledItemDelegate):
def paint(self, painter, option, index):
self.parent().openPersistentEditor(index)
super(ButtonsDelegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
return ViewWidget(300, index, parent)
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
dirPath = "/home/cioc/Documents/GPR/GRP"
self.setCentralWidget(QtGui.QWidget())
layout = QtGui. QGridLayout(self.centralWidget())
self.model =QtGui.QStandardItemModel(self)
self.tableView = QtGui.QTableView()
self.tableView.setModel(self.model)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.clicked.connect(self.onClick)
self.tableView.verticalHeader().hide()
self.appendRowItems(dirPath)
delegate = ButtonsDelegate(self.tableView)
self.tableView.setItemDelegate(delegate)
layout.addWidget(self.tableView)
self.resize(800,500)
def appendRowItems(self, dir_path):
for root, dirs, files in os.walk(dir_path):
if root == dir_path:
for file in files:
item = QtGui.QStandardItem(file)
item.setData(os.path.join(root, file))
self.model.appendRow(item)
#QtCore.Slot(QtCore.QModelIndex)
def onClick(self, ix):
it = self.model.itemFromIndex(ix)
print(it.data())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
eg = Example()
eg.show()
sys.exit(app.exec_())
Or setIndexWidget():
import os
import sys
from PySide import QtGui, QtCore
class ViewWidget(QtGui.QWidget):
def __init__(self, x, index, parent=None):
super(ViewWidget, self).__init__(parent)
self.p_index = QtCore.QPersistentModelIndex(index)
self.content_button = QtGui.QWidget(self)
lay = QtGui.QHBoxLayout(self.content_button)
lay.setContentsMargins(0, 0, 0,0)
self.share_btn = QtGui.QPushButton("share")
self.share_btn.clicked.connect(self.share_clicked)
self.delete_btn = QtGui.QPushButton("delete")
self.delete_btn.clicked.connect(self.delete_clicked)
lay.addWidget(self.share_btn)
lay.addWidget(self.delete_btn)
self.content_button.move(x, 0)
#QtCore.Slot()
def delete_clicked(self):
model = self.p_index.model()
model.removeRow(self.p_index.row())
#QtCore.Slot()
def share_clicked(self):
text = self.p_index.data()
full_path = self.p_index.data(QtCore.Qt.UserRole+1)
print(text, full_path)
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
dirPath = "/home/cioc/Documents/GPR/GRP"
self.setCentralWidget(QtGui.QWidget())
layout = QtGui. QGridLayout(self.centralWidget())
self.model =QtGui.QStandardItemModel(self)
self.tableView = QtGui.QTableView()
self.tableView.setModel(self.model)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.clicked.connect(self.onClick)
self.tableView.verticalHeader().hide()
self.appendRowItems(dirPath)
layout.addWidget(self.tableView)
self.resize(800,500)
def appendRowItems(self, dir_path):
for root, dirs, files in os.walk(dir_path):
if root == dir_path:
for file in files:
item = QtGui.QStandardItem(file)
item.setData(os.path.join(root, file))
self.model.appendRow(item)
ix = self.model.indexFromItem(item)
self.tableView.setIndexWidget(ix, ViewWidget(300, ix))
#QtCore.Slot(QtCore.QModelIndex)
def onClick(self, ix):
it = self.model.itemFromIndex(ix)
print(it.data())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
eg = Example()
eg.show()
sys.exit(app.exec_())
I have used the following code what it does is displays a list of values in the combo box but the difficulty that i am experiencing is that each and every time the value is check ed the drop down closes.
Is there a way possible where instead of the drop down all the menu is displayed in the main window as a list of all check boxes so that multiple values can be clicked at once.
Following is the code snippet.
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class CheckableComboBox(QtWidgets.QComboBox):
def __init__(self, parent = None):
super(CheckableComboBox, self).__init__(parent)
self.setView(QtWidgets.QListView(self))
self.view().pressed.connect(self.handleItemPressed)
self.setModel(QtGui.QStandardItemModel(self))
def handleItemPressed(self, index):
item = self.model().itemFromIndex(index)
if item.checkState() == QtCore.Qt.Checked:
item.setCheckState(QtCore.Qt.Unchecked)
else:
item.setCheckState(QtCore.Qt.Checked)
def checkedItems(self):
checkedItems = []
for index in range(self.count()):
item = self.model().item(index)
if item.checkState() == QtCore.Qt.Checked:
checkedItems.append(item)
return checkedItems
class Ui_dialogCreateBatch(object):
def setupUi(self, dialogCreateBatch):
dialogCreateBatch.resize(400, 338)
dialogCreateBatch.setMouseTracking(True)
self.gridLayoutWidget = QtWidgets.QWidget(dialogCreateBatch)
self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 360, 115))
self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.cboItemList = CheckableComboBox(self.gridLayoutWidget)
self.cboItemList.setObjectName("cboItemList")
self.gridLayout.addWidget(self.cboItemList, 0, 0, 1, 1)
data = ('item1', 'item2', 'item3')
for index, element in enumerate(data):
self.cboItemList.addItem(element)
item = self.cboItemList.model().item(index, 0)
item.setCheckState(QtCore.Qt.Unchecked)
self.buttonBox = QtWidgets.QDialogButtonBox(dialogCreateBatch)
self.buttonBox.setGeometry(QtCore.QRect(100, 300, 156, 23))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.retranslateUi(dialogCreateBatch)
QtCore.QMetaObject.connectSlotsByName(dialogCreateBatch)
def retranslateUi(self, dialogCreateBatch):
_translate = QtCore.QCoreApplication.translate
dialogCreateBatch.setWindowTitle(_translate("dialogCreateBatch", "Create Item Batch"))
class DialogCreateBatch(QtWidgets.QDialog, Ui_dialogCreateBatch):
def __init__(self, parent=None):
QtWidgets.QDialog.__init__(self, parent)
self.setupUi(self)
self.buttonBox.accepted.connect(self.on_accepted)
self.buttonBox.rejected.connect(self.reject)
def on_accepted(self):
selectedItems = self.cboItemList.checkedItems()
print(selectedItems)
self.accept()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = DialogCreateBatch()
w.show()
sys.exit(app.exec_())
The following code implements a QDialog that shows a QListView with a model that has checkable items based on QStandardItemModel:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class DialogCreateBatch(QtWidgets.QDialog):
def __init__(self, parent=None):
super(DialogCreateBatch, self).__init__(parent)
self.model = QtGui.QStandardItemModel(self)
self.view = QtWidgets.QListView()
self.view.setModel(self.model)
self.button_box = QtWidgets.QDialogButtonBox()
self.button_box.setOrientation(QtCore.Qt.Horizontal)
self.button_box.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.view)
lay.addWidget(self.button_box)
#property
def items(self):
items = []
for i in range(self.model.rowCount()):
it = self.model.item(i)
items.append(it.text())
return items
#items.setter
def items(self, items):
self.model.clear()
for item in items:
it = QtGui.QStandardItem(item)
it.setCheckable(True)
self.model.appendRow(it)
#property
def checked_items(self):
checked_items = []
for i in range(self.model.rowCount()):
it = self.model.item(i)
if it.data(QtCore.Qt.CheckStateRole) == QtCore.Qt.Checked:
checked_items.append(it.text())
return checked_items
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = DialogCreateBatch()
w.setWindowTitle("Stack Overflow")
w.items = ("item1", "item2", "item3")
if w.exec_() == QtWidgets.QDialog.Accepted:
print(w.checked_items)
Here is my sample code,i want to add a push button to each and every row of the list view.I am not found any method to set the widget to model.Can any one please help me how to add widget for each and every row of the list view.Thank you in advance.
Given below is my code:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyCustomWidget(QWidget):
def __init__(self,parent=None):
super(MyCustomWidget, self).__init__(parent)
self.row = QHBoxLayout()
self.row.addWidget(QPushButton("add"))
self.setLayout(self.row)
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QtGui.QVBoxLayout(self)
hLayout = QtGui.QHBoxLayout()
self.lineEdit = QtGui.QLineEdit()
hLayout.addWidget(self.lineEdit)
self.filter = QtGui.QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.list = QtGui.QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QtGui.QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
self.list.setModel(self.model)
for code in codes:
item = QtGui.QStandardItem(code)
self.model.appendRow(item)
self.list.setIndexWidget(item.index(), QtGui.QPushButton("button"))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
You have to create a custom widget where you must set the button on the right side with a layout.
import sys
from PyQt4 import QtCore, QtGui
class CustomWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(CustomWidget, self).__init__(parent)
self.button = QtGui.QPushButton("button")
lay = QtGui.QHBoxLayout(self)
lay.addWidget(self.button, alignment=QtCore.Qt.AlignRight)
lay.setContentsMargins(0, 0, 0, 0)
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QtGui.QVBoxLayout(self)
hLayout = QtGui.QHBoxLayout()
self.lineEdit = QtGui.QLineEdit()
hLayout.addWidget(self.lineEdit)
self.filter = QtGui.QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.list = QtGui.QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QtGui.QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
self.list.setModel(self.model)
for code in codes:
item = QtGui.QStandardItem(code)
self.model.appendRow(item)
self.list.setIndexWidget(item.index(), CustomWidget())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
Could someone help me create a recursive function which loops through the treeview QStandardItemModel and collects all items which are 'checked true'
I'm not entirely clear on how to go about doing this myself.
from PySide import QtGui, QtCore
from PySide import QtSvg, QtXml
import sys
class Person:
def __init__(self, name="", children=None):
self.name = name
self.children = children if children else []
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.resize(300, 400)
self.init_ui()
def init_ui(self):
# Setup Tabs Widget
# self.treeview = QtGui.QTreeView()
self.treeview = QtGui.QTreeView()
self.treeview.setHeaderHidden(True)
self.treeview.setUniformRowHeights(True)
self.treeview.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.model = QtGui.QStandardItemModel()
self.treeview.setModel(self.model)
self.action = QtGui.QAction('Print', self)
self.action.setShortcut('F5')
self.action.triggered.connect(self.get_checked)
fileMenu = QtGui.QMenu("&File", self)
fileMenu.addAction(self.action)
self.menuBar().addMenu(fileMenu)
# Setup central widget
self.setCentralWidget(self.treeview)
# populate data
self.populate_people()
self.treeview.expandAll()
def populate_people(self):
parent = Person("Kevin", [
Person("Tom", [Person("Sally"), Person("Susan")]),
Person("Snappy", [Person("John"), Person("Kimmy"),
Person("Joe")]),
Person("Chester", [Person("Danny"), Person("Colleen")])
]
)
self.create_nodes(parent, self.model)
def create_nodes(self, node, parent):
tnode = QtGui.QStandardItem()
tnode.setCheckable(True)
tnode.setData(QtCore.Qt.Unchecked, role=QtCore.Qt.CheckStateRole)
tnode.setData(node.name , role=QtCore.Qt.DisplayRole)
tnode.setData(node, role=QtCore.Qt.UserRole) # store object on item
parent.appendRow(tnode)
for x in node.children:
self.create_nodes(x, tnode)
def get_checked(self):
print "collecting..."
def main():
app = QtGui.QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
It can be done with the model's match method:
def get_checked(self):
model = self.treeview.model()
checked = model.match(
model.index(0, 0), QtCore.Qt.CheckStateRole,
QtCore.Qt.Checked, -1,
QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
for index in checked:
item = model.itemFromIndex(index)
print(item.text())
To keep the GUI widgets number to minimum I need to find a way to give to user a choice of pull-down menu items that could be used to filter out the displayed in a listWidget items.
Let's say the listWidget lists 5 different categories of Items: "Cat A", "Cat B","Cat C","Cat D","Cat E". I could implement the radio or checkboxes for each item category. But then 5 radio buttons or checkboxes would take a lot of GUI space. A combobox with the checkable items seems to be a right choice. Any ideas?
from PyQt4 import QtGui, QtCore
import sys, os
class CheckableComboBox(QtGui.QComboBox):
def __init__(self):
super(CheckableComboBox, self).__init__()
def flags(self, index):
return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
class Dialog_01(QtGui.QMainWindow):
def __init__(self):
super(QtGui.QMainWindow,self).__init__()
myQWidget = QtGui.QWidget()
myBoxLayout = QtGui.QVBoxLayout()
myQWidget.setLayout(myBoxLayout)
self.setCentralWidget(myQWidget)
self.ComboBox = CheckableComboBox()
for i in range(3):
self.ComboBox.addItem("Combobox Item " + str(i))
myBoxLayout.addWidget(self.ComboBox)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(480,320)
sys.exit(app.exec_())
This idea of a multi-select combo has come up before, but I'm not sure that its the best solution. Really, all that's needed is a tool-button with a drop-down menu (similar to the history buttons in a web-browser).
Here's a basic demo that illustrates both options (button left, combo right):
PyQt5:
from PyQt5 import QtWidgets, QtGui, QtCore
class CheckableComboBox(QtWidgets.QComboBox):
def __init__(self):
super(CheckableComboBox, self).__init__()
self.view().pressed.connect(self.handleItemPressed)
self.setModel(QtGui.QStandardItemModel(self))
def handleItemPressed(self, index):
item = self.model().itemFromIndex(index)
if item.checkState() == QtCore.Qt.Checked:
item.setCheckState(QtCore.Qt.Unchecked)
else:
item.setCheckState(QtCore.Qt.Checked)
class Dialog_01(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
myQWidget = QtWidgets.QWidget()
myBoxLayout = QtWidgets.QHBoxLayout()
myQWidget.setLayout(myBoxLayout)
self.setCentralWidget(myQWidget)
self.ComboBox = CheckableComboBox()
self.toolbutton = QtWidgets.QToolButton(self)
self.toolbutton.setText('Categories ')
self.toolmenu = QtWidgets.QMenu(self)
for i in range(3):
self.ComboBox.addItem('Category %s' % i)
item = self.ComboBox.model().item(i, 0)
item.setCheckState(QtCore.Qt.Unchecked)
action = self.toolmenu.addAction('Category %s' % i)
action.setCheckable(True)
self.toolbutton.setMenu(self.toolmenu)
self.toolbutton.setPopupMode(QtWidgets.QToolButton.InstantPopup)
myBoxLayout.addWidget(self.toolbutton)
myBoxLayout.addWidget(self.ComboBox)
if __name__ == '__main__':
app = QtWidgets.QApplication(['Test'])
dialog_1 = Dialog_01()
dialog_1.show()
app.exec_()
**PyQt4**:
from PyQt4 import QtGui, QtCore
class CheckableComboBox(QtGui.QComboBox):
def __init__(self):
super(CheckableComboBox, self).__init__()
self.view().pressed.connect(self.handleItemPressed)
self.setModel(QtGui.QStandardItemModel(self))
def handleItemPressed(self, index):
item = self.model().itemFromIndex(index)
if item.checkState() == QtCore.Qt.Checked:
item.setCheckState(QtCore.Qt.Unchecked)
else:
item.setCheckState(QtCore.Qt.Checked)
class Dialog_01(QtGui.QMainWindow):
def __init__(self):
super(QtGui.QMainWindow, self).__init__()
myQWidget = QtGui.QWidget()
myBoxLayout = QtGui.QHBoxLayout()
myQWidget.setLayout(myBoxLayout)
self.setCentralWidget(myQWidget)
self.ComboBox = CheckableComboBox()
self.toolbutton = QtGui.QToolButton(self)
self.toolbutton.setText('Categories ')
self.toolmenu = QtGui.QMenu(self)
self.toolbutton.setMenu(self.toolmenu)
self.toolbutton.setPopupMode(QtGui.QToolButton.InstantPopup)
for i in range(3):
self.ComboBox.addItem('Category %s' % i)
item = self.ComboBox.model().item(i, 0)
item.setCheckState(QtCore.Qt.Unchecked)
action = self.toolmenu.addAction('Category %s' % i)
action.setCheckable(True)
myBoxLayout.addWidget(self.toolbutton)
myBoxLayout.addWidget(self.ComboBox)
if __name__ == '__main__':
app = QtGui.QApplication(['Test'])
dialog_1 = Dialog_01()
dialog_1.show()
app.exec_()
It is very easy. Just set the item Checkable using the flags() function in the model associated with the comboBox.
def flags(self, index):
return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
UPDATE
This may not be the best method, But it should sort your problem. Here is a something u may want look at , IF you have space restrictionn and cannot display the complete listView, Just resize it until it looks like a ComboBox.
(Not an answere to the question, hence I used most of the code from here)
I added a function and changed the name to RadioComboBox if anyone else wants to have a class for a RadioComboBox.
from PyQt4 import QtCore
from PyQt4.QtGui import QComboBox, QStandardItemModel
class RadioComboBox(QComboBox):
def __init__(self):
super(RadioComboBox, self).__init__()
self.view().pressed.connect(self.handle_item_pressed)
self.setModel(QStandardItemModel(self))
def handle_item_pressed(self, index):
item = self.model().itemFromIndex(index)
target_row = item.index().row()
if item.checkState() != QtCore.Qt.Checked:
item.setCheckState(QtCore.Qt.Checked)
self.check_others(target_row)
def check_others(self, target_row):
for i in range(self.model().rowCount()):
if i == target_row:
continue
else:
item = self.model().item(i)
item.setCheckState(QtCore.Qt.Unchecked)