最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Trouble drawing using pyqt - Stack Overflow

programmeradmin1浏览0评论

I looked around and i could not find anything. So here I am. i am making a very simple drawing sofware in python using pyqt. im starting with a rectangle draw tool. For some reason(maybe due to lack understanding), I cannot for the life of me to get this to work. It is a blank screen that when you click and drag should use the rectangle tool to create the shape. there is a button on there but it is not programmed to do anything yet. When you click in the area it reads the mouse click but no movement or release events. I added a debugger so you can see. now if you click the outer edge of the program(like in the border parts) it will read all events you can even start to draw your rectangle. you just have to start at the edges. This is a fresh install of Python and a new virtual environment that only holds what needs to be installed. Any insight will be awesome! Thanks in advance!

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QGraphicsScene, QGraphicsView, QVBoxLayout, QWidget, QMessageBox, QFileDialog, QGraphicsRectItem
from PyQt5.QtGui import QPixmap, QImage, QPen, QColor
from PyQt5.QtCore import Qt, QPointF

class Test(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.image_path = None
        self.start_point = None
        self.rect_item = None
        self.confirmed_rects = []

    def initUI(self):
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)

        self.fetch_random_button = QPushButton("Test")

        self.scene = QGraphicsScene(self)
        self.view = QGraphicsView(self.scene, self)
        self.layout.addWidget(self.view)

        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Test')
        

    def mousePressEvent(self, event):
        scene_pos = self.view.mapToScene(event.pos())
        self.start_point = scene_pos
        print(f"mousePressEvent: scene_pos = {scene_pos}")

    def mouseMoveEvent(self, event):
        if self.start_point:
            scene_pos = self.view.mapToScene(event.pos())
            top_left, width, height = self.create_rectangle(self.start_point, scene_pos)
            print(f"mouseMoveEvent: scene_pos = {scene_pos}, top_left = {top_left}, width = {width}, height = {height}")
            if self.rect_item:
                self.scene.removeItem(self.rect_item)
            pen = QPen(QColor(0, 0, 255))
            pen.setWidth(2)
            self.rect_item = QGraphicsRectItem(top_left.x(), top_left.y(), width, height)
            self.rect_item.setPen(pen)
            self.scene.addItem(self.rect_item)

    def mouseReleaseEvent(self, event):
        print("mouseReleaseEvent")
        self.start_point = None
        self.rect_item = None

    def create_rectangle(self, start_point, end_point):
        x = min(start_point.x(), end_point.x())
        y = min(start_point.y(), end_point.y())
        width = abs(start_point.x() - end_point.x())
        height = abs(start_point.y() - end_point.y())
        print(f"create_rectangle: start_point = {start_point}, end_point = {end_point}, x = {x}, y = {y}, width = {width}, height = {height}")
        return QPointF(x, y), width, height


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

I looked around and i could not find anything. So here I am. i am making a very simple drawing sofware in python using pyqt. im starting with a rectangle draw tool. For some reason(maybe due to lack understanding), I cannot for the life of me to get this to work. It is a blank screen that when you click and drag should use the rectangle tool to create the shape. there is a button on there but it is not programmed to do anything yet. When you click in the area it reads the mouse click but no movement or release events. I added a debugger so you can see. now if you click the outer edge of the program(like in the border parts) it will read all events you can even start to draw your rectangle. you just have to start at the edges. This is a fresh install of Python and a new virtual environment that only holds what needs to be installed. Any insight will be awesome! Thanks in advance!

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QGraphicsScene, QGraphicsView, QVBoxLayout, QWidget, QMessageBox, QFileDialog, QGraphicsRectItem
from PyQt5.QtGui import QPixmap, QImage, QPen, QColor
from PyQt5.QtCore import Qt, QPointF

