如何激活带有自定义元素的列表的 qListWidget 滚动条?

How to activate qListWidget scrollbar for list with custom elements?

我在使用小型桌面应用程序时遇到了一个问题:我想将 QCheckBox 实例添加到 QListWidget 中,但是当我这样做时,其中一些复选框的文本超出了 window.我试图在这些复选框中换行,但我遇到了另一个问题 - 文本相交。

所以,我决定使用滚动条,但如果我只是使用 setHorizo​​ntalScrollBar 它是行不通的,但据我所知,它行不通,因为我的项目是不同的小部件。 那么,是否可以让这个水平滚动条滚动带有复选框的列表?

我在 Python 3.8

中使用 PyQt

向 ListWidget 添加元素的 python 代码示例:

import sys
from PyQt5 import QtWidgets
from PyQt5 import uic
from PyQt5 import Qt


class Widget(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        uic.loadUi("updates_list.ui", self)
        self.centralwidget.setStyleSheet("QListWidget {background: rgba(255,255,255,200)}")

        manga = ['Smth very long, line with a text, more long line with a text, even more long, and even more more \
            more long etc.', 'more text', 'even more text']
        for i in range(len(manga)):
            widget_manga = manga[i]
            box = QtWidgets.QCheckBox(widget_manga)
            item = Qt.QListWidgetItem()
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, box)


app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())

updates_list.ui 文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>783</width>
    <height>776</height>
   </rect>
  </property>
  <property name="font">
   <font>
    <family>Ink Free</family>
   </font>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="autoFillBackground">
   <bool>false</bool>
  </property>
  <property name="styleSheet">
   <string notr="true">QPushButton{
    color: #fe6637;
    background: #2a2a5c;
    border-radius: 8px;
    border: 2px solid #fe6637;
}
QPushButton:hover{
    background: #5959a8;
}</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <property name="styleSheet">
    <string notr="true"/>
   </property>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>550</x>
      <y>40</y>
      <width>191</width>
      <height>41</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Fixedsys</family>
      <pointsize>12</pointsize>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true"/>
    </property>
    <property name="text">
     <string>Выбор сайта</string>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>190</x>
      <y>20</y>
      <width>231</width>
      <height>71</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Gabriola</family>
      <pointsize>26</pointsize>
      <weight>50</weight>
      <bold>false</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">
text-shadow: 2px 0 0 #fff, -2px 0 0 #fff, 0 2px 0 #fff, 0 -2px 0 #fff, 1px 1px #fff, -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff;
</string>
    </property>
    <property name="text">
     <string>ChapterSaver</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>10</y>
      <width>111</width>
      <height>101</height>
     </rect>
    </property>
    <property name="frameShadow">
     <enum>QFrame::Plain</enum>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="pixmap">
     <pixmap>pixel_logo.png</pixmap>
    </property>
   </widget>
   <widget class="QListWidget" name="listWidget">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>110</y>
      <width>701</width>
      <height>511</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Joystix</family>
      <pointsize>12</pointsize>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true"/>
    </property>
    <property name="verticalScrollBarPolicy">
     <enum>Qt::ScrollBarAlwaysOn</enum>
    </property>
    <property name="horizontalScrollBarPolicy">
     <enum>Qt::ScrollBarAlwaysOn</enum>
    </property>
    <property name="sizeAdjustPolicy">
     <enum>QAbstractScrollArea::AdjustToContents</enum>
    </property>
    <property name="autoScroll">
     <bool>false</bool>
    </property>
    <property name="dragDropOverwriteMode">
     <bool>false</bool>
    </property>
    <property name="dragDropMode">
     <enum>QAbstractItemView::NoDragDrop</enum>
    </property>
    <property name="selectionBehavior">
     <enum>QAbstractItemView::SelectItems</enum>
    </property>
    <property name="textElideMode">
     <enum>Qt::ElideLeft</enum>
    </property>
    <property name="horizontalScrollMode">
     <enum>QAbstractItemView::ScrollPerItem</enum>
    </property>
    <property name="viewMode">
     <enum>QListView::ListMode</enum>
    </property>
    <property name="modelColumn">
     <number>0</number>
    </property>
    <property name="currentRow">
     <number>-1</number>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_2">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>640</y>
      <width>121</width>
      <height>28</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Fixedsys</family>
     </font>
    </property>
    <property name="text">
     <string>Выбрать все</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_3">
    <property name="geometry">
     <rect>
      <x>650</x>
      <y>640</y>
      <width>93</width>
      <height>28</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Fixedsys</family>
     </font>
    </property>
    <property name="text">
     <string>Удалить</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_4">
    <property name="geometry">
     <rect>
      <x>260</x>
      <y>690</y>
      <width>251</width>
      <height>51</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Fixedsys</family>
      <pointsize>12</pointsize>
     </font>
    </property>
    <property name="text">
     <string>Обновить</string>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

问题是您正在为每个项目设置一个小部件,如果嵌入式小部件需要它,这样做不会使项目自动变大(实际上,它是尝试调整大小的项目大小提示小部件,如果可能的话)。

您的问题的直接解决方案是根据复选框大小 提示 设置项目的大小(这是小部件请求的首选大小,以便正确显示自身).

        for i in range(len(manga)):
            widget_manga = manga[i]
            box = QtWidgets.QCheckBox(widget_manga)
            item = Qt.QListWidgetItem()
            item.setSizeHint(box.sizeHint())
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, box)

但是,如果您只希望项目可检查,通常不需要这样做,因为默认情况下 QListWidget 中的所有项目都可以检查,您只需要 明确地 设置初始状态:

        for i in range(len(manga)):
            widget_manga = manga[i]
            item = Qt.QListWidgetItem(widget_manga)
            item.setCheckState(QtCore.Qt.Unchecked)
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, box)

如果您需要有关检查状态更改的通知,请连接到发出正在修改的项目的 itemChanged 信号,然后验证其 checkState() getter 函数,记住检查状态在 Qt 中有三个值:Unchecked (0), PartiallyChecked (1) 和 Checked (2).

然后,如果您想知道所有选中的项目,请在 for 循环中使用该函数:

class Widget(QtWidgets.QMainWindow):
    def __init__(self):
        # ...
        self.listWidget.itemChanged.connect(self.mangaItemChanged)

    def mangaItemChanged(self, changed):
        print('{} changed to {}'.format(
            changed.text(), changed.checkState() == QtCore.Qt.Checked)
        for i in range(self.listWidget.count()):
            item = self.listWidget.item(i)
            print(item.text(), item.checkState() == QtCore.Qt.Checked)

我看到您正在为 UI 中的所有小部件使用手动固定几何图形;考虑到 很多 原因不鼓励这样做,应该首选 layout managers