Данные в виде таблицы, но не QTableWidget
Необходимо что-то похожее на такую структуру:
Особенности:
- Текст в первой ячейке с левого края и по центру, в остальных - по центру.
- При изменении размеров таблицы изменяется длина и высота ячеек.
- Высота ячейки подгоняется под её содержимое, как в ответе на мой предыдущий вопрос Динамическое изменение размера QTextEdit
Сразу же отбросил мысль о использовании QTableWidget, т.к. ячейки статичны. Решил использовать измененный QPlainTextEdit из предыдущего вопроса + QGridLayout, но столкнулся с проблемой - из-за разного количества данных в ячейках, высоты у них тоже разные:
Хотел передавать ячейкам высоту самой большой, но другая проблема - текст в ячейках располагается не по центру, а сверху и изменить этого нельзя, т.к. QPlainTextEdit не знает что такое высота, а следовательно, где центр в вертикальной плоскости.
Тогда решил схитрить и поместил QPlainTextEdit в QFrame + QGridLayout и залил фон у QFrame:
from PyQt5 import QtCore, QtGui, QtWidgets
class PlainTextEdit(QtWidgets.QPlainTextEdit):
def __init__(self, parent=None):
super(PlainTextEdit, self).__init__(parent)
def text_to_center(self):
self.updateRequest.connect(lambda: self.handle_updateRequest(self))
def handle_updateRequest(self, a):
doc = a.document()
tb = doc.findBlockByNumber(doc.blockCount() - 1)
h = a.blockBoundingGeometry(tb).bottom() + 2 * doc.documentMargin()
a.setFixedHeight(h)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.grid = QtWidgets.QGridLayout(self.centralwidget)
self.centralwidget.setStyleSheet("QFrame{background-color: rgb(255, 255, 255);}")
self.frame1 = QtWidgets.QFrame()
self.frame1.setFrameShape(QtWidgets.QFrame.Box)
self.frame1.setMaximumHeight(65)
self.vlay1 = QtWidgets.QVBoxLayout(self.frame1)
self.textEdit1 = PlainTextEdit(self.frame1)
self.textEdit1.setFrameShape(QtWidgets.QFrame.NoFrame)
self.textEdit1.setPlainText('GoGOGO GoGOGO GoGOGO')
self.textEdit1.text_to_center()
self.vlay1.addWidget(self.textEdit1)
self.grid.addWidget(self.frame1, 0, 0, 1, 1)
self.frame2 = QtWidgets.QFrame()
self.frame2.setFrameShape(QtWidgets.QFrame.Box)
self.frame2.setMaximumHeight(65)
self.vlay2 = QtWidgets.QVBoxLayout(self.frame2)
self.textEdit2 = PlainTextEdit(self.frame2)
self.textEdit2.setFrameShape(QtWidgets.QFrame.NoFrame)
self.textEdit2.setPlainText('GoGOGO GoGOGO')
self.textEdit2.text_to_center()
self.vlay2.addWidget(self.textEdit2)
self.grid.addWidget(self.frame2, 0, 1, 1, 1)
self.frame3 = QtWidgets.QFrame()
self.frame3.setFrameShape(QtWidgets.QFrame.Box)
self.frame3.setMaximumHeight(65)
self.vlay3 = QtWidgets.QVBoxLayout(self.frame3)
self.textEdit3 = PlainTextEdit(self.frame3)
self.textEdit3.setFrameShape(QtWidgets.QFrame.NoFrame)
self.textEdit3.setPlainText('GoGOGO')
self.textEdit3.text_to_center()
self.vlay3.addWidget(self.textEdit3)
self.grid.addWidget(self.frame3, 0, 2, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
И результат-то меня устраивает. Ячейки ведут себя так, как надо, но... Костыль же + в 2 раза больше объектов.
Вопросы:
- Можно ли всё таки изменить
QTableWidgetтак, чтобы появилось необходимое поведение? - Есть ли более элегантное решение на основе
QPlainTextEdit?
Ответы (1 шт):
А если так:
from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, QHeaderView
from PyQt5.QtCore import Qt
class MainWindow(QTableWidget):
def __init__(self):
super().__init__()
items = [
['Поле 1:\n' * 3, '123\n' * 2, 'abc ' * 10],
['Поле 2:\n' * 3, '456\n' * 2, 'def ' * 10],
]
self.setRowCount(len(items))
self.setColumnCount(len(items[0]))
for col in range(self.columnCount()):
self.horizontalHeader().setSectionResizeMode(col, QHeaderView.Stretch)
for row in range(self.rowCount()):
item = QTableWidgetItem(items[row][0])
self.setItem(row, 0, item)
item = QTableWidgetItem(items[row][1])
item.setTextAlignment(Qt.AlignCenter)
self.setItem(row, 1, item)
item = QTableWidgetItem(items[row][2])
item.setTextAlignment(Qt.AlignCenter)
self.setItem(row, 2, item)
self.resizeRowsToContents()
if __name__ == '__main__':
app = QApplication([])
mw = MainWindow()
mw.show()
app.exec()
Скриншот:



