首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用鼠标调整QGraphicsItem的大小

用鼠标调整QGraphicsItem的大小
EN

Stack Overflow用户
提问于 2015-12-23 06:09:23
回答 5查看 10.3K关注 0票数 10

在将长方形放入QGraphicsScene并使其与鼠标移动后,我如何用鼠标调整它的大小?

如果没有人知道答案,那么一个例子也可能是好的,我正在使用PyQt4开发Python。

我知道这里也有类似的问题,但他们没有分别回答我。

我的简化代码:

代码语言:javascript
运行
复制
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

app = QApplication(sys.argv)

grview = QGraphicsView()
scene = QGraphicsScene()
scene.setSceneRect(0, 0, 512, 512)

scene.addPixmap(QPixmap('01.png'))
grview.setScene(scene)

item = QGraphicsRectItem(0, 0, 300, 150)

pen = QPen(Qt.darkMagenta)
pen.setWidth(4)
item.setPen(pen)

item.setFlag(QGraphicsItem.ItemIsMovable)
scene.addItem(item)

grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)

grview.show()

sys.exit(app.exec_())
EN

Stack Overflow用户

发布于 2021-05-09 17:08:04

丹尼莱密码非常有用,我特别喜欢调整大小的句柄。我不喜欢这样的事实,你可以把矩形移出窗口限制或调整它的大小,直到它有负的宽度或高度。

此代码强制限制移动和调整大小,因此不会导致这些问题。为了保持这个示例的简单性,我取消了调整手柄的大小。

代码语言:javascript
运行
复制
import typing

from PySide6.QtCore import QRectF, QSize
from PySide6.QtGui import QPen, QBrush, QColor, QResizeEvent
from PySide6.QtWidgets import (QApplication, QGraphicsView, QGraphicsScene,
                               QGraphicsItem, QGraphicsRectItem, QMainWindow,
                               QVBoxLayout, QWidget)


class ResizableRect(QGraphicsRectItem):
    def __init__(self, *args):
        super().__init__(*args)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.setPen(QPen(QBrush(QColor('blue')), 5))
        self.selected_edge = None
        self.click_pos = self.click_rect = None

    def mousePressEvent(self, event):
        """ The mouse is pressed, start tracking movement. """
        self.click_pos = event.pos()
        rect = self.rect()
        if abs(rect.left() - self.click_pos.x()) < 5:
            self.selected_edge = 'left'
        elif abs(rect.right() - self.click_pos.x()) < 5:
            self.selected_edge = 'right'
        elif abs(rect.top() - self.click_pos.y()) < 5:
            self.selected_edge = 'top'
        elif abs(rect.bottom() - self.click_pos.y()) < 5:
            self.selected_edge = 'bottom'
        else:
            self.selected_edge = None
        self.click_pos = event.pos()
        self.click_rect = rect
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        """ Continue tracking movement while the mouse is pressed. """
        # Calculate how much the mouse has moved since the click.
        pos = event.pos()
        x_diff = pos.x() - self.click_pos.x()
        y_diff = pos.y() - self.click_pos.y()

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

        # Then adjust by the distance the mouse moved.
        if self.selected_edge is None:
            rect.translate(x_diff, y_diff)
        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)

        # Figure out the limits of movement. I did it by updating the scene's
        # rect after the window resizes.
        scene_rect = self.scene().sceneRect()
        view_left = scene_rect.left()
        view_top = scene_rect.top()
        view_right = scene_rect.right()
        view_bottom = scene_rect.bottom()

        # Next, check if the rectangle has been dragged out of bounds.
        if rect.top() < view_top:
            if self.selected_edge is None:
                rect.translate(0, view_top-rect.top())
            else:
                rect.setTop(view_top)
        if rect.left() < view_left:
            if self.selected_edge is None:
                rect.translate(view_left-rect.left(), 0)
            else:
                rect.setLeft(view_left)
        if view_bottom < rect.bottom():
            if self.selected_edge is None:
                rect.translate(0, view_bottom - rect.bottom())
            else:
                rect.setBottom(view_bottom)
        if view_right < rect.right():
            if self.selected_edge is None:
                rect.translate(view_right - rect.right(), 0)
            else:
                rect.setRight(view_right)

        # Also check if the rectangle has been dragged inside out.
        if rect.width() < 5:
            if self.selected_edge == 'left':
                rect.setLeft(rect.right() - 5)
            else:
                rect.setRight(rect.left() + 5)
        if rect.height() < 5:
            if self.selected_edge == 'top':
                rect.setTop(rect.bottom() - 5)
            else:
                rect.setBottom(rect.top() + 5)

        # Finally, update the rect that is now guaranteed to stay in bounds.
        self.setRect(rect)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        central = QWidget(self)
        self.setCentralWidget(central)

        self.rect = ResizableRect()
        scene = QGraphicsScene(0, 0, 300, 300)
        scene.addItem(self.rect)
        self.view = QGraphicsView(central)
        self.view.setScene(scene)

        layout = QVBoxLayout(central)
        self.setLayout(layout)
        layout.addWidget(self.view)

        self.old_size: typing.Optional[QSize] = None

    def show(self):
        super().show()
        self.resize_scene()

    def resizeEvent(self, event: QResizeEvent):
        super().resizeEvent(event)
        self.resize_scene()

    def resize_scene(self):
        if not self.isVisible():
            # Viewport size isn't set yet, so calculation won't work.
            return
        size = self.view.maximumViewportSize()
        if self.old_size is None:
            new_rect = QRectF(size.width()/4, size.height()/4,
                              size.width()/2, size.height()/2)
        else:
            old_rect = QRectF(self.rect.rect())
            x_scale = size.width() / self.old_size.width()
            y_scale = size.height() / self.old_size.height()
            new_rect = QRectF(old_rect.left()*x_scale, old_rect.top()*y_scale,
                              old_rect.width()*x_scale, old_rect.height()*y_scale)
        self.rect.setRect(new_rect)
        self.view.scene().setSceneRect(0, 0, size.width(), size.height())
        self.old_size = size


def main():
    app = QApplication()
    window = MainWindow()
    window.show()

    app.exec_()


main()
票数 5
EN
查看全部 5 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34429632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档