Изменение размера дочернего виджета при масштабировании колесом родительского
у меня есть родительский виджет(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()
"""