使用 PySide 向 QWidget 子类添加附加参数

Adding additional parameters to QWidget subclass using PySide

我正在向 QWidget 的 subclass 添加颜色参数。我已经找到了几个关于如何向 Python 中的 subclass 添加附加参数的示例 3 并且相信我已经听从了建议。然而,当我使用 box = LineBand(self.widget2, color) 调用 class 的新版本时,我收到错误 File "C:/Users/...", line 63, in showBoxes ... box = LineBand(viewport, color) ... TypeError: __init__() takes 2 positional arguments but 3 were given。但是,我只是用 2 个参数调用 LineBand,对吗?下面是完整的代码。我已经评论了我更改的所有部分。我还注释掉了更改文本背景颜色的代码,以便更清楚地看到彩色线条(当它们实际绘制时)。背景颜色代码工作正常。

import sys
from PySide.QtCore import *
from PySide.QtGui import *

db = ((5,8,'A',Qt.darkMagenta),(20,35,'B',Qt.darkYellow),(45,60,'C',Qt.darkCyan)) # added color to db

class TextEditor(QTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        text="This is example text that is several lines\nlong and also\nstrangely broken up and can be\nwrapped."
        self.setText(text)
        cursor = self.textCursor()
        for n in range(0,len(db)):
            row = db[n]
            startChar = row[0]
            endChar = row[1]
            id = row[2]
            color = row[3]  # assign color from db to variable
            cursor.setPosition(startChar)
            cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, endChar-startChar)
            #charfmt = cursor.charFormat()
            #charfmt.setBackground(QColor(color)) # assign color to highlight (background)
            #cursor.setCharFormat(charfmt)
        cursor.clearSelection()
        self.setTextCursor(cursor)

    def getBoundingRect(self, start, end):
        cursor = self.textCursor()
        cursor.setPosition(end)
        last_rect = end_rect = self.cursorRect(cursor)
        cursor.setPosition(start)
        first_rect = start_rect = self.cursorRect(cursor)
        if start_rect.y() != end_rect.y():
            cursor.movePosition(QTextCursor.StartOfLine)
            first_rect = last_rect = self.cursorRect(cursor)
            while True:
                cursor.movePosition(QTextCursor.EndOfLine)
                rect = self.cursorRect(cursor)
                if rect.y() < end_rect.y() and rect.x() > last_rect.x():
                    last_rect = rect
                moved = cursor.movePosition(QTextCursor.NextCharacter)
                if not moved or rect.y() > end_rect.y():
                    break
            last_rect = last_rect.united(end_rect)
        return first_rect.united(last_rect)



class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.edit = TextEditor(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.edit)
        self.boxes = []

    def showBoxes(self):
        while self.boxes:
            self.boxes.pop().deleteLater()
        viewport = self.edit.viewport()
        for start, end, id, color in db:  # get color too
            rect = self.edit.getBoundingRect(start, end)
            box = LineBand(viewport, color) # call LineBand with color as argument
            box.setGeometry(rect)
            box.show()
            self.boxes.append(box)

    def resizeEvent(self, event):
        self.showBoxes()
        super().resizeEvent(event)

class LineBand(QWidget):
    def __init__(self, color):  # define color within __init__
        super().__init__(self)
        self.color = color


    def  paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QPen(color, 1.8)) # call setPen with color
        painter.drawLine(self.rect().topLeft(), self.rect().bottomRight())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    window.showBoxes()
    app.exec_()
    sys.exit(app.exec_())

当一个方法没有被覆盖时,它将与父类的实现方法相同,所以如果你想让它工作,你必须添加这些参数,因为这些参数很多时候依赖于父类,一个简单的方法是使用*args**kwargs 并将新参数作为第一个参数传递。此外,您必须使用 self.color 而不是颜色,因为颜色仅存在于构造函数中。

class Window(QWidget):
    [...]
    def showBoxes(self):
        while self.boxes:
            self.boxes.pop().deleteLater()
        viewport = self.edit.viewport()
        for start, end, id, color in db:  # get color too
            rect = self.edit.getBoundingRect(start, end)
            box = LineBand(color, viewport) # call LineBand with color as argument
            box.setGeometry(rect)
            box.show()
            self.boxes.append(box)
    [...]

class LineBand(QWidget):
    def __init__(self, color, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.color = color


    def  paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QPen(self.color, 1.8)) # call setPen with color
        painter.drawLine(self.rect().topLeft(), self.rect().bottomRight())

输出: