QCheckBox и Excel таблица
Имеется динамическая exсel таблица, с изменяющимся количеством строк (наименование колонок изменить нельзя, скачивается с файла в таблицу QTableWidget). Необходимо для дальнейшей обработки определить, какие строки помечены CheckBox.
Трудности:
CheckBoxотображается в первой колонке с данными, хотелось бы что бы располагался до номера строки. Таких примеров не попадалось, возможно ли это?- Не пойму, как корректно определить, какие строки в таблице имеют статус
CheckBox: Trueпо кнопке (в момент установки/снятия CheckBox’а - работает), при условии, что кнопка и таблица находятся в разных классах. - Как можно установить и снять
CheckBoxвсех имеющихся строк галкой «Весь список» (без постоянного отслеживания манипуляции мыши). - В статусбаре элементы добавляются справа, а команда
statusBar().insertPermanentWidget(1, _ )– делает привязку в крайнюю левую позицию из имеющихся. Можно привязать элемент к левому краю рамки?
Пример таблицы: https://dropmefiles.com/YK7zT[2] Пример кода:
m3.py
import os, sys
import openpyxl
import pathlib
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (QTableWidget, QTableWidgetItem, QVBoxLayout,
QWidget, QGridLayout, QPushButton, QCheckBox, QApplication, )
# from forma import form_MainWindow # форма
# class Example(QMainWindow, form_MainWindow):
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
# self.setupUi(self)
self.initUI()
self.tabl = Tabl()
self.widget = QtWidgets.QWidget()
self.setCentralWidget(self.widget)
self.tabl.setupTab(self.widget)
self.gridLayout = QGridLayout(self.widget)
self.gridLayout.addWidget(self.tabl, 0, 0, 0, 0)
def initUI(self):
self.btn_che = QPushButton('Счет CheckBox')
self.btn_che.clicked.connect(self.excelCheck)
self.excelCheckBox = QCheckBox('Весь список')
self.excelCheckBox.stateChanged.connect(self.excelCheck)
self.excelCheckBox.setChecked(True)
self.statusBar().insertPermanentWidget(1, self.excelCheckBox)
self.statusBar().addPermanentWidget(self.btn_che)
@QtCore.pyqtSlot()
def excelCheck(self):
try:
# print(f'main.py > class Example > def excelCheck > выбраны строки c номерами {xx}')
items = []
for i in range(self.tabl.tableW.rowCount()):
for j in range(self.tabl.tableW.columnCount()):
item = self.tabl.tableW.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.tabl.tableW.horizontalHeaderItem(c).text(), self.tabl.tableW.verticalHeaderItem(r).text()
print(h, v)
except Exception as check:
print('ошибка! = ', check)
# ----------------------------------------------------------------------------#
class Tabl(QWidget, object): # Сбор таблицы из excel файла
def setupTab(self, parent=None):
QWidget.__init__(self, parent)
QtCore.QMetaObject.connectSlotsByName(parent)
self.tableW = QTableWidget(self)
self.setLayout(QVBoxLayout())
self.layout().addWidget(self.tableW)
file = pathlib.Path("testing.xlsx")
wb = openpyxl.load_workbook(os.path.join(os.getcwd(), file), read_only=True)
ws = wb.active
try: # закрыть (file .xlsx) после работы
headers = [item.value for item in ws[1] if item.value is not None]
data = ws.iter_rows(min_row=2, max_col=9, max_row=100)
self.tableW.setColumnCount(len(headers))
self.tableW.setHorizontalHeaderLabels(headers)
for x, rows in enumerate(data):
if rows[0].value is not None:
self.tableW.setRowCount(self.tableW.rowCount() + 1)
for y, cell in enumerate(rows):
val = cell.value
if val is not None:
item = QTableWidgetItem(str(val))
self.tableW.setItem(self.tableW.rowCount() - 1, y, item)
self.tableW.resizeColumnsToContents() # ширина столцов подогнать по ширине текста
for i in range(self.tableW.rowCount()):
ch = QtWidgets.QCheckBox(parent=self.tableW)
ch.setChecked(True)
ch.clicked.connect(self.stateCh)
self.tableW.setCellWidget(i, 0, ch)
print(f'main.py > class Tabl > строка {i+1} - ch.isChecked() =', ch.isChecked())
finally:
wb.close()
print(f'main.py > class Tabl > Файл {file} закрыт')
print()
return
def stateCh(self):
ch = self.sender()
ix = self.tableW.indexAt(ch.pos())
xx = ix.row() + 1
print(f'main.py > class Tabl > Строка {xx} статус {ch.isChecked()}')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.resize(350, 250)
ex.show()
sys.exit(app.exec())
Ответы (1 шт):
Пожалуйста, не задавайте много вопросов. Вопрос, который вы задаете, должен рассматривать ОДНУ проблему.
Я не смог прочитать ваш testing.xlsx, поэтому нарисовал свое.
Я попробовал ответить на ваш вопрос: "Необходимо для дальнейшей обработки определить, какие строки помечены CheckBox" и некоторые другие вопросы.
Если у вас есть другие проблемы - задайте НОВЫЙ вопрос.
import sys
import os
import openpyxl
import pathlib
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (QTableWidget, QTableWidgetItem,
QVBoxLayout, QWidget, QGridLayout, QPushButton, QCheckBox,
QApplication, QAbstractItemView)
class TableWidget(QTableWidget):
def edit(self, index, trigger, event):
# редактирование не разрешено только для первого столбца
if index.column() == 0:
trigger = self.NoEditTriggers
return super().edit(index, trigger, event)
# -----------------> vvvvvv ??? <-----------------------------
#class Tabl(QWidget, object):
class Tabl(QWidget):
def __init__(self, parent=None): # +++
super().__init__(parent) # +++
def setupTab(self): # ??? , parent=None):
# ??? QWidget.__init__(self, parent)
# ??? QtCore.QMetaObject.connectSlotsByName(parent)
# self.tableW = QTableWidget()
self.tableW = TableWidget() # +++
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.tableW)
file = pathlib.Path("testing.xlsx")
wb = openpyxl.load_workbook(os.path.join(os.getcwd(), file), read_only=True)
ws = wb.active
try: # закрыть (file .xlsx) после работы
headers = [item.value for item in ws[1] if item.value is not None]
data = ws.iter_rows(min_row=2, max_col=9, max_row=100)
self.tableW.setColumnCount(len(headers))
self.tableW.setHorizontalHeaderLabels(headers)
for x, rows in enumerate(data):
if rows[0].value is not None:
self.tableW.setRowCount(self.tableW.rowCount() + 1)
for y, cell in enumerate(rows):
val = cell.value
if val is not None:
item = QTableWidgetItem(str(val))
self.tableW.setItem(
self.tableW.rowCount() - 1, y, item)
self.tableW.resizeColumnsToContents()
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
for i in range(self.tableW.rowCount()):
ch = QtWidgets.QTableWidgetItem(str(i+1))
ch.setFlags(ch.flags() | QtCore.Qt.ItemIsUserCheckable)
ch.setCheckState(QtCore.Qt.Checked)
# ------------------------> vvvvvvv
self.tableW.setItem(i, 0, ch)
self.tableW.verticalHeader().setVisible(False)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
finally:
wb.close()
print(f'main.py > class Tabl > Файл {file} закрыт')
print()
return
class Example(QtWidgets.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.centralWidget = QtWidgets.QWidget()
self.setCentralWidget(self.centralWidget)
# self.initUI()
self.tabl = Tabl(self) # + self
self.tabl.setupTab() # - self.centralWidget
self.initUI() # +++
self.gridLayout = QGridLayout(self.centralWidget)
self.gridLayout.addWidget(self.tabl, 0, 0, 0, 0)
def initUI(self):
self.btn_che = QPushButton('Счет CheckBox')
self.btn_che.clicked.connect(self.excelCheck)
self.excelCheckBox = QCheckBox('Весь список')
self.excelCheckBox.stateChanged.connect(self.state_changed) # !!! state_changed
self.excelCheckBox.setChecked(True)
self.statusBar().insertPermanentWidget(1, self.excelCheckBox)
self.statusBar().addPermanentWidget(self.btn_che)
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def state_changed(self, state):
if state:
for r in range(self.tabl.tableW.rowCount()):
item = self.tabl.tableW.item(r, 0)
item.setCheckState(QtCore.Qt.Checked)
else:
for r in range(self.tabl.tableW.rowCount()):
item = self.tabl.tableW.item(r, 0)
item.setCheckState(QtCore.Qt.Unchecked)
@QtCore.pyqtSlot()
def excelCheck(self):
items = []
for r in range(self.tabl.tableW.rowCount()):
item = self.tabl.tableW.item(r, 0)
if item.checkState() == QtCore.Qt.Checked:
items.append(item)
for it in items:
r = it.row()
c = it.column()
v = self.tabl.tableW.horizontalHeaderItem(c).text()
h = it.text()
print(f'row={r} / Header = `{h}`; column={c} / Header = `{v}`')
print()
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.resize(350, 250)
ex.show()
sys.exit(app.exec())


