如何在QTableWidget的cellChanged信号中区分颜色与文本变更
Got it, let's break down what's happening here and fix those annoying issues:
The core problem is that Qt's cellChanged signal fires any time any property of a QTableWidgetItem changes—not just when the text is edited. When your search function changes the cell's background color, it triggers this signal, which then runs your validation logic incorrectly. Plus, relying on previous_value set only when a cell is selected leads to errors when no cell is selected.
Here's a clean, reliable solution:
Step 1: Track Valid Text for Each Cell
Instead of relying on a single previous_value variable, store the "valid" text for each cell using a custom data role (Qt.UserRole). This way, every cell keeps track of its own approved value, regardless of selection state.
Step 2: Update the cellChanged Handler
In your on_tablewidget_cell_changed method, first check if the cell's text actually changed. If it's the same as the stored valid text, that means the change was something like a background color update—so we skip the validation logic entirely. If the text did change, we run the validation and update the stored value if it passes.
Step 3: Clean Up Unnecessary Code
We can remove the itemSelectionChanged connection since we don't need previous_value anymore. This eliminates the "no previous_value" error entirely.
Full Fixed Code
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sys class myapp(QWidget): def __init__(self): QWidget.__init__(self) self.tableWidget = QTableWidget() self.tableWidget.setSortingEnabled(True) self.tableWidget.setRowCount(5) self.tableWidget.setColumnCount(5) # Initialize cells with stored valid text for i in range(5): for j in range(5): item_text = f"cell[{i},{j}]" item = QTableWidgetItem(item_text) # Store valid text using a custom role item.setData(Qt.UserRole, item_text) self.tableWidget.setItem(i,j,item) # Only connect cellChanged (no more itemSelectionChanged) self.tableWidget.cellChanged.connect(self.on_tablewidget_cell_changed) self.search_entry = QLineEdit() self.search_entry.textChanged.connect(self.seek) layout = QVBoxLayout() layout.addWidget(self.tableWidget) layout.addWidget(self.search_entry) self.setLayout(layout) def on_tablewidget_cell_changed(self, row, col): item = self.tableWidget.item(row, col) current_text = item.text() saved_valid_text = item.data(Qt.UserRole) # If text hasn't changed, this is a property update (like color)—skip if current_text == saved_valid_text: return # Validate if input is numeric if not self.check_numeric(current_text): # Revert to the last valid text item.setText(saved_valid_text) else: # Update stored valid text and save to SQLite here item.setData(Qt.UserRole, current_text) # Example: save_to_sql(row, col, current_text) def seek(self): keyword = self.search_entry.text() # Clear all existing background colors first for row in range(self.tableWidget.rowCount()): for col in range(self.tableWidget.columnCount()): self.tableWidget.item(row, col).setBackground(Qt.white) # Highlight matching cells if keyword exists if keyword: matching_items = self.tableWidget.findItems(keyword, Qt.MatchContains) for item in matching_items: item.setBackground(Qt.red) def check_numeric(self, value): # Simplified numeric check (handles empty string correctly) stripped_value = value.strip() return stripped_value.isdigit() if stripped_value else False app = QApplication(sys.argv) win = myapp() win.show() sys.exit(app.exec_())
Bonus Improvements
- Simplified Numeric Check: Replaced the list comprehension with
str.isdigit()for cleaner, more readable code. - Clear Previous Highlights: Added code to reset all cell backgrounds before applying new search highlights, so old results don't linger.
- No More Selection Dependency: Removed the
itemSelectionChangedconnection, eliminating the "no previous_value" error entirely.
This setup will correctly ignore background color changes in the cellChanged handler, only running validation when the actual text is edited. You can now safely add your SQLite save logic in the else block where we update the stored valid text.
内容的提问来源于stack exchange,提问作者Shoaib Mirzaei

