Данные QTreeView изменили реализацию сигнала / слота? - PullRequest
1 голос
/ 14 июня 2019

Я использую 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). Если вы щелкнете по строке, вы сразу же перейдете в режим редактирования в столбце «Значение». Однако я не могу определить, как узнать, когда проверять, изменилось ли поле (я фиксирую значения перед редактированием). Таким образом, «потерянный фокус» был бы достаточен, но «измененные данные» были бы лучше.

1 Ответ

2 голосов
/ 14 июня 2019

Если вы хотите получить текст элемента, если он был только изменен, вы должны использовать сигнал dataChanged(...)

# ...
class ItemDsplyr(QTreeView):
    def __init__(self, CentrPane):
        QTreeView.__init__(self, CentrPane)
        # ...
        self.model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self.model.dataChanged.connect(self.on_data_changed)
        # ...

    @pyqtSlot("QModelIndex", "QModelIndex", "QVector<int>")
    def on_data_changed(self, top_left, bottom_right, roles):
        if top_left == bottom_right and Qt.DisplayRole in roles:
            print(top_left.data())
# ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...