การเปลี่ยนสีแถวเมื่อคลิก PyQt

ฉันพยายามทำงานนี้มาหลายวันแล้ว แต่ก็ไม่มีประโยชน์ หวังว่าพวกคุณจะช่วยฉันได้

ฉันมี QSqlTableModel แบบกำหนดเองที่มีสิ่งนี้เนื่องจากเป็นฟังก์ชันข้อมูล:

def data(self, index, role):
    #Formats Cells according to data in them
    if role == QtCore.Qt.TextAlignmentRole:
        if index.column() == 2:
            text = QtSql.QSqlTableModel.data(self, self.index(index.row(), 2), QtCore.Qt.DisplayRole)

            if text.split():
                if not re.search(r'start|Z[NARXTFEISL]|gv', text.split()[0], re.I):
                    return QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop
                else: return QtCore.Qt.AlignLeft
            else: pass
        else: return QtCore.Qt.AlignLeft

    if role == QtCore.Qt.BackgroundRole:
        if 'MILESTONE' in  QtSql.QSqlTableModel.data(self, self.index(index.row(), 2), QtCore.Qt.DisplayRole):
            return QtGui.QBrush(QtCore.Qt.yellow)


    return QtSql.QSqlTableModel.data(self, index, role)

ไม่มีสิ่งใดที่เกี่ยวข้องกับคำถามจริงๆ ยกเว้นบล็อก BackgroundRole สิ่งที่ฉันพยายามทำคือเมื่อฉันคลิกขวาที่ tableview เมนูบริบทจะปรากฏขึ้น:

menu = QMenu()
stepx = menu.addAction('Mark Step as Executed')
stepdx = menu.addAction('Clear Step Execution')

action = menu.exec_(self.tableView.mapToGlobal(pos))
index = self.model.index(self.tableView.rowAt(pos.y()), 2)

if action == stepx:
    logging.info(' Executed Step: ' + str(self.tableView.rowAt(pos.y()) + 1))
    self.model.setData(index, QtCore.QVariant(QtGui.QBrush(QtCore.Qt.red)), QtCore.Qt.BackgroundRole)

ทั้งหมดที่ฉันพยายามทำคือเมื่อฉันคลิก "Mark Step as Executed" บนเมนูตามบริบท ฉันต้องการให้แถว (หรือแม้แต่เซลล์ ตอนนี้ฉันจะทำอะไรก็ได้) เปลี่ยนเป็นสีแดง

สิ่งที่ฉันทำอยู่ไม่ได้ผลและฉันหวังว่าจะมีคนสามารถช่วยฉันได้


person aseylys    schedule 25.09.2017    source แหล่งที่มา


คำตอบ (1)


วิธีแก้ไขง่ายๆ คือการสร้างเขตข้อมูลในตารางฐานข้อมูลและใช้เป็นแฟล็กเพื่อเปลี่ยนสีพื้นหลัง แต่ถ้าคุณไม่สามารถทำการเปลี่ยนแปลงในฐานข้อมูลได้ คุณจะต้องสร้างบทบาทใหม่ จากนั้นเราจะใช้บทบาทนั้นเพื่อทำการเปลี่ยนแปลงที่จำเป็น เพื่อสิ่งนี้เราจะบันทึกแฟล็กในพจนานุกรม คีย์ของพจนานุกรมจะเป็น id เนื่องจากสิ่งเหล่านี้ไม่มีการเปลี่ยนแปลง

class SqlTableModel(QtSql.QSqlTableModel):
    ExecuteRole = QtCore.Qt.UserRole + 1

    def __init__(self, parent=None, db = QtSql.QSqlDatabase()):
        QtSql.QSqlTableModel.__init__(self, parent, db)
        self.d = {}

    def data(self, index, role):
        if role == self.ExecuteRole:
            _id = self.getId(index)
            if _id in self.d.keys():
                return self.d[_id]
            return False

        if role == QtCore.Qt.BackgroundRole:
            if self.data(index, self.ExecuteRole):
                return QtGui.QBrush(QtCore.Qt.red)
            if 'MILESTONE' in QtSql.QSqlTableModel.data(self, self.index(index.row(), 2), QtCore.Qt.DisplayRole):
                return QtGui.QBrush(QtCore.Qt.yellow)

        return QtSql.QSqlTableModel.data(self, index, role)

    def getId(self, index):
        ix = self.fieldIndex("id")
        return self.data(self.index(index.row(), ix), QtCore.Qt.DisplayRole)

    def setData(self, index, value, role):
        if role == self.ExecuteRole:
            self.d[self.getId(index)] = value
            return True
        return QtSql.QSqlTableModel.setData(self, index, value, role)

    def roleNames(self):
        rn = QtSql.QSqlTableModel.roleNames(self)
        rn[self.SelectRole] = QtCore.QByteArray(b'execute')
        return rn

