PyQt QTableWidget получает отредактированное поле

Я новичок в PyQt, и я создаю графический интерфейс в PyQt4 и Python 2.7, который (среди прочего) контролирует настройки нескольких микроконтроллеров. Чтобы легко заполнить и отобразить список настроек и указать, из какого контроллера они взяты, я поместил его в QTableWidget, где столбцы являются контроллерами, а строки - настройками (все контроллеры просто дублируют друг друга, хотя не все настройки будут быть одним и тем же значением от контроллера к контроллеру).

Проблема, с которой я столкнулся, заключается в том, что когда пользователь редактирует ячейку, я пытаюсь получить это новое значение с помощью

value = self.Settings1Table.item(n, s).text()

но при этом извлекается только значение, которое я поместил в ячейку во время заполнения, а не значение, которое было только что введено с клавиатуры. Я читал о методе currentText(), но насколько я понимаю, он требует, чтобы каждая ячейка была отдельным виджетом, и я не уверен, как это делается.

Весь код довольно большой, и я чувствовал, что нет необходимости публиковать его полностью, но если потребуется больше кода, я буду рад предоставить. Спасибо за помощь, надеюсь, она придет.

Изменить: вот метод, который выполняет итерацию по каждому элементу в таблице, он должен получить текущее значение, но сейчас возвращает только значение, которое я установил через item.setText (str) (должно быть значение, которое пользователь вводится с клавиатуры)

def ApplyAll1(self):
    if not self.CheckHealth():
        for s in xrange(NumOfSegs):
            n = 0
            for item in Settings1List:
                value = self.Settings1Table.item(n, s).text()
                print value
    else:
        self.MsgCntrField.setText("CONNECTION ERROR")

Self.CheckHealth () - это просто проверка ошибок


person Senofa    schedule 17.08.2014    source источник
comment
Итак, ваш вопрос: Как я получаю отредактированные данные для QTableWidget, когда пользователь редактирует данные, прикрепляя их к переменной. правильно ?   -  person Kitsune Meyoko    schedule 17.08.2014


Ответы (1)


ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ 19.08.2014 0:29

Меня действительно не волнует событие, поскольку я собираюсь перебрать всю таблицу, мне нужны данные, измененные с помощью клавиатуры, а не QtGui.QTableWidgetItem.setText, так что да

Хорошо, возможно создать событие, а затем только клавиатуру, но вы должны реализовать QtGui.QTableWidget.focusInEvent(self, eventQFocusEvent) и QtGui.QTableWidget.focusOutEvent(self, eventQFocusEvent). Итак, посмотрите любой пример кода, надеюсь, вам поможет;

import sys
from PyQt4 import QtGui, QtCore

class QCustomTableWidget (QtGui.QTableWidget):
    def __init__ (self, parent = None):
        super(QCustomTableWidget, self).__init__(parent)
        self.focusKeyboardOn = False
        # Setup row & column data
        listsVerticalHeaderItem = ['Device 1', 'Device 2', 'Device 3', 'Device 4', 'Device 5']
        self.setRowCount(len(listsVerticalHeaderItem))
        for index in range(self.rowCount()):
            self.setVerticalHeaderItem(index, QtGui.QTableWidgetItem(listsVerticalHeaderItem[index]))
        listsVerticalHeaderItem = ['Device 1', 'Device 2', 'Device 3', 'Device 4']
        self.setColumnCount(5)
        listsHorizontalHeaderItem = ['Option 1', 'Option 2']
        self.setColumnCount(len(listsHorizontalHeaderItem))
        for index in range(self.columnCount()):
            self.setHorizontalHeaderItem(index, QtGui.QTableWidgetItem(listsHorizontalHeaderItem[index]))

    def dataChanged (self, topLeftQModelIndex, bottomRightQModelIndex):
        row                  = topLeftQModelIndex.row()
        column               = topLeftQModelIndex.column()
        dataQTableWidgetItem = self.item(row, column)
        if (self.currentItem() == dataQTableWidgetItem) and (self.focusKeyboardOn == True):
            self.emit(QtCore.SIGNAL('currentKeyboardDataChanged'), row, column, dataQTableWidgetItem)
        self.emit(QtCore.SIGNAL('dataChanged'), row, column, dataQTableWidgetItem)
        QtGui.QTableWidget.dataChanged(self, topLeftQModelIndex, bottomRightQModelIndex)

    def focusInEvent (self, eventQFocusEvent):
        self.focusKeyboardOn = False
        QtGui.QTableWidget.focusInEvent(self, eventQFocusEvent)

    def focusOutEvent (self, eventQFocusEvent):
        self.focusKeyboardOn = True
        QtGui.QTableWidget.focusOutEvent(self, eventQFocusEvent)

class QCustomWidget (QtGui.QWidget):
    def __init__(self, parent = None):
        super(QCustomWidget, self).__init__(parent)
        self.myQCustomTableWidget = QCustomTableWidget(self)
        self.myQLabel = QtGui.QLabel('Track edited data', self)
        myQVBoxLayout = QtGui.QVBoxLayout()
        myQVBoxLayout.addWidget(self.myQLabel)
        myQVBoxLayout.addWidget(self.myQCustomTableWidget)
        self.setLayout(myQVBoxLayout)
        self.connect(self.myQCustomTableWidget, QtCore.SIGNAL('currentKeyboardDataChanged'), self.setTrackData)
        self.myQCustomTableWidget.setItem(0, 0, QtGui.QTableWidgetItem('Test'))
        self.myQCustomTableWidget.setItem(1, 1, QtGui.QTableWidgetItem('Work'))

    def setTrackData (self, row, column, dataQTableWidgetItem):
        self.myQLabel.setText('Last updated\nRow : %d, Column : %d, Data : %s' % (row + 1, column + 1, str(dataQTableWidgetItem.text())))

if __name__ == '__main__':
    myQApplication = QtGui.QApplication(sys.argv)
    myQCustomWidget = QCustomWidget()
    myQCustomWidget.show()
    sys.exit(myQApplication.exec_())

ПРИМЕЧАНИЕ. У него есть 1 кодирование, чтобы иметь ОШИБКУ: если ваш установлен QtGui.QTableWidgetItem.setText при активном редактировании с клавиатуры. Но если у вас строгие правила, я предлагаю создать свой собственный виджет и настроить делегирование элемента по своему усмотрению. (Но, очень хардкорно ...)


Я не знаю, что это за данные в вашей ячейке, что это такое. (Это другой кастом QWidget или просто нормальные данные QTableWidgetItem)

В любом случае, когда пользователь редактирует ячейку, вы пытаетесь получить это новое значение с помощью этого метода QAbstractItemView.dataChanged (self, QModelIndex topLeft, QModelIndex bottomRight). Этот метод возвращает позицию данных, которые были отредактированы, и вы получаете данные из индекса с помощью QTableWidgetItem QTableWidget.item (self, int row, int column). (Это то, о чем вы говорите, вопрос) Но эта работа закрыта только при редактировании (не во время редактирования).

Пример;

import sys
from PyQt4 import QtGui, QtCore

class QCustomTableWidget (QtGui.QTableWidget):
    def __init__ (self, parent = None):
        super(QCustomTableWidget, self).__init__(parent)
        # Setup row & column data
        listsVerticalHeaderItem = ['Device 1', 'Device 2', 'Device 3', 'Device 4', 'Device 5']
        self.setRowCount(len(listsVerticalHeaderItem))
        for index in range(self.rowCount()):
            self.setVerticalHeaderItem(index, QtGui.QTableWidgetItem(listsVerticalHeaderItem[index]))
        listsVerticalHeaderItem = ['Device 1', 'Device 2', 'Device 3', 'Device 4']
        self.setColumnCount(5)
        listsHorizontalHeaderItem = ['Option 1', 'Option 2']
        self.setColumnCount(len(listsHorizontalHeaderItem))
        for index in range(self.columnCount()):
            self.setHorizontalHeaderItem(index, QtGui.QTableWidgetItem(listsHorizontalHeaderItem[index]))

    def dataChanged (self, topLeftQModelIndex, bottomRightQModelIndex):
        row                  = topLeftQModelIndex.row()
        column               = topLeftQModelIndex.column()
        dataQTableWidgetItem = self.item(row, column)
        print '###### Data Changed  ######'
        print 'row    :', row + 1
        print 'column :', column + 1
        print 'data   :', dataQTableWidgetItem.text()
        self.emit(QtCore.SIGNAL('dataChanged'), row, column, dataQTableWidgetItem)
        QtGui.QTableWidget.dataChanged(self, topLeftQModelIndex, bottomRightQModelIndex)

