如何将 TextEdit 放入 QTableWidget - Pyqt5 的单元格中?

How to put a TextEdit inside a cell in QTableWidget - Pyqt5?

我设法使用以下代码将 TextEdit 放入我的 QTableWidget 的单元格中:

for i in range(10):
    rowCount = self.tableWidget_3.rowCount()
    self.tableWidget_3.insertRow(rowCount)

    combo = QTextEdit(self)
    self.tableWidget_3.setCellWidget(i, 0, combo)
    self.tableWidget_3.cellWidget(i, 0).setText(str(per_picture[i]))
    
    #Adjusting the TextEdit
    docHeight = self.tableWidget_3.cellWidget(i, 0).document().size().height()
    self.tableWidget_3.cellWidget(i, 0).setMinimumHeight(docHeight)

一切正常,直到我调整 TextEdit 的大小以匹配文本的大小。 2 文本编辑在调整大小时似乎重叠了,就像这个

.

如何解决这 2 个 TextEdit 重叠问题? 如何在 TableWidget 中调整 TextEdit 的大小?

这些是重现问题所需的文件:

MyApp.py:

from PyQt5.QtWidgets import QApplication, QWidget, QTextEdit
from PyQt5 import uic
from PyQt5 import QtWidgets
import sys

text = """In order to have a complete sentence, the sentence must 
        have a minimum of three word types: a subject, a verb, 
        and an object. In most cases, the subject is a noun or 
        a pronoun."""

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi("MyApp.ui", self)
        self.tableWidget_3.verticalHeader().setVisible(False)
        self.tableWidget_3.horizontalHeader().setVisible(False)
        self.tableWidget_3.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)

        for i in range(10):
            rowCount = self.tableWidget_3.rowCount()
            self.tableWidget_3.insertRow(rowCount)
            combo = QTextEdit(self)
            self.tableWidget_3.setCellWidget(i, 0, combo)
            self.tableWidget_3.cellWidget(i, 0).setText(text)
            #self.tableWidget_3.cellWidget(i, 0).adjustSize()
            docHeight = self.tableWidget_3.cellWidget(i, 0).document().size().height()
            self.tableWidget_3.cellWidget(i, 0).setMinimumHeight(int(docHeight))

app = QApplication(sys.argv)
myApp = MyApp()
myApp.show()
try:
    sys.exit(app.exec())
except:
    print('Closing Window')

MyApp.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>561</width>
    <height>421</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Editor</string>
  </property>
  <widget class="QWidget" name="verticalLayoutWidget_2">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>561</width>
     <height>421</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <property name="sizeConstraint">
     <enum>QLayout::SetNoConstraint</enum>
    </property>
    <item>
     <widget class="QTableWidget" name="tableWidget_3">
      <column>
       <property name="text">
        <string>New Column</string>
       </property>
      </column>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

问题是设置单元格小部件的最小尺寸 而不是 设置部分的最小尺寸。默认情况下,所有部分都有标准项目大小(使用默认字体和 system/style 配置计算),并且由于未考虑小部件的最小大小,结果是您只能看到编辑器的一部分.

由于您隐藏了垂直 header,我想您希望行自动调整大小,这可以通过正确实施编辑器的 sizeHint 来完成。然后,您可以在 table 上安装一个事件过滤器,以便它会自动尝试根据内容调整行的大小:

class TextEdit(QTextEdit):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.textChanged.connect(self.updateGeometry)

    def sizeHint(self):
        hint = super().sizeHint()
        if self.toPlainText():
            doc = self.document().clone()
            width = self.width() - self.frameWidth() * 2
            if self.verticalScrollBar().isVisible():
                width -= self.verticalScrollBar().width()
            doc.setTextWidth(width)
            height = round(doc.size().height())
        else:
            height = self.fontMetrics().height()
            height += self.document().documentMargin() * 2
        height += self.frameWidth() * 2
        hint.setHeight(height)
        return hint


class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi("MyApp.ui", self)
        self.tableWidget_3.verticalHeader().setVisible(False)
        self.tableWidget_3.horizontalHeader().setVisible(False)
        self.tableWidget_3.horizontalHeader().setSectionResizeMode(
            0, QtWidgets.QHeaderView.Stretch)

        for i in range(10):
            rowCount = self.tableWidget_3.rowCount()
            self.tableWidget_3.insertRow(rowCount)
            combo = TextEdit(self)
            self.tableWidget_3.setCellWidget(i, 0, combo)
            combo.setText(text)
            combo.textChanged.connect(
                lambda i=i: self.tableWidget_3.resizeRowToContents(i))
        self.tableWidget_3.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == event.Resize:
            QTimer.singleShot(0, self.tableWidget_3.resizeRowsToContents)
        return super().eventFilter(source, event)

注意:您没有在主 window 上正确设置布局:您只是添加了一个“浮动”布局,当 window 调整大小时该布局被完全忽略;将 table 移到它外面,删除该布局,右键单击 window 的空白区域,然后 select 从“布局”子菜单中选择垂直或水平布局。
此外,为了将来参考,如果您的示例只需要几个小部件,则不需要使用 Designer 文件:只需创建一个基本的 QWidget 子class,为其设置布局,并添加您需要使用的小部件;您的示例可以减少到 MyApp class 中的 3 行,而不需要 UI 文件:
layout = QVBoxLayout(self)
self.tableWidget = QTableWidget()
layout.addWidget(self.tableWidget)
这将使您的示例更简单,也将使我们的工作更容易,因为我们只需要 copy/paste 一个文件。