PyQt6 Add a widget with a layout to the scroll area, but it can't be scrolled

450 views Asked by At

I tried to add multiple widgets, which contain a vertical layout to split text and buttons and a horizontal layout to split buttons, into a scroll area.

In my expectation, all widgets should be one by one, and if there are too many widgets, the scroll area can be scrolled.

I use a container vertical layout to contain all the widgets I tried to put in the scroll area, and then I put the container layout into a container widget. After that, I set a widget in the scroll area with a container widget, but the results weren't what I expected; instead, all the widgets in the layout collapsed together, and I could barely see the words, and I couldn't scroll the area either.

import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QScrollArea, QSizePolicy, QLayout
from UI import comment  # Assuming you have saved the form in a file named comment_form.py

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("Scroll Area Example")
window.setGeometry(100, 100, 400, 400)

# Create a container widget and layout to hold the forms
container_widget = QWidget()
container_layout = QVBoxLayout()
container_layout.setSpacing(10)  # Adjust the spacing as needed

for i in range(5):
    # Create instances of the Ui_Form
    form = comment.Ui_Form()
    form_widget = QWidget()
    form.setupUi(form_widget)
    form.Comment_label.setWordWrap(True)  # Allow text to wrap to multiple lines
    form.Comment_label.setFixedWidth(300)
    form.Comment_label.setText("Test message in scroll area" * i)
    form_widget.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum)  # Set the size policy
    container_layout.addWidget(form_widget)

container_layout.setSizeConstraint(QLayout.SizeConstraint.SetMaximumSize)
container_widget.setLayout(container_layout)

# Create a scroll area and set the container widget as its content
scroll_area = QScrollArea()
scroll_area.setMinimumSize(350, 300)
scroll_area.setWidgetResizable(True)  # Allows the scroll area to resize its contents

scroll_area.setWidget(container_widget)

window_layout = QVBoxLayout()
window_layout.addWidget(scroll_area)
window.setLayout(window_layout)

window.show()
sys.exit(app.exec())
<?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>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="contextMenuPolicy">
   <enum>Qt::DefaultContextMenu</enum>
  </property>
  <property name="windowTitle">
   <string>Discuss</string>
  </property>
  <widget class="QWidget" name="verticalLayoutWidget">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>10</y>
     <width>354</width>
     <height>81</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <property name="sizeConstraint">
     <enum>QLayout::SetFixedSize</enum>
    </property>
    <item>
     <widget class="QLabel" name="Author_label">
      <property name="font">
       <font>
        <family>Arial</family>
        <weight>75</weight>
        <bold>true</bold>
       </font>
      </property>
      <property name="text">
       <string>TextLabel</string>
      </property>
      <property name="wordWrap">
       <bool>true</bool>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLabel" name="Comment_label">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="font">
       <font>
        <family>Arial</family>
       </font>
      </property>
      <property name="text">
       <string>TextLabel</string>
      </property>
      <property name="scaledContents">
       <bool>true</bool>
      </property>
      <property name="alignment">
       <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
      </property>
      <property name="wordWrap">
       <bool>true</bool>
      </property>
     </widget>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <property name="sizeConstraint">
       <enum>QLayout::SetFixedSize</enum>
      </property>
      <item>
       <widget class="QLabel" name="Floor_Time_label">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>100</width>
          <height>0</height>
         </size>
        </property>
        <property name="palette">
         <palette>
          <active>
           <colorrole role="WindowText">
            <brush brushstyle="SolidPattern">
             <color alpha="255">
              <red>90</red>
              <green>90</green>
              <blue>90</blue>
             </color>
            </brush>
           </colorrole>
          </active>
          <inactive>
           <colorrole role="WindowText">
            <brush brushstyle="SolidPattern">
             <color alpha="255">
              <red>90</red>
              <green>90</green>
              <blue>90</blue>
             </color>
            </brush>
           </colorrole>
          </inactive>
          <disabled>
           <colorrole role="WindowText">
            <brush brushstyle="SolidPattern">
             <color alpha="255">
              <red>120</red>
              <green>120</green>
              <blue>120</blue>
             </color>
            </brush>
           </colorrole>
          </disabled>
         </palette>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
         </font>
        </property>
        <property name="text">
         <string>B1, 3 days ago</string>
        </property>
        <property name="scaledContents">
         <bool>true</bool>
        </property>
        <property name="alignment">
         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
        </property>
        <property name="wordWrap">
         <bool>true</bool>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="Reply_pushButton">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>50</width>
          <height>0</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>50</width>
          <height>16777215</height>
         </size>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
         </font>
        </property>
        <property name="styleSheet">
         <string notr="true"/>
        </property>
        <property name="text">
         <string>Reply</string>
        </property>
        <property name="autoDefault">
         <bool>false</bool>
        </property>
        <property name="default">
         <bool>false</bool>
        </property>
        <property name="flat">
         <bool>true</bool>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="Delete_pushButton">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>50</width>
          <height>0</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>50</width>
          <height>16777215</height>
         </size>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
         </font>
        </property>
        <property name="styleSheet">
         <string notr="true"/>
        </property>
        <property name="text">
         <string>Delete</string>
        </property>
        <property name="autoDefault">
         <bool>false</bool>
        </property>
        <property name="default">
         <bool>false</bool>
        </property>
        <property name="flat">
         <bool>true</bool>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

comment widget Example of scroll area

1

There are 1 answers

1
抹茶抹茶 On

After some exploration on my own, I found this post which inspired me. Then, I add this line into the code, and it works!

form_widget.setMinimumHeight(65+form.Comment_label.sizeHint().height())

This code represent first label height + button height + comment label height, and can automatically fetch how high comment label is to adapt the widget since wordWrap is True.