首页 > 解决方案 > PyQt5 - 如何更改列表小部件中的特定项目背景颜色

问题描述

这个程序有一个简单的列表小部件。如何在不单击列表中更改任何特定项目的背景颜色?

from PyQt5 import QtWidgets, uic, QtGui
import threading

app = QtWidgets.QApplication([])
ui = uic.loadUi("app.ui")

update_ui = True

ui.lst_positions.addItem("Item 1")
ui.lst_positions.addItem("Item 2")
ui.lst_positions.addItem("Item 3")


def ui_update():
    while update_ui == True:
        # Updating labels works fine with threading
        ui.lbl_in_position.setText("Random text")
        # This does not work with threading
        item = ui.lst_positions.item(1)
        item.setBackground(QtGui.QColor("red"))


ui_thread = threading.Thread(target=ui_update)
ui_thread.daemon = True

ui_thread.start()

ui.show()
app.exec()

标签: pythonpyqt5

解决方案


任务很简单:

  • 获取与索引关联的 QListWidgetItem。
  • 使用 QListWidgetItem 的 setBackground 方法。
item = ui.lst_positions.item(item_number_to_change)
item.setBackground(QtGui.QColor("red"))

更新:

问题是您不应该从另一个线程更新 GUI,因为 GUI 的元素不是线程安全的,因此您会收到您在评论中指出的警告。一种解决方案是创建一个具有信号(线程安全)的 QObject,以在线程之间交换信息。

# ...
class Signaller(QtCore.QObject):
    textChanged = QtCore.pyqtSignal(str)
    itemChanged = QtCore.pyqtSignal(int, QtGui.QColor)


def ui_update(qobject):
    while update_ui == True:
        qobject.textChanged.emit("Random text")
        qobject.itemChanged.emit(i, QtGui.QColor("red"))


def foo(i, color):
    item = ui.lst_positions.item(i)
    if item:
        item.setBackground(color)

signaller = Signaller()
signaller.textChanged.connect(ui.lbl_in_position.setText)
signaller.itemChanged.connect(foo)

ui_thread = threading.Thread(target=ui_update, args=(signaller,))
ui_thread.daemon = True

ui_thread.start()
# ...

注意:仅仅因为文本显示正确并不意味着它是正确的。如果直接从另一个线程更新 GUI,Qt 不保证(这意味着它可能会失败)正确的操作。


推荐阅读