使用 itemdelegate 和来自列表小部件的信号时,如何保护 qtablewidget 中的单元格变化?
How to protect the cells changing in tablewidget when using itemdelegate and signal from liswidget?
我有代码可以开始在 tablewidget 中编辑单元格,然后双击列表小部件中的名称以将其添加到单元格中。但是当我在第二个单元格上这样做时,两个单元格都在改变。如何保护单元格不被改变,代码如下
from functools import partial
from PyQt4 import QtCore, QtGui
class StyledItemDelegate(QtGui.QStyledItemDelegate):
textChanged = QtCore.pyqtSignal(int, int, str)
#editingFinished = QtCore.pyqtSignal()
def createEditor(self, parent, option, index):
editor = super(StyledItemDelegate, self).createEditor(
parent, option, index
)
if isinstance(editor, QtGui.QLineEdit):
editor.textChanged.connect(
partial(self.textChanged.emit, index.row(), index.column())
)
#editor.editingFinished.connect(self.editingFinished)
return editor
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.table_widget = QtGui.QTableWidget(4, 4)
self.table_widget.setHorizontalHeaderLabels(("Name", "1", "2",
"3"))
delegate = StyledItemDelegate(self.table_widget)
delegate.textChanged.connect(self.filter)
#delegate.editingFinished.connect(self.clear_filter)
self.table_widget.setItemDelegate(delegate)
self.list_widget = QtGui.QListWidget()
hlay = QtGui.QHBoxLayout(self)
hlay.addWidget(self.table_widget)
hlay.addWidget(self.list_widget)
for letter1 in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for letter2 in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
text = letter1 + letter2
it = QtGui.QListWidgetItem(text)
self.list_widget.addItem(it)
@QtCore.pyqtSlot(int, int, str)
def filter(self, row, column, text):
print(row, column)
self.clear_filter()
for r in range(self.list_widget.count()):
it = self.list_widget.item(r)
# filter algorithm
is_showing = text in it.text()
# Hide the row if necessary
it.setHidden(not is_showing)
self.list_widget.itemDoubleClicked.connect(
lambda:self.nameselected(row,column))
@QtCore.pyqtSlot()
def clear_filter(self):
for r in range(self.list_widget.count()):
it = self.list_widget.item(r)
it.setHidden(False)
def nameselected(self,row,column):
name=self.list_widget.currentItem().text()
print(name,row,column)
#self.table_Widget.blockSignals(True)
self.table_widget.setItem(row,column,
QtGui.QTableWidgetItem(name))
#self.table_Widget.blockSignals(False)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
假设我在第一个单元格中输入了 'A',当我双击 listwidget 中的 'AA' 时,listwidget 具有所有以 'A' 开头的名称,第一个单元格具有文本 'AA'。当我在第二个单元格中键入 'B' 时,listwidget 具有所有以 'B' 开头的名称 当我双击 listwidget 中的 'BA' 时,第二个单元格应具有文本 'BA'。但是这里两个单元格都设置为'BA'。如何保护其他单元格不被更改。
问题出在每次应用新过滤器时您都连接到 self.nameselected
插槽。如果多次更改过滤器,您可以很容易地看到它:每当您双击列表视图中的项目时,它都会多次打印 nameselected
的插槽输出。
您可以使用 try
并在每次应用过滤器时断开 itemDoubleClicked 信号,但即使这样也不是一个好的解决方案(您可能需要来自该信号的一些其他连接)。
只需将 itemDoubleClicked 信号连接到 __init__
中的 nameselected
,然后像这样更改该函数:
def nameselected(self):
name=self.list_widget.currentItem().text()
tableIndex = self.table_widget.currentIndex()
self.table_widget.setItem(tableIndex(), tableIndex(),
QtGui.QTableWidgetItem(name))
如果你不想这样做(例如,如果用户错误地点击了 table 中的另一个项目,以避免错误的索引),只需保留对最后一个 "edited" 项目索引并在 nameselected 函数中使用它。
我有代码可以开始在 tablewidget 中编辑单元格,然后双击列表小部件中的名称以将其添加到单元格中。但是当我在第二个单元格上这样做时,两个单元格都在改变。如何保护单元格不被改变,代码如下
from functools import partial
from PyQt4 import QtCore, QtGui
class StyledItemDelegate(QtGui.QStyledItemDelegate):
textChanged = QtCore.pyqtSignal(int, int, str)
#editingFinished = QtCore.pyqtSignal()
def createEditor(self, parent, option, index):
editor = super(StyledItemDelegate, self).createEditor(
parent, option, index
)
if isinstance(editor, QtGui.QLineEdit):
editor.textChanged.connect(
partial(self.textChanged.emit, index.row(), index.column())
)
#editor.editingFinished.connect(self.editingFinished)
return editor
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.table_widget = QtGui.QTableWidget(4, 4)
self.table_widget.setHorizontalHeaderLabels(("Name", "1", "2",
"3"))
delegate = StyledItemDelegate(self.table_widget)
delegate.textChanged.connect(self.filter)
#delegate.editingFinished.connect(self.clear_filter)
self.table_widget.setItemDelegate(delegate)
self.list_widget = QtGui.QListWidget()
hlay = QtGui.QHBoxLayout(self)
hlay.addWidget(self.table_widget)
hlay.addWidget(self.list_widget)
for letter1 in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for letter2 in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
text = letter1 + letter2
it = QtGui.QListWidgetItem(text)
self.list_widget.addItem(it)
@QtCore.pyqtSlot(int, int, str)
def filter(self, row, column, text):
print(row, column)
self.clear_filter()
for r in range(self.list_widget.count()):
it = self.list_widget.item(r)
# filter algorithm
is_showing = text in it.text()
# Hide the row if necessary
it.setHidden(not is_showing)
self.list_widget.itemDoubleClicked.connect(
lambda:self.nameselected(row,column))
@QtCore.pyqtSlot()
def clear_filter(self):
for r in range(self.list_widget.count()):
it = self.list_widget.item(r)
it.setHidden(False)
def nameselected(self,row,column):
name=self.list_widget.currentItem().text()
print(name,row,column)
#self.table_Widget.blockSignals(True)
self.table_widget.setItem(row,column,
QtGui.QTableWidgetItem(name))
#self.table_Widget.blockSignals(False)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
假设我在第一个单元格中输入了 'A',当我双击 listwidget 中的 'AA' 时,listwidget 具有所有以 'A' 开头的名称,第一个单元格具有文本 'AA'。当我在第二个单元格中键入 'B' 时,listwidget 具有所有以 'B' 开头的名称 当我双击 listwidget 中的 'BA' 时,第二个单元格应具有文本 'BA'。但是这里两个单元格都设置为'BA'。如何保护其他单元格不被更改。
问题出在每次应用新过滤器时您都连接到 self.nameselected
插槽。如果多次更改过滤器,您可以很容易地看到它:每当您双击列表视图中的项目时,它都会多次打印 nameselected
的插槽输出。
您可以使用 try
并在每次应用过滤器时断开 itemDoubleClicked 信号,但即使这样也不是一个好的解决方案(您可能需要来自该信号的一些其他连接)。
只需将 itemDoubleClicked 信号连接到 __init__
中的 nameselected
,然后像这样更改该函数:
def nameselected(self):
name=self.list_widget.currentItem().text()
tableIndex = self.table_widget.currentIndex()
self.table_widget.setItem(tableIndex(), tableIndex(),
QtGui.QTableWidgetItem(name))
如果你不想这样做(例如,如果用户错误地点击了 table 中的另一个项目,以避免错误的索引),只需保留对最后一个 "edited" 项目索引并在 nameselected 函数中使用它。