การเปลี่ยนแปลงข้างต้นเปลี่ยนเฉพาะรายการที่เลือกจนกว่าจะรีเฟรชด้วยตนเอง แต่ลักษณะการทำงานนี้ไม่ใช่ลักษณะที่ต้องการทำ ดังนั้นจึงต้องออกสัญญาณโมเดล dataChanged()

class TableView(QtWidgets.QTableView):
    def contextMenuEvent(self, event):
        pos = event.pos()
        menu = QtWidgets.QMenu()
        stepx = menu.addAction('Mark Step as Executed')
        stepdx = menu.addAction('Clear Step Execution')

        action = menu.exec_(self.mapToGlobal(pos))
        if action == stepx:
            if self.model():
                index = self.model().index(self.rowAt(pos.y()), 2)
                self.model().setData(index, True, SqlTableModel.ExecuteRole)
                self.model().dataChanged.emit(self.model().index(index.row(), 0),
                                              self.model().index(index.row(), self.model().columnCount()-1),
                                              [QtCore.Qt.BackgroundRole])

การใช้งานปัจจุบันมีข้อดีคือยกเลิกการเลือกหากเราเปลี่ยนสถานะจากจริงเป็นเท็จ

self.model().setData(index, False, SqlTableModel.ExecuteRole)
person eyllanesc    schedule 25.09.2017
comment
ขอบคุณมากสำหรับสิ่งนี้! วิธีนี้ใช้ได้ผลในแง่ที่ว่ามันเปลี่ยนสีได้จริงๆ และฉันชอบที่สามารถเปลี่ยนสีกลับได้ อย่างไรก็ตาม ดูเหมือนว่าจะเปลี่ยนทั้งโต๊ะเป็นสีแดง ไม่ใช่แค่แถวที่เลือก เหตุใดจึงเป็นเช่นนั้น? - person aseylys; 25.09.2017
comment
คุณแน่ใจไหม? ในการทดสอบของฉัน เพียงเปลี่ยนแถวที่เลือก ลองทำตามตัวอย่างต่อไปนี้ และแจ้งให้เราทราบหากคุณมีข้อผิดพลาดเดียวกัน: gist.github.com/eyllanesc/150e981878122e171bd25dc470781a87 - person eyllanesc; 25.09.2017
comment
หากคุณแบ่งปันโครงการของคุณเพื่อตรวจสอบว่าคุณทำผิดพลาดตรงไหน หากคำตอบของฉันช่วยคุณได้อย่าลืมทำเครื่องหมายว่าถูกต้อง - person eyllanesc; 25.09.2017
comment
ตัวอย่างของคุณใช้งานได้ แต่ของฉันไม่ได้ผล ฉันเชื่อว่ามีบางอย่างเกี่ยวข้องกับวิธีที่ฉันเริ่มต้น qTableView แต่นี่คือโครงการของฉันจนถึงตอนนี้ github.com/aseylys/sView แก้ไข: และฉันทำเครื่องหมายคุณว่าตอบแล้วเพราะคุณตอบ มันเป็นโปรแกรมของฉัน ไม่สามารถให้ความร่วมมือได้นั่นคือปัญหา - person aseylys; 25.09.2017
comment
@aseylys ฉันจะโหลดฐานข้อมูลได้อย่างไร ฉันไม่เห็นข้อมูลใด ๆ ใน tableview - person eyllanesc; 25.09.2017
comment
File->Open Script ขออภัย ฉันยังไม่ได้อ่าน README เลย - person aseylys; 25.09.2017
comment
ปัญหาคือคุณไม่มีคีย์หลักในตาราง แต่ฉันคิดว่า Row # สามารถใช้ได้โดยการเปลี่ยน: ix = self.fieldIndex("id") เป็น ix = self.fieldIndex("Row #") - person eyllanesc; 25.09.2017