I have recently started to use PyQt4 for making GUI applications. I was trying to make an application in which I used the QTableWidget. It's is 2-column table where the first column was set to QLineEdit and second column was set to QListWidget using delegates (sorry if "set to" is not the correct terminology"). The entries in the QListWidget column are coming from the list output of a QFileDialog
import sys
from PyQt4.QtGui import *
from PyQt4 import uic
from PyQt4.QtCore import *
qtCreatorFile = "app_name.ui" # UI File designed using QtDesigner
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class DelegateLEdit(QStyledItemDelegate):
def createEditor(self, parent, option, index):
line_edit = QLineEdit(parent)
return line_edit
class DelegateLWidget(QStyledItemDelegate):
def createEditor(self, parent, option, index):
list_widget = QListWidget(parent)
list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)
return list_widget
Everything seems to work fine except for one thing. Whenever I double click on any cell in the QListWidget column, the contents of that particular cell are set to -1. I have not handled the "doubleClicked" signal. Even when I did (I made it print the content of the cell on a textBrowser), double clicking the cell set the contents to -1. Can anyone please help me through this? I have tried reading the QTableWidget documentation but did not find any success. Can someone please point out what am I missing? Here is the init function of my Form class
def __init__(self):
QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.setWindowFlags(Qt.WindowMinimizeButtonHint)
self.list_widget = QListWidget()
self.add_button.clicked.connect(self.add_to_list)
# self.table.itemDoubleClicked.connect(self.print_cell_content)
self.table.setColumnCount(2)
first_header = "Option"
second_header = "Directories"
header = first_header + ";" + second_header
self.table.setHorizontalHeaderLabels(header.split(";"))
header = self.table.horizontalHeader()
header.setResizeMode(1, QHeaderView.ResizeToContents)
self.table.resizeColumnsToContents()
# self.table.setShowGrid(False)
self.delegate_lw = DelegateLWidget(self)
self.delegate_le = DelegateLEdit(self)
self.table.setItemDelegateForColumn(0, self.delegate_le)
self.table.setItemDelegateForColumn(1, self.delegate_lw)
EDIT: handler for add button that adds files to the second column of table
def add_to_list(self):
file_dialog = QFileDialog(self)
file_dialog.saveState()
file_dialog.setOption(QFileDialog.DontUseNativeDialog, True)
file_list = file_dialog.getOpenFileNames()
self.dir_list.extend(file_list)
self.dir_list = list(set(self.dir_list))
self.add_items(self.dir_list)
def add_items(self, list_items):
list_items.sort()
column = 1
self.row_count = 0
for item in list_items:
self.table.insertRow(self.row_count)
self.table.setItem(self.row_count, column, QTableWidgetItem(item))
self.row_count += 1
Thank You
You need to implement setEditorData and setModelData in your delegate, in order to be able to store and retrieve the model's data. For the list-widget column, the default behaviour is to display the current index, which will be -1
for an empty list.
Here is what your delegate classes should look like:
class DelegateLEdit(QStyledItemDelegate):
def createEditor(self, parent, option, index):
line_edit = QLineEdit(parent)
return line_edit
def setEditorData(self, editor, index):
editor.setText(index.data())
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
class DelegateLWidget(QStyledItemDelegate):
def createEditor(self, parent, option, index):
list_widget = QListWidget(parent)
list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)
list_widget.addItems('One Two Three Four'.split()) # or whatever
return list_widget
def setEditorData(self, editor, index):
for line in index.data().splitlines():
for item in editor.findItems(line, Qt.MatchExactly):
item.setSelected(True)
def setModelData(self, editor, model, index):
text = '\n'.join(item.text() for item in editor.selectedItems())
model.setData(index, text)