简体   繁体   English

QPainter 在 QScrollArea 内绘制线条

[英]QPainter draw lines inside a QScrollArea

I raised a problem earlier on how to draw lines between widgets.我之前提出了一个关于如何在小部件之间画线的问题。 and @eyllanesc solves it very well. @eyllanesc 很好地解决了这个问题。 But I faced another problem.但我遇到了另一个问题。 I try to make the widget with QScrollarea.我尝试使用 QScrollarea 制作小部件。 But the lines are not shown.但是没有显示线条。

When using Widget it works fine with drawing lines, but seems QScrollArea need another paint_event .使用Widget时,它可以很好地绘制线条,但似乎 QScrollArea 需要另一个paint_event Don't know how to do that.不知道该怎么做。

Can anyone help me to show lines with QScrollarea.谁能帮我用 QScrollarea 显示线条。

import functools
import sys

from PyQt5.QtCore import QEvent, QLine
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget, QScrollArea


class Drawer:
    def __init__(self):
        self._lines = []

    @property
    def lines(self):
        return self._lines

    @lines.setter
    def lines(self, l):
        self._lines = l[:]
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        for line in self.lines:
            painter.drawLine(line)


class Example(QScrollArea, Drawer):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.initUI()

    def initUI(self):
        self.AddButton = QPushButton("Add")
        self.AddButton.clicked.connect(self.addbuttonwithline)

        self.w = QWidget()
        self.setWidget(self.w)
        self.setWidgetResizable(True)

        self.vbox = QVBoxLayout(self.w)
        self.vbox.addWidget(self.AddButton)

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle("Buttons")

        self.buttons = []

    def addbuttonwithline(self):
        button = QPushButton("delete")
        button.clicked.connect(functools.partial(self.remove_button, button))
        button.installEventFilter(self)
        self.vbox.addWidget(button)
        self.buttons.append(button)
        self.recalculate_position()

    def remove_button(self, button):
        self.buttons.remove(button)
        button.deleteLater()
        self.recalculate_position()

    def recalculate_position(self):
        lines = []
        for last_button, next_button in zip(self.buttons, self.buttons[1:]):
            l = QLine(last_button.pos().x()+50, last_button.pos().y(), next_button.pos().x()+50, next_button.pos().y())
            lines.append(l)
        self.lines = lines

    def eventFilter(self, o, e):
        if e.type() == QEvent.Move and o in self.buttons:
            self.recalculate_position()
        return super().eventFilter(o, e)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())

QScrollArea is designed to be a container so you should not paint over that item since the content covers it, instead it sets the painting in the content widget. QScrollArea 被设计为一个容器,因此您不应该在该项目上绘画,因为内容会覆盖它,而是在内容小部件中设置绘画。

Based on my code from my previous answer then just change to:根据我之前回答的代码,然后更改为:

if __name__ == "__main__":

    app = QApplication(sys.argv)
    ex = Example()
    w = QScrollArea(widgetResizable=True)
    w.setWidget(ex)
    w.show()
    sys.exit(app.exec_())

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM