Ввод данных в QTableView
Пытаюсь сделать программу, куда можно будет записывать игроков, и их баллы. Желательно, что бы данные можно было записывать подряд, т.е. когда ввел одно имя, нужно ввести следующее и т.д. Также нужно что бы была возможность переписывания данных по определенной колонке и строке, т.е в определенной клетке.
Вопрос: как это здесь реализовать?
Ввод: Player 1 | 25 ; Player 2 | 18
Вывод:
| Player 1 | 25 |
| Player 2 | 18 |
Counter.py
import sys
from random import randint
from PyQt5 import QtWidgets, QtCore, QtGui
class CustomTableView(QtWidgets.QTableView):
def __init__(self, parent=None):
super(CustomTableView, self).__init__(parent)
self.setSortingEnabled(True)
def KeyPressEvent(self, event: QtGui.QKeyEvent):
if event.key() == QtCore.Qt.Key_Enter:
print("Key_Enter ")
elif event.key() == QtCore.Qt.Key_Return:
print("Key_Return ")
class NumberSortModel(QtCore.QSortFilterProxyModel):
def lessThan(self, left_index: "QModelIndex",
right_index: "QModelIndex") -> bool:
left_var: str = left_index.data(QtCore.Qt.EditRole)
right_var: str = right_index.data(QtCore.Qt.EditRole)
try:
return float(left_var) < float(right_var)
except (ValueError, TypeError):
pass
try:
return left_var < right_var
except TypeError:
return True
class Counter(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Counter, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window)
QtWidgets.QMainWindow.__init__(self)
font = QtGui.QFont("Formula1", 10, QtGui.QFont.Bold)
self.setFont(font)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
grid_layout = QtWidgets.QGridLayout()
central_widget.setLayout(grid_layout)
self.model = QtGui.QStandardItemModel(self)
self.model.setHorizontalHeaderLabels(["Name" , "Points"])
self.proxy = NumberSortModel()
self.proxy.setSourceModel(self.model)
self.table = CustomTableView(self)
self.table.setModel(self.proxy)
for i in range(10):
self.model.appendRow([QtGui.QStandardItem(f'Name{randint(10, 99)}'),
QtGui.QStandardItem(str(randint(1, 100)))])
sort_button = QtWidgets.QPushButton("Sort")
qlineedit_name = QtWidgets.QLineEdit()
qlineedit_name.resize(24, 80)
qlineedit_name.setText("Name")
qlineedit_name.selectAll()
qlineedit_points = QtWidgets.QLineEdit()
qlineedit_points.resize(24, 80)
qlineedit_points.setText("Points")
qlineedit_points.selectAll()
horisontal_layout = QtWidgets.QHBoxLayout()
horisontal_layout.addStretch(1)
horisontal_layout.addWidget(qlineedit_name)
horisontal_layout.addStretch(1)
horisontal_layout.addWidget(qlineedit_points)
horisontal_layout.addStretch(1)
horisontal_layout.addWidget(sort_button)
horisontal_layout.addStretch(1)
horisontal_layout.setAlignment(QtCore.Qt.AlignRight)
grid_layout.addLayout(horisontal_layout, 0, 0)
grid_layout.addWidget(self.table, 1, 0)
if __name__ == "__main__":
application = QtWidgets.QApplication([])
window = Counter()
window.setWindowTitle("Counter")
window.setMinimumSize(480, 380)
window.show()
sys.exit(application.exec_())
Ответы (2 шт):
Чтобы среагировать на нажатие кнопки ввода, у QLineEdit имеется такой сигнал returnPressed:
def __init__():
#...
# лучше добавить self.qlineedit_name, чтобы можно было обращать к объекту за данными
self.qlineedit_name = QtWidgets.QLineEdit()
self.qlineedit_name.returnPressed.connect(self._nameEntered)
def _nameEntered(self):
# получили данные из QLineEdit
name = self.qlineedit_name.text()
# Дальше решаем, что делать, либо изменить значение в столбце,
# выделенной строки, либо добавить новую строку, либо что-то еще
Предположим, что вам надо изменить значения только в первой (их может быть много) выделенной строке. Из таблицы получаем модель выбора, из нее выделенные строки (их индексы), при помощи которых обновляем данные в модели данных таблицы при помощи метода setData:
s_model = self.table->selectionModel();
rows = s_model.selectedRows(0) # 0 - это номер колонки
if len(rows) > 0:
self.model.setData(rows[0], name, Qt.DisplayRole)
Если таблица пустая, или выделенных строк нет, что подразумевает добавление новой строки, то делается это так:
if len(rows) > 0:
#...
else: # Таблица пустая, или нет выделенных строк
item1 = QStandartItem()
item1.setText(self.qlineedit_name.text())
item2 = QStandartItem()
item2.setText(self.qlineedit_points.text())
items = [item1, item2]
self.model.appendRow(items)
я добавил для вас метод on_update_button , которые сработает по нажатию кнопки Update
import sys
from random import randint
from PyQt5 import QtWidgets, QtCore, QtGui
class CustomTableView(QtWidgets.QTableView):
def __init__(self, parent=None):
super(CustomTableView, self).__init__(parent)
self.setSortingEnabled(True)
def KeyPressEvent(self, event: QtGui.QKeyEvent):
if event.key() == QtCore.Qt.Key_Enter:
print("Key_Enter ")
elif event.key() == QtCore.Qt.Key_Return:
print("Key_Return ")
class NumberSortModel(QtCore.QSortFilterProxyModel):
def lessThan(self, left_index: "QModelIndex",
right_index: "QModelIndex") -> bool:
left_var: str = left_index.data(QtCore.Qt.EditRole)
right_var: str = right_index.data(QtCore.Qt.EditRole)
try:
return float(left_var) < float(right_var)
except (ValueError, TypeError):
pass
try:
return left_var < right_var
except TypeError:
return True
class Counter(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Counter, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window)
QtWidgets.QMainWindow.__init__(self)
font = QtGui.QFont("Formula1", 10, QtGui.QFont.Bold)
self.setFont(font)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
grid_layout = QtWidgets.QGridLayout()
central_widget.setLayout(grid_layout)
self.model = QtGui.QStandardItemModel(self)
self.model.setHorizontalHeaderLabels(["Name" , "Points"])
self.proxy = NumberSortModel()
self.proxy.setSourceModel(self.model)
self.table = CustomTableView(self)
self.table.setModel(self.proxy)
for i in range(10):
self.model.appendRow([QtGui.QStandardItem(f'Name{randint(10, 99)}'),
QtGui.QStandardItem(str(randint(1, 100)))])
update_button = QtWidgets.QPushButton("Update") # +++
update_button.clicked.connect(self.on_update_button) # +++
sort_button = QtWidgets.QPushButton("Sort")
self.qlineedit_name = QtWidgets.QLineEdit()
self.qlineedit_name.resize(24, 80)
self.qlineedit_name.setText("Name")
self.qlineedit_name.selectAll()
self.qlineedit_points = QtWidgets.QLineEdit()
self.qlineedit_points.resize(24, 80)
self.qlineedit_points.setText("Points")
self.qlineedit_points.selectAll()
horisontal_layout = QtWidgets.QHBoxLayout()
# horisontal_layout.addStretch(1)
horisontal_layout.addWidget(self.qlineedit_name, stretch=1)
# horisontal_layout.addStretch(1)
horisontal_layout.addWidget(self.qlineedit_points, stretch=1)
horisontal_layout.addStretch(1)
horisontal_layout.addWidget(update_button) # +++
horisontal_layout.addWidget(sort_button)
# horisontal_layout.addStretch(1)
horisontal_layout.setAlignment(QtCore.Qt.AlignRight)
grid_layout.addLayout(horisontal_layout, 0, 0)
grid_layout.addWidget(self.table, 1, 0)
# ++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def on_update_button(self):
name = self.qlineedit_name.text().strip()
point = self.qlineedit_points.text().strip() if self.qlineedit_points.text().strip() else '0'
if not point.isdigit():
msg = QtWidgets.QMessageBox.information(self, 'ВНИМАНИЕ', 'Заполните правильно поле ввода Points!')
return
if not name:
msg = QtWidgets.QMessageBox.information(self, 'ВНИМАНИЕ', 'Заполните поле ввода Name!')
return
rows = self.table.model().rowCount()
add_record = True
for row in range(rows):
if name == self.proxy.data(self.proxy.index(row, 0)):
#print(name)
add_record = False
row_edit = row
break
if add_record: # add
if self.table.selectedIndexes():
#print(f' {self.table.selectedIndexes()[-1].row()}')
row = self.table.selectedIndexes()[-1].row()
# insertRow(int row, const QList<QStandardItem *> &items)
self.model.insertRow(row+1, [QtGui.QStandardItem(name),
QtGui.QStandardItem(point)])
else:
#print(f' ничего не выбрано, добавляем в конец ')
self.model.appendRow([QtGui.QStandardItem(name),
QtGui.QStandardItem(point)])
else: # update
self.model.setData(self.model.index(row_edit, 1), point, QtCore.Qt.EditRole)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if __name__ == "__main__":
application = QtWidgets.QApplication([])
window = Counter()
window.setWindowTitle("Counter")
window.setMinimumSize(480, 380)
window.show()
sys.exit(application.exec_())