class QCustomWidget (QtGui.QWidget):
    def __init__(self, parent = None):
        super(QCustomWidget, self).__init__(parent)
        self.myQCustomTableWidget = QCustomTableWidget(self)
        self.myQLabel = QtGui.QLabel('Track edited data', self)
        myQVBoxLayout = QtGui.QVBoxLayout()
        myQVBoxLayout.addWidget(self.myQLabel)
        myQVBoxLayout.addWidget(self.myQCustomTableWidget)
        self.setLayout(myQVBoxLayout)
        self.connect(self.myQCustomTableWidget, QtCore.SIGNAL('dataChanged'), self.setTrackData)

    def setTrackData (self, row, column, dataQTableWidgetItem):
        self.myQLabel.setText('Last updated\nRow : %d, Column : %d, Data : %s' % (row + 1, column + 1, str(dataQTableWidgetItem.text())))

if __name__ == '__main__':
    myQApplication = QtGui.QApplication(sys.argv)
    myQCustomWidget = QCustomWidget()
    myQCustomWidget.show()
    sys.exit(myQApplication.exec_())

QAbstractItemView.dataChanged (self, QModelIndex topLeft, QModelIndex bottomRight) Ссылка: http://pyqt.sourceforge.net/Docs/PyQt4/qabstractitemview.html#dataChanged


С уважением,

person Kitsune Meyoko    schedule 17.08.2014
comment
Благодарю за ваш ответ. Мне сложно понять, как этот код узнает, когда поле было отредактировано. Я не вижу никаких сигналов для cellChanged или какого-либо способа для программы узнать, что фокус был изменен. Где на самом деле происходит это изменение? Мой код проходит через все ячейки, поэтому знать, какая из них была изменена, не очень важно, просто чтобы измененные данные могли быть вызваны (я предполагаю, что с помощью item.text ()) я добавляю в OP свой код применения, который принимает все предположительно текущие значения (но на самом деле не текущие, отсюда и моя проблема) - person Senofa; 18.08.2014
comment
Кроме того, чтобы ответить на ваш первый вопрос, я имею в виду данные QTableWidgetItem - person Senofa; 18.08.2014
comment
Я очень запутался (извините). Моя программа (этот код ответа) показывает, как получить индекс (строку и столбец) и данные, когда поле было отредактировано (так, во время редактирования ничего не делать). Этот код известен как автоматический, если данные были изменены, и вы можете их изменить или проиндексировать. Вы говорите, что я не вижу никаких сигналов для cellChanged или какого-либо способа для программы узнать, что фокус был изменен. Это не сигнал, это просто событие, когда данные были отредактированы. - person Kitsune Meyoko; 18.08.2014
comment
Или вы хотите отслеживать событие, а затем вводить данные только с клавиатуры, а не QtGui.QTableWidgetItem.setText, верно? - person Kitsune Meyoko; 18.08.2014
comment
Меня действительно не волнует событие, так как я собираюсь перебрать всю таблицу, мне нужны данные, измененные с клавиатуры, а не QtGui.QTableWidgetItem.setText, так что да - person Senofa; 18.08.2014
comment
Я также должен упомянуть, что я запустил ваш код, и он делает то, что я хочу, но мне не удалось успешно интегрировать его в свою программу. - person Senofa; 18.08.2014