使用父窗口小部件的滚轮缩放时更改子窗口小部件的大小

问题描述 投票:0回答:1

我有一个父小部件(QWidget)。我使用 PaintEvent 方法在其上绘制网格。该小部件有一个子小部件(QWidget)。子窗口小部件只能在父窗口小部件的网格单元中移动(我已经重写了这些方法)。我需要实现以下功能:

能够缩放网格。也就是说,当我滚动鼠标滚轮时,屏幕上适合的单元格数量会增加。因此,当我向另一个方向滚动滚轮时,数量会减少。我在wheelEvent方法中实现了这个功能。

增加位于单元格中的小部件的大小。也就是说,当您接近时,小部件的大小与单元格的大小成比例增长。我对此有问题,因为小部件尺寸的减小/增大与单元格尺寸不成比例。 我尝试使用坐标变换,但没有成功。让我立即澄清:我没有在 QGraphicsView 中实现所有这些功能。但这些类并不合适,因为无法在 QGraphicsScene 上放置安装了第三方应用程序窗口的小部件。我的程序涉及拦截第三方窗口并将这些窗口安装到小部件中,并进一步将这些小部件添加到网格中。我将不胜感激任何帮助!

class MoveWidget(QWidget):

    def __init__(self):
        super(MoveWidget, self).__init__()
        self.click_rect = self.rect()
        self.selected_edge = None
        self.click_pos = None
        self.setAutoFillBackground(True)
        self.setStyleSheet("background-color: yellow; "
                           "color: red;"
                           "border: 2px solid blue;")
        grid = QGridLayout(self)
        self.setLayout(grid)
        grid.addWidget(QPushButton("fdfdsfdsfdsf"), 0, 0)
        grid.addWidget(QPushButton("1111111111111"), 1, 0)
        self.setGeometry(0, 0, 300, 300)

    def paintEvent(self, a0) -> None:

        opt = QStyleOption()

        opt.initFrom(self)
        painter = QPainter(self)
        self.style().drawPrimitive(QStyle.PrimitiveElement.PE_Widget, opt, painter, self)


    def mousePressEvent(self, event):
        self.click_pos = event.pos()
        rect = self.rect()
        top = abs(rect.top())
        bottom = abs(rect.bottom())
        left = abs(rect.left())
        right = abs(rect.right())

        if abs(left - abs(self.click_pos.x())) < 30 and (
                abs(bottom - abs(self.click_pos.y())) > 30) and (abs(top - abs(self.click_pos.y())) > 30):
            self.selected_edge = 'left'

        elif abs(right - abs(self.click_pos.x())) < 30 and (
                abs(bottom - abs(self.click_pos.y())) > 30) and (abs(top - abs(self.click_pos.y())) > 30):
            self.selected_edge = 'right'

        elif abs(top - abs(self.click_pos.y())) < 30 and (abs(right - abs(self.click_pos.x())) > 30) and (
                abs(left - abs(self.click_pos.x())) > 30):
            self.selected_edge = 'top'

        elif abs(bottom - abs(self.click_pos.y())) < 30 and (
                abs(right - abs(self.click_pos.x())) > 30) and (abs(left - abs(self.click_pos.x())) > 30):
            self.selected_edge = 'bottom'

        elif (abs(bottom - abs(self.click_pos.y())) < 30) and (abs(right - abs(self.click_pos.x())) < 30):
            self.selected_edge = 'diag_bottom_right'

        elif (abs(bottom - abs(self.click_pos.y())) < 30) and (abs(left - abs(self.click_pos.x())) < 30):
            self.selected_edge = 'diag_bottom_left'

        elif (abs(top - abs(self.click_pos.y())) < 30) and (abs(right - abs(self.click_pos.x())) < 30):
            self.selected_edge = 'diag_top_right'

        elif (abs(top - abs(self.click_pos.y())) < 30) and (abs(left - abs(self.click_pos.x())) < 30):
            self.selected_edge = 'diag_top_left'

        else:
            self.selected_edge = None
        self.click_pos = event.pos()
        self.click_rect = rect
        self.cl = self.mapFromParent(QPoint(rect.x(), rect.y()))
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        pos = event.pos()

        x_diff = (round((pos.x() - self.click_pos.x()) / 300) * 300)
        y_diff = (round((pos.y() - self.click_pos.y()) / 300) * 300)

        # Start with the rectangle as it was when clicked.
        rect = QRectF(self.click_rect)

        # c = self.rect().getCoords()
        # rect = QRectF(c[0], c[1], c[2], c[3],)
        self.pos()

        if self.selected_edge is None:

            self.move(self.mapToParent(QPoint(x_diff, y_diff)))
            print(self.pos())
            return
        elif self.selected_edge == 'top':
            rect.adjust(0, y_diff, 0, 0)


        elif self.selected_edge == 'left':

            rect.adjust(x_diff, 0, 0, 0)

        elif self.selected_edge == 'bottom':

            rect.adjust(0, 0, 0, y_diff)

        elif self.selected_edge == 'right':

            rect.adjust(0, 0, (x_diff), 0)

        elif self.selected_edge == 'diag_bottom_right':

            rect.adjust(0, 0, (x_diff), (x_diff))

        elif self.selected_edge == 'diag_top_right':

            rect.adjust(0, -(x_diff), (x_diff), 0)

        elif self.selected_edge == 'diag_bottom_left':

            rect.adjust((x_diff), 0, 0, -(x_diff))

        elif self.selected_edge == 'diag_top_left':

            rect.adjust((x_diff), (x_diff), 0, 0)

        s = self.mapToParent(QPoint(int(rect.x()), int(rect.y())))

        d = rect.getCoords()
        ee = self.mapToParent(QPoint(int(d[2]), int(d[3])))
        self.setGeometry(s.x(), s.y(), int(d[2]), int(d[3]))
        s = self.rect()

        print(self.pos())



      
    class WidMain(QWidget):

    def __init__(self):
        super().__init__()
        self.setStyleSheet("background: transparent;")
        self.setAutoFillBackground(True)
        self.movewid = MoveWidget()
        self.movewid.setParent(self)
      
        self.factor = 1.0
   

    def wheelEvent(self, event):
        self.factor *= 1.01 ** (event.angleDelta().y() / 15.0)
        self.update()
        print("масштаб", self.factor)
        child = self.children()
        print(child[0].rect(), "геометрия дочернего виджета без применения преобразования в своих координатах")

        transform = QTransform()
        transform.scale(self.factor, self.factor)


        print(transform.mapRect(child[0].rect()), "геометрия дочернего виджета с применения преобразования в своих координатах")
        child[0].setGeometry(transform.mapRect(child[0].rect()))
        print(child[0].rect(),'Новая геометрия дочернего виджета после преобразований')
        transform.reset()
       

    def paintEvent(self, a0) -> None:
        opt = QStyleOption()
        opt.initFrom(self)
        painter = QPainter(self)
        self.style().drawPrimitive(QStyle.PrimitiveElement.PE_Widget, opt, painter, self)

        pen = QPen(QColor("blue"))
        pen.setWidth(5)
        painter.setPen(pen)
        child = self.children()
       
        transform = QTransform()
        transform.scale(self.factor, self.factor)
        painter.setTransform(transform)


        for i in range(0, int(self.width()*1000), 300):
            painter.drawLine(i, 0, i, int(self.height()*1000))
        for i in range(0, int(self.height()*1000), 300):
            painter.drawLine(0, i, int(self.width()*1000), i)

        super().paintEvent(a0)

    if __name__ == '__main__':
    app = QApplication([])

    w = WidMain()

    w.show()

    app.exec()

qt pyqt pyqt5 pyqt6
1个回答
0
投票

您没有考虑之前应用于几何体的当前比例。

一个可能更正确的实现如下:

    def wheelEvent(self, event):
        old = self.factor

        self.factor *= 1.01 ** (event.angleDelta().y() / 15.0)

        child = self.children()

        new = self.factor / old
        transform = QTransform().scale(new, new)

        child[0].setGeometry(transform.mapRect(child[0].rect()))

        self.update()

但请注意,您使用的是基于整数的几何形状,这意味着如果超出某个“放大”因子,您将遇到近似问题。

更好的方法是基于网格的占用“单元”,使用预定义的几何图形作为参考,并始终基于此计算新的几何图形。

© www.soinside.com 2019 - 2024. All rights reserved.