class Test(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.image_path = None
        self.start_point = None
        self.rect_item = None
        self.confirmed_rects = []

    def initUI(self):
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)

        self.fetch_random_button = QPushButton("Test")

        self.scene = QGraphicsScene(self)
        self.view = QGraphicsView(self.scene, self)
        self.layout.addWidget(self.view)

        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Test')
        

    def mousePressEvent(self, event):
        scene_pos = self.view.mapToScene(event.pos())
        self.start_point = scene_pos
        print(f"mousePressEvent: scene_pos = {scene_pos}")

    def mouseMoveEvent(self, event):
        if self.start_point:
            scene_pos = self.view.mapToScene(event.pos())
            top_left, width, height = self.create_rectangle(self.start_point, scene_pos)
            print(f"mouseMoveEvent: scene_pos = {scene_pos}, top_left = {top_left}, width = {width}, height = {height}")
            if self.rect_item:
                self.scene.removeItem(self.rect_item)
            pen = QPen(QColor(0, 0, 255))
            pen.setWidth(2)
            self.rect_item = QGraphicsRectItem(top_left.x(), top_left.y(), width, height)
            self.rect_item.setPen(pen)
            self.scene.addItem(self.rect_item)

    def mouseReleaseEvent(self, event):
        print("mouseReleaseEvent")
        self.start_point = None
        self.rect_item = None

    def create_rectangle(self, start_point, end_point):
        x = min(start_point.x(), end_point.x())
        y = min(start_point.y(), end_point.y())
        width = abs(start_point.x() - end_point.x())
        height = abs(start_point.y() - end_point.y())
        print(f"create_rectangle: start_point = {start_point}, end_point = {end_point}, x = {x}, y = {y}, width = {width}, height = {height}")
        return QPointF(x, y), width, height


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

Share Improve this question asked Mar 12 at 18:18 Damion OwensDamion Owens 231 silver badge7 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

The issue is that when you click within the QGraphicsView, the mouse events are intercepted by it and not passed to the QMainWindow. You need to create your own QGraphicsView which will handle those events as you want.

Here is a modification of your program which properly handles the mouse events:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QGraphicsScene, QGraphicsView, QVBoxLayout, QWidget, QMessageBox, QFileDialog, QGraphicsRectItem
from PyQt5.QtGui import QPixmap, QImage, QPen, QColor
from PyQt5.QtCore import Qt, QPointF


class GraphicsView(QGraphicsView):
    def __init__(self, scene, parent=None):
        super().__init__(scene, parent)
        
        self.image_path = None
        self.start_point = None
        self.rect_item = None
        self.confirmed_rects = []
    
    def mousePressEvent(self, event):
        scene_pos = self.mapToScene(event.pos())
        self.start_point = scene_pos
        print(f"mousePressEvent: scene_pos = {scene_pos}")
    
    def mouseMoveEvent(self, event):
        if self.start_point:
            scene_pos = self.mapToScene(event.pos())
            top_left, width, height = self.create_rectangle(self.start_point, scene_pos)
            print(f"mouseMoveEvent: scene_pos = {scene_pos}, top_left = {top_left}, width = {width}, height = {height}")
            if self.rect_item:
                self.scene().removeItem(self.rect_item)
            pen = QPen(QColor(0, 0, 255))
            pen.setWidth(2)
            self.rect_item = QGraphicsRectItem(top_left.x(), top_left.y(), width, height)
            self.rect_item.setPen(pen)
            self.scene().addItem(self.rect_item)
        
    def mouseReleaseEvent(self, event):
        print("mouseReleaseEvent")
        self.start_point = None
        self.rect_item = None

    def create_rectangle(self, start_point, end_point):
        x = min(start_point.x(), end_point.x())
        y = min(start_point.y(), end_point.y())
        width = abs(start_point.x() - end_point.x())
        height = abs(start_point.y() - end_point.y())
        print(f"create_rectangle: start_point = {start_point}, end_point = {end_point}, x = {x}, y = {y}, width = {width}, height = {height}")
        return QPointF(x, y), width, height

class Test(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.image_path = None
        self.start_point = None
        self.rect_item = None
        self.confirmed_rects = []

    def initUI(self):
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)

        self.fetch_random_button = QPushButton("Test")

        self.scene = QGraphicsScene(self)
        self.view = GraphicsView(self.scene, self) # Use your own GraphicsView
        self.layout.addWidget(self.view)

        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Test')
    



if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Test()
    window.show()
    sys.exit(app.exec_())
发布评论

评论列表(0)

  1. 暂无评论