如何激活带有自定义元素的列表的 qListWidget 滚动条?
How to activate qListWidget scrollbar for list with custom elements?
我在使用小型桌面应用程序时遇到了一个问题:我想将 QCheckBox 实例添加到 QListWidget 中,但是当我这样做时,其中一些复选框的文本超出了 window.我试图在这些复选框中换行,但我遇到了另一个问题 - 文本相交。
所以,我决定使用滚动条,但如果我只是使用 setHorizontalScrollBar 它是行不通的,但据我所知,它行不通,因为我的项目是不同的小部件。
那么,是否可以让这个水平滚动条滚动带有复选框的列表?
我在 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。
我在使用小型桌面应用程序时遇到了一个问题:我想将 QCheckBox 实例添加到 QListWidget 中,但是当我这样做时,其中一些复选框的文本超出了 window.我试图在这些复选框中换行,但我遇到了另一个问题 - 文本相交。
所以,我决定使用滚动条,但如果我只是使用 setHorizontalScrollBar 它是行不通的,但据我所知,它行不通,因为我的项目是不同的小部件。 那么,是否可以让这个水平滚动条滚动带有复选框的列表?
我在 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。