Я использую pyqt5 / python 3.7 / win10, и у меня есть QTreeView, который имеет только один редактируемый столбец, который можно редактировать очень хорошо. Теперь мне нужно сообщить программе, что поле было изменено (или чтобы проверить, изменилось ли оно), когда нажата клавиша возврата или ввода, или поле теряет фокус из-за щелчка мышью где-либо еще.
Я включил простую программу, которая полностью отражает мою ситуацию на данный момент со всеми ее слоями, и мы выбрали один щелчок вместо двойного щелчка для выбора поля для редактирования.
Я потратил довольно много времени, пытаясь выяснить это, и, хотя я видел возможные ответы, я еще не нашел, чтобы один работал на меня. Я уверен, что это, вероятно, довольно просто, но у меня есть время на внедрение решения.
from sys import exit as sysExit
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class CustomItemModel(QStandardItemModel):
def headerData(self, section, orientation, role):
if role == Qt.ForegroundRole:
brush = QBrush()
brush.setColor(Qt.blue)
brush.setStyle(Qt.SolidPattern)
return brush
elif role == Qt.BackgroundRole:
brush = QBrush()
brush.setColor(Qt.yellow)
brush.setStyle(Qt.SolidPattern)
return brush
elif role == Qt.FontRole:
font = QFont()
font.setBold(True)
font.setPointSize(10)
return font
return super().headerData(section, orientation, role)
class ItemDsplyr(QTreeView):
def __init__(self, CentrPane):
QTreeView.__init__(self, CentrPane)
self.CntrPane = CentrPane
self.setEditTriggers(QTreeView().NoEditTriggers)
self.model = CustomItemModel(0, 4)
self.model.setHorizontalHeaderLabels(['', 'ItemName', 'Value', 'Units'])
self.model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
self.setModel(self.model)
self.setColumnWidth(0, 1) #Not sure what the minimum column width is but is greater than 1
self.setColumnHidden(0, True)
self.header().setSectionResizeMode(0, QHeaderView.Fixed)
self.header().setStretchLastSection(False)
self.header().setSectionResizeMode(1, QHeaderView.Stretch)
self.setColumnWidth(2, 75)
self.setColumnWidth(3, 100)
self.clicked.connect(self.__itemSingleClicked)
@property
def CntrPane(self):
return self.__parent
@CntrPane.setter
def CntrPane(self, value):
self.__parent = value
def SetContent(self, tmpItmList):
self.model.setRowCount(0)
for Item in tmpItmList:
blnkVal = QStandardItem('')
ItmNam = QStandardItem(Item['ItemName'])
ItmNam.setTextAlignment(Qt.AlignLeft)
ItmNam.isEditable = False
ItmVal = QStandardItem(Item['Value'])
ItmVal.setTextAlignment(Qt.AlignCenter)
ItmUnt = QStandardItem((Item['Units']))
ItmUnt.setTextAlignment(Qt.AlignLeft)
ItmUnt.isEditable = False
self.model.appendRow([blnkVal, ItmNam, ItmVal, ItmUnt])
def __itemSingleClicked(self, index):
Item = self.selectedIndexes()[0]
CurRow = index.row()
ItemIdx = index.sibling(CurRow, 1)
ValuIdx = index.sibling(CurRow, 2)
self.edit(ValuIdx)
ItemVal = Item.model().itemFromIndex(ItemIdx).text()
ValuVal = Item.model().itemFromIndex(ValuIdx).text()
self.CntrPane.CurItemValue(ItemVal, ValuVal)
class CenterPanel(QWidget):
def __init__(self, MainWin):
QWidget.__init__(self)
self.MainWin = MainWin
self.ListItm = ''
self.ListVal = ''
ItmList = [
{'ItemName':'Cal-Itm-1', 'Value':'54', 'Units':'Units'},
{'ItemName':'Cal-Itm-2', 'Value':'54', 'Units':'Units'},
{'ItemName':'Cal-Itm-1', 'Value':'10', 'Units':'Passes'},
{'ItemName':'Cal-Itm-2', 'Value':'2.5', 'Units':'Volts'},
{'ItemName':'Run-Itm-1', 'Value':'2', 'Units':'Units'},
{'ItemName':'Run-Itm-2', 'Value':'1', 'Units':'Units'},
{'ItemName':'Run-Itm-1', 'Value':'10', 'Units':'Units'},
{'ItemName':'Run-Itm-2', 'Value':'50', 'Units':'Units'},
{'ItemName':'Tbl-Itm-1', 'Value':'0', 'Units':'Units'},
{'ItemName':'Tbl-Itm-2', 'Value':'0', 'Units':'Units'},
{'ItemName':'Tbl-Itm-1', 'Value':'0', 'Units':'Units'},
{'ItemName':'Tbl-Itm-2', 'Value':'255', 'Units':'Units'}
]
self.CatGrpTree = QTextEdit()
self.ItemDsply = ItemDsplyr(self)
self.ItemDsply.SetContent(ItmList)
CntrPane = QSplitter(Qt.Horizontal, self)
CntrPane.addWidget(self.CatGrpTree)
CntrPane.addWidget(self.ItemDsply)
CntrPane.setSizes([50,200])
hbox = QHBoxLayout(self)
hbox.addWidget(CntrPane)
self.setLayout(hbox)
@property
def MainWin(self):
return self.__parent
@MainWin.setter
def MainWin(self, value):
self.__parent = value
def CurItemValue(self, LstItm, LstVal):
print("List Item/Value Clicked:",LstItm,"/",LstVal)
if LstItm != self.ListItm:
self.ListItm = LstItm
self.ListVal = LstVal
class Window(QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.title = 'Main Window'
self.left = 100
self.ztop = 100
self.wide = 700
self.high = 600
self.InitGUI()
def InitGUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.ztop, self.wide, self.high)
self.CenterPane = CenterPanel(self)
self.setCentralWidget(self.CenterPane)
self.setStyle(QStyleFactory.create('Cleanlooks'))
if __name__ == "__main__":
MainApp = QApplication([])
# This fixes a display issue with Windows
MainApp.setStyle("fusion")
MainGUI = Window()
MainGUI.show()
sysExit(MainApp.exec_())
Как видно (после запуска этого) вы получаете QTreeView (в основном просто List, но из моих исследований лучше всего использовать QTreeView). Если вы щелкнете по строке, вы сразу же перейдете в режим редактирования в столбце «Значение». Однако я не могу определить, как узнать, когда проверять, изменилось ли поле (я фиксирую значения перед редактированием). Таким образом, «потерянный фокус» был бы достаточен, но «измененные данные» были бы лучше.