#python #pyqt #pyqt5 #qtablewidget #qtablewidgetitem
#python #pyqt #pyqt5 #qtablewidget #qtablewidgetitem
Вопрос:
Я пытаюсь создать систему бронирования номеров, используя таблицу. В таблице у меня есть флажки, я бы хотел, чтобы, когда пользователь нажимает кнопку book, программа видела, какие флажки были установлены, чтобы она могла удалить эти флажки из таблицы.
Я создал таблицу с помощью PyQt5 designer, с флажками в каждом пространстве таблицы, подобными этому:
Код файла пользовательского интерфейса содержит много строк, подобных этой:
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)
self.tableWidget.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)
self.tableWidget.setItem(0, 1, item)
Означает ли это, что все флажки называются item? есть ли способ, с помощью которого я могу задать отдельное имя для каждого флажка?
Извините, если это кажется простым вопросом — заранее спасибо
Комментарии:
1. как называется флажок?
2. Я не уверен, как я уже сказал, я разработал его в PyQt designer, поэтому я использовал QTableWidget, дважды щелкнул по нему, перешел к элементам, свойствам, затем в разделе флаги я установил флажок user Checkable.
3. Нет, я думаю, вы меня не поняли, вы хотите определить флажок, поэтому мне интересно, какие данные вы хотите получить из элемента, в моем ответе я предложил напечатать метку строки и столбца
Ответ №1:
Вы должны выполнить итерацию по таблице и выполнить проверку состояния каждого элемента, используя отфильтрованные элементы, вы можете получить строку и столбец с какими вы можете получить метками.
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.tableWidget = QtWidgets.QTableWidget(6, 5)
self.book_button = QtWidgets.QPushButton("Book")
self.book_button.clicked.connect(self.book_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.tableWidget)
lay.addWidget(self.book_button)
self.tableWidget.setHorizontalHeaderLabels("P1 P2 P3 P4 P5 P6".split())
self.tableWidget.setVerticalHeaderLabels("C101 C214 C320 F04 E201".split())
for i in range(self.tableWidget.rowCount()):
for j in range(self.tableWidget.columnCount()):
item = QtWidgets.QTableWidgetItem()
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setCheckState(QtCore.Qt.Unchecked)
self.tableWidget.setItem(i, j, item)
@QtCore.pyqtSlot()
def book_clicked(self):
items = []
for i in range(self.tableWidget.rowCount()):
for j in range(self.tableWidget.columnCount()):
item = self.tableWidget.item(i, j)
if item.checkState() == QtCore.Qt.Checked:
items.append(item)
for it in items:
r = it.row()
c = it.column()
v, h = self.tableWidget.horizontalHeaderItem(c).text(), self.tableWidget.verticalHeaderItem(r).text()
print(h, v)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Комментарии:
1. Как я могу сделать так, чтобы вместо печати (h, v) они добавлялись в один массив или список, чтобы затем печататься как одно целое.
2. Также, как бы мне снять флажок после этого
Ответ №2:
Просто немного измените приведенный выше код!
1) в конструкторе объявите пустое значение списка.
self._checked_items = []
2) внутри метода ‘book_clicked’ добавьте строку:
self._checked_items.append([h, v])
3) объявите средство получения checked_items:
def checked_items(self):
return self._checked_items
4) выведите checked_items в методе main:
print(w.checked_items())
Но я предлагаю вам использовать QTableView () , а не QTableWidget().
QTableWidget () основан на элементах, QTableView () — на модели.
Конечно, на первый взгляд это кажется более сложным, но позже, когда вы поймете, как использовать виджеты на основе моделей, вам это понравится!
Что вам нужно сделать, так это реализовать пользовательскую CheckedItemsModel , которая расширяет QAbstractItemModel . Посмотрите на документацию, вы найдете много примеров.
Ответ №3:
Я сделал это за вас, вам повезло)))
Главное окно.
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QHeaderView
from examples.checkedItemsModel import CheckedItemsModel
from examples.checkedItemsUI import Ui_CheckedItemsView
class CheckedItems(QtWidgets.QMainWindow):
def __init__(self, model= None, parent = None):
super(CheckedItems, self).__init__(parent)
self._ui = Ui_CheckedItemsView()
self._ui.setupUi(self)
self._model = model
self._ui.ui_table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self._ui.ui_table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
# set the table model
self._ui.ui_table_view.setModel(self._model)
# create connecitons
self._ui.btn_book.clicked.connect(self.print_checked_items)
def print_checked_items(self):
model = self._ui.ui_table_view.model()
items = model.checkedItems()
self._ui.ui_result.setPlainText(str(items))
print(items)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
# data for table creation
column_headers = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6']
row_headers = ['C101', 'C214', 'C320', 'F04', 'E201']
# create table model
model = CheckedItemsModel(column_headers, row_headers)
# pass model to custom widget
w = CheckedItems(model)
w.show()
sys.exit(app.exec_())
Реализация модели:
import typing
from PyQt5 import QtCore
from PyQt5.QtCore import QAbstractTableModel, Qt, QModelIndex
class CheckedItemsModel(QAbstractTableModel):
def __init__(self, column_headers= [], row_headers=[], parent = None):
super(CheckedItemsModel, self).__init__(parent)
self._column_headers = column_headers
self._row_headers = row_headers
# create all unchecked items by default
self._items = []
for i in range(len(self._row_headers)):
self._items.append([])
for j in range(len(self._column_headers)):
self._items[i].append(Qt.Unchecked)
def rowCount(self, parent: QModelIndex = QtCore.QModelIndex()) -> int:
return len(self._row_headers)
def columnCount(self, parent: QModelIndex = ...) -> int:
return len(self._column_headers)
def data(self, index: QModelIndex, role: int = QtCore.Qt.DisplayRole) -> typing.Any:
if role == QtCore.Qt.DisplayRole:
return ''#str(index.row()) ', ' str(index.column())
if role == QtCore.Qt.CheckStateRole:
if self._items[index.row()][index.column()] == Qt.Checked:
return QtCore.Qt.Checked
else:
return QtCore.Qt.Unchecked
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
if role == QtCore.Qt.DisplayRole:
if orientation == Qt.Horizontal:
return self._column_headers[section]
else:
return self._row_headers[section]
def setData(self, index: QModelIndex, value: typing.Any, role: int = QtCore.Qt.EditRole) -> bool:
if role == Qt.EditRole:
self._items[index.row()][index.column()] = value
self.dataChanged.emit(index, index)
return True
if role == Qt.CheckStateRole:
self._items[index.row()][index.column()] = value
self.dataChanged.emit(index, index)
return True
def flags(self, index: QModelIndex):
return Qt.ItemIsUserCheckable | Qt.ItemIsEnabled
def checkedItems(self):
items = []
for i in range(self.rowCount()):
for j in range(self.columnCount()):
if self._items[i][j] == QtCore.Qt.Checked:
items.append('(' str(self._row_headers[i]) ', ' str(self._column_headers[j]) ')')
return items
И класс View (автоматически преобразованный файл .ui в .py) из Qt Designer:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui_CheckedItems.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_CheckedItemsView(object):
def setupUi(self, CheckedItemsView):
CheckedItemsView.setObjectName("CheckedItemsView")
CheckedItemsView.resize(685, 470)
self.centralwidget = QtWidgets.QWidget(CheckedItemsView)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.ui_table_view = QtWidgets.QTableView(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.ui_table_view.sizePolicy().hasHeightForWidth())
self.ui_table_view.setSizePolicy(sizePolicy)
self.ui_table_view.setMinimumSize(QtCore.QSize(200, 200))
self.ui_table_view.setObjectName("ui_table_view")
self.verticalLayout.addWidget(self.ui_table_view)
self.ui_result = QtWidgets.QTextEdit(self.centralwidget)
self.ui_result.setReadOnly(True)
self.ui_result.setObjectName("ui_result")
self.verticalLayout.addWidget(self.ui_result)
self.buttonsLayout = QtWidgets.QHBoxLayout()
self.buttonsLayout.setObjectName("buttonsLayout")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.buttonsLayout.addItem(spacerItem)
self.btn_book = QtWidgets.QPushButton(self.centralwidget)
self.btn_book.setObjectName("btn_book")
self.buttonsLayout.addWidget(self.btn_book)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.buttonsLayout.addItem(spacerItem1)
self.verticalLayout.addLayout(self.buttonsLayout)
self.verticalLayout.setStretch(0, 5)
self.verticalLayout.setStretch(1, 1)
self.horizontalLayout.addLayout(self.verticalLayout)
CheckedItemsView.setCentralWidget(self.centralwidget)
self.retranslateUi(CheckedItemsView)
QtCore.QMetaObject.connectSlotsByName(CheckedItemsView)
def retranslateUi(self, CheckedItemsView):
_translate = QtCore.QCoreApplication.translate
CheckedItemsView.setWindowTitle(_translate("CheckedItemsView", "MainWindow"))
self.btn_book.setText(_translate("CheckedItemsView", "Book"))