2025, Sep 24 19:32

PySide6 में QTableView के एडिट मोड को डार्क थीम पर पठनीय बनाना: QStyledItemDelegate से साफ समाधान

PySide6 QTableView में डार्क थीम पर एडिट मोड में काला टेक्स्ट क्यों दिखता है, जानें और QStyledItemDelegate से एडिटर का palette सेट कर सरल फिक्स पाएं.

डार्क स्टाइल वाली विंडो में QTableView के अंदर टेक्स्ट संपादित करना डिस्प्ले मोड में तो बिल्कुल सही दिखता है, लेकिन जैसे ही उपयोगकर्ता टाइप करना शुरू करता है, वह अचानक पढ़ना कठिन हो सकता है। अगर आपकी PySide6 ऐप parent QDialog के लिए डार्क बैकग्राउंड सेट करती है और मॉडल से टेबल सेल्स को सफेद रंग में पेंट करती है, तब भी एडिट मोड में दिखने वाला एडिटर हल्के OS थीम पर काले अक्षर दिखा सकता है, जिससे कंटेंट मुश्किल से दिखता है। ऐसा क्यों होता है और इसे साफ़ तरीके से कैसे ठीक करें—यहाँ समझिए।

समस्या का सेटअप

विंडो में स्टाइलशीट के साथ डार्क बैकग्राउंड है, टेबल हेडर पारदर्शी है, मॉडल सेल टेक्स्ट को सफेद रंग में पेंट करता है, और आइटम संपादन योग्य हैं। कोड में यह कुछ ऐसा दिखता है:

from PySide6 import QtCore, QtGui, QtWidgets
dlg = QtWidgets.QDialog()
dlg.setStyleSheet("background-color: #11375E;")
view = QtWidgets.QTableView(dlg)
view.setStyleSheet(
    "QHeaderView::section {\n"
    "background-color: transparent;\n"
    "border-style: hidden\n"
    "}"
)
class GridModel(QtCore.QAbstractTableModel):
    def data(self, ix, role):
        match role:
            case QtCore.Qt.ItemDataRole.ForegroundRole:
                return QtGui.QBrush(QtGui.QColorConstants.White)
        return super().data(ix, role)
    def flags(self, ix):
        return (
            QtCore.Qt.ItemFlag.ItemIsEnabled |
            QtCore.Qt.ItemFlag.ItemIsEditable
        )

डिस्प्ले मोड में यह डार्क और लाइट—दोनों OS थीम पर सही दिखता है। समस्या सिर्फ एडिट मोड में आती है: हल्के थीम पर टाइप किया गया टेक्स्ट डार्क बैकग्राउंड पर काला दिखता है और पढ़ना कठिन हो जाता है।

एडिट मोड में असल में होता क्या है

जब कोई सेल एडिट मोड में जाती है, तो व्यू पेंट किए गए सेल का रंग नहीं बदलता। उसकी बजाय वह एक अलग एडिटर विजेट बनाता है—स्ट्रिंग वैल्यूज़ के लिए डिफ़ॉल्ट रूप से एक फ्रेमलेस QLineEdit—जो उस सेल के ऊपर रखा जाता है। वह एडिटर साधारण विजेट होता है और अपने पैरेंट से पैलेट इनहेरिट करता है। मॉडल से लौटाया गया ForegroundRole एडिटर के रूप को प्रभावित नहीं करता। इसी तरह, व्यू या हेडर पर लगाए गए QSS नियम भी उस अलग एडिटर विजेट पर जरूरी नहीं कि लागू हों।

अगर आपका पैलेट डार्क बैकग्राउंड के अनुरूप नहीं है, तो OS का लाइट थीम डार्क सतह पर काला एडिटिंग टेक्स्ट दिखा देगा। एडिटर को सुसंगत रखने के लिए, उसका पैलेट स्पष्ट रूप से नियंत्रित करना होगा।

समाधान: एडिटर को डेलीगेट करें और उसका पैलेट सेट करें

सबसे सीधा उपाय है, एडिटिंग के लिए बन रहे एडिटर को कस्टमाइज़ करना। QStyledItemDelegate में createEditor को ओवरराइड करें, ज़रूरी रंग सेट करें, और उस डेलीगेट को टेबल पर इंस्टॉल कर दें ताकि यह हर जगह लागू हो।

from PySide6 import QtCore, QtGui, QtWidgets
class EditTintDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, host, opt, ix):
        editor_widget = super().createEditor(host, opt, ix)
        pal = editor_widget.palette()
        pal.setColor(QtGui.QPalette.Base, QtGui.QColor("#11375E"))
        pal.setColor(QtGui.QPalette.Text, QtCore.Qt.white)
        pal.setColor(QtGui.QPalette.Highlight, QtGui.QColor("#1b4f80"))
        pal.setColor(QtGui.QPalette.HighlightedText, QtCore.Qt.white)
        editor_widget.setPalette(pal)
        editor_widget.setStyleSheet("color: white;")
        return editor_widget
# पूरी टेबल पर लागू करें
view.setItemDelegate(EditTintDelegate(view))

इससे इन-प्लेस एडिटर डार्क विंडो से मेल खाता है, टाइप करते समय टेक्स्ट सफेद रहता है, और चयन स्पष्ट दिखाई देता है।

यह तरीका क्यों कारगर है

एडिटर अलग विजेट होता है, इसलिए उसे सीधे स्टाइल करने से थीम-निर्भर अनपेक्षित बदलाव नहीं आते। Base और Text सेट करने से आप एडिटर का बैकग्राउंड और फोरग्राउंड नियंत्रित करते हैं। Highlight और HighlightedText को समायोजित करने से चयन पठनीय रहता है। क्योंकि डेलीगेट एडिटर का निर्माण स्वयं संभालता है, बदलाव सीमित रहता है और हर संपादित सेल पर एकसमान लागू होता है।

विंडो स्तर पर पैलेट कब सेट करें

यदि पूरा डायलॉग डार्क स्कीम का उपयोग करता है, तो टॉप-लेवल विंडो के लिए पैलेट कॉन्फ़िगर करना भी समझदारी है। Window को अपने बैकग्राउंड पर सेट करें और Base को उसी रंग या QColorConstants.Transparent से संरेखित करें, फिर WindowText, ButtonText और Text के लिए सफेद रंग का उपयोग करें—इससे इनहेरिट होने वाले विजेट्स के लिए एक सुसंगत आधार बनता है। यह तरीका सिर्फ टेबल एडिटर से आगे की चीज़ों को भी संबोधित करता है और बिखरी हुई QSS पर निर्भरता घटा सकता है।

मुख्य बातें

QTableView में एडिटिंग के दौरान वास्तव में एक वास्तविक एडिटर विजेट बनाया जाता है, इसलिए मॉडल रोल्स और व्यू स्टाइलशीट्स थीम बदलने पर पठनीय टेक्स्ट की गारंटी नहीं देते। रंगों की पूर्वानुमेयता के लिए QStyledItemDelegate के जरिए एडिटर का पैलेट नियंत्रित करें, और पूरी UI को दृश्य रूप से सुसंगत रखने के लिए पैरेंट विंडो का पैलेट परिभाषित करने पर भी विचार करें। इससे आपकी टेबल डार्क और लाइट—दोनों परिवेशों में पठनीय रहती है और थीम-जनित रिग्रेशन से बचाव होता है।

यह लेख StackOverflow पर प्रश्न (लेखक: user2965433) और Ahrimann Steiner के उत्तर पर आधारित है।