Reputation: 464
This program has a simple list widget. How do I change the background color of any specific item in the list without it being clicked?
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()
Upvotes: 1
Views: 1481
Reputation: 243897
The task is trivial:
item = ui.lst_positions.item(item_number_to_change)
item.setBackground(QtGui.QColor("red"))
Update:
The problem is that you should not update the GUI from another thread since the elements of the GUI are not thread-safe, so you get that warning that you point out in the comments. One solution is to create a QObject that has signals (which are thread-safe) to exchange information between threads.
# ...
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()
# ...
Note: Just because the text is displayed correctly does not imply that it is correct. Qt does not guarantee (that implies that it can fail) the correct operation if the GUI is updated from another thread directly.
Upvotes: 1