PyQt - 基于值更新的闪烁背景颜色
PyQt - Blink Background Color based on Value Update
我在根据更改的值设置 QWidgetItem 的背景颜色时遇到问题。
我有以下设置,它只是根据单击按钮将随机数生成到 QTableWidget 中。
我想让单元格的背景根据新值高于或低于旧值而改变。例如,如果新值较高,则闪烁蓝色一秒钟(或半秒),或者如果新值低于 flash/blink 则闪烁黄色一段时间。
我完全不知道从哪里开始这个过程。
非常感谢
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
from random import randint
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(100, 100, 350, 380)
self.createTable()
self.button = QPushButton('Update Values', self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.on_click)
self.show()
def createTable(self):
self.tableWidget = QTableWidget()
self.nrows=10
self.ncols=3
self.tableWidget.setRowCount(self.nrows)
self.tableWidget.setColumnCount(self.ncols)
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.setItem(i, j, QTableWidgetItem('{}'.format(randint(0,9))))
self.tableWidget.move(0,0)
self.tableWidget.doubleClicked.connect(self.on_click)
@pyqtSlot()
def on_click(self):
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.setItem(i, j, QTableWidgetItem('{}'.format(randint(0,9))))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
可能有许多不同的方法可以实现这一点。一种方法是创建 QTableWidgetItem
的子 class 并覆盖 setData
方法。这将允许您监视特定 item data role 的哪些值正在更改。 (如果你使用像 QTableWidgem.itemChanged()
这样的信号,这是不可能的,因为它没有给你角色)。
以这种方式做事时唯一要记住的是,它只能在 将项目添加到 table 之后监视更改。因此,您需要先添加空白项,然后再更新所有值。
改变背景颜色的机制要简单得多,因为它只需要 single-shot timer.
以下是基于您的示例的上述所有内容的演示:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QColor
from PyQt5.QtCore import pyqtSlot, Qt, QTimer
from random import randint
class TableWidgetItem(QTableWidgetItem):
def setData(self, role, value):
if role == Qt.DisplayRole:
try:
newvalue = int(value)
oldvalue = int(self.data(role))
except (ValueError, TypeError):
pass
else:
if newvalue != oldvalue:
if newvalue > oldvalue:
color = QColor('aliceblue')
elif newvalue < oldvalue:
color = QColor('lightyellow')
def update_background(color=None):
super(TableWidgetItem, self).setData(
Qt.BackgroundRole, color)
update_background(color)
QTimer.singleShot(2000, update_background)
super(TableWidgetItem, self).setData(role, value)
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(700, 100, 350, 380)
self.createTable()
self.button = QPushButton('Update Values', self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.populateTable)
self.show()
def createTable(self):
self.tableWidget = QTableWidget()
self.nrows=10
self.ncols=3
self.tableWidget.setRowCount(self.nrows)
self.tableWidget.setColumnCount(self.ncols)
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.setItem(i, j, TableWidgetItem())
self.tableWidget.move(0,0)
self.tableWidget.doubleClicked.connect(self.populateTable)
self.populateTable()
@pyqtSlot()
def populateTable(self):
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.item(i, j).setText('{}'.format(randint(0,9)))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
我在根据更改的值设置 QWidgetItem 的背景颜色时遇到问题。
我有以下设置,它只是根据单击按钮将随机数生成到 QTableWidget 中。
我想让单元格的背景根据新值高于或低于旧值而改变。例如,如果新值较高,则闪烁蓝色一秒钟(或半秒),或者如果新值低于 flash/blink 则闪烁黄色一段时间。
我完全不知道从哪里开始这个过程。
非常感谢
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
from random import randint
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(100, 100, 350, 380)
self.createTable()
self.button = QPushButton('Update Values', self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.on_click)
self.show()
def createTable(self):
self.tableWidget = QTableWidget()
self.nrows=10
self.ncols=3
self.tableWidget.setRowCount(self.nrows)
self.tableWidget.setColumnCount(self.ncols)
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.setItem(i, j, QTableWidgetItem('{}'.format(randint(0,9))))
self.tableWidget.move(0,0)
self.tableWidget.doubleClicked.connect(self.on_click)
@pyqtSlot()
def on_click(self):
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.setItem(i, j, QTableWidgetItem('{}'.format(randint(0,9))))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
可能有许多不同的方法可以实现这一点。一种方法是创建 QTableWidgetItem
的子 class 并覆盖 setData
方法。这将允许您监视特定 item data role 的哪些值正在更改。 (如果你使用像 QTableWidgem.itemChanged()
这样的信号,这是不可能的,因为它没有给你角色)。
以这种方式做事时唯一要记住的是,它只能在 将项目添加到 table 之后监视更改。因此,您需要先添加空白项,然后再更新所有值。
改变背景颜色的机制要简单得多,因为它只需要 single-shot timer.
以下是基于您的示例的上述所有内容的演示:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QColor
from PyQt5.QtCore import pyqtSlot, Qt, QTimer
from random import randint
class TableWidgetItem(QTableWidgetItem):
def setData(self, role, value):
if role == Qt.DisplayRole:
try:
newvalue = int(value)
oldvalue = int(self.data(role))
except (ValueError, TypeError):
pass
else:
if newvalue != oldvalue:
if newvalue > oldvalue:
color = QColor('aliceblue')
elif newvalue < oldvalue:
color = QColor('lightyellow')
def update_background(color=None):
super(TableWidgetItem, self).setData(
Qt.BackgroundRole, color)
update_background(color)
QTimer.singleShot(2000, update_background)
super(TableWidgetItem, self).setData(role, value)
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(700, 100, 350, 380)
self.createTable()
self.button = QPushButton('Update Values', self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.populateTable)
self.show()
def createTable(self):
self.tableWidget = QTableWidget()
self.nrows=10
self.ncols=3
self.tableWidget.setRowCount(self.nrows)
self.tableWidget.setColumnCount(self.ncols)
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.setItem(i, j, TableWidgetItem())
self.tableWidget.move(0,0)
self.tableWidget.doubleClicked.connect(self.populateTable)
self.populateTable()
@pyqtSlot()
def populateTable(self):
for i in range(self.nrows):
for j in range(self.ncols):
self.tableWidget.item(i, j).setText('{}'.format(randint(0,9)))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())