Запретить точке QPainter выходить за пределы области окна

#python #python-3.x #pyqt #pyqt4 #qpainter

#python #python-3.x #pyqt #pyqt4 #qpainter

Вопрос:

У меня есть приложение PyQt, в котором я должен реализовать функцию перетаскивания и удаления точек, созданных с помощью QPainter . Моя проблема в том, что я даже могу перетащить эти точки за пределы области окна, например, я могу перетащить точку в строку заголовка или панель задач и оставить ее там, а когда я оставлю ее там, я больше не смогу перетащить их обратно в свое главное окно.

Пожалуйста, предоставьте решение, чтобы я никогда не мог перетащить их туда.

Код:

 import sys
import numpy as np

from PyQt4 import QtCore, QtGui


class Canvas(QtGui.QWidget):

    DELTA = 100 #for the minimum distance        

    def __init__(self, parent=None):
        super(Canvas, self).__init__(parent)
        self.draggin_idx = -1        
        self.points = np.array([[x[0],x[1]] for x in [[100,200], [200,200], [100,400], [200,400]]], dtype=np.float)  
        self.id = None 

        self.points_dict = {}

        for i, x in enumerate(self.points):
            point=(int(x[0]),int(x[1]))
            self.points_dict[i] = point

    def paintEvent(self, e):
        qp = QtGui.QPainter()
        qp.begin(self)
        self.drawPoints(qp)
        self.drawLines(qp)
        qp.end()

    def drawPoints(self, qp):
        # qp.setPen(QtCore.Qt.red)
        pen = QtGui.QPen()
        pen.setWidth(10)
        pen.setColor(QtGui.QColor('red'))
        qp.setPen(pen)
        for x,y in self.points:
            qp.drawPoint(x,y)        

    def drawLines(self, qp):
        # pen.setWidth(5)
        # pen.setColor(QtGui.QColor('red'))
        qp.setPen(QtCore.Qt.red)
        qp.drawLine(self.points_dict[0][0], self.points_dict[0][1], self.points_dict[1][0], self.points_dict[1][1])
        qp.drawLine(self.points_dict[1][0], self.points_dict[1][1], self.points_dict[3][0], self.points_dict[3][1])
        qp.drawLine(self.points_dict[3][0], self.points_dict[3][1], self.points_dict[2][0], self.points_dict[2][1])
        qp.drawLine(self.points_dict[2][0], self.points_dict[2][1], self.points_dict[0][0], self.points_dict[0][1])

    def _get_point(self, evt):
        return np.array([evt.pos().x(),evt.pos().y()])

    #get the click coordinates
    def mousePressEvent(self, evt):
        if evt.button() == QtCore.Qt.LeftButton and self.draggin_idx == -1:
            point = self._get_point(evt)
            int_point = (int(point[0]), int(point[1]))
            min_dist = ((int_point[0]-self.points_dict[0][0])**2   (int_point[1]-self.points_dict[0][1])**2)**0.5
            
            for i, x in enumerate(list(self.points_dict.values())):
                distance = ((int_point[0]-x[0])**2   (int_point[1]-x[1])**2)**0.5
                if min_dist >= distance:
                    min_dist = distance
                    self.id = i
                    
            #dist will hold the square distance from the click to the points
            dist = self.points - point
            dist = dist[:,0]**2   dist[:,1]**2
            dist[dist>self.DELTA] = np.inf #obviate the distances above DELTA
            if dist.min() < np.inf:
                self.draggin_idx = dist.argmin()        

    def mouseMoveEvent(self, evt):
        if self.draggin_idx != -1:
            point = self._get_point(evt)
            self.points[self.draggin_idx] = point
            self.update()

    def mouseReleaseEvent(self, evt):
        if evt.button() == QtCore.Qt.LeftButton and self.draggin_idx != -1:
            point = self._get_point(evt)
            int_point = (int(point[0]), int(point[1]))
            self.points_dict[self.id] = int_point
            self.points[self.draggin_idx] = point
            self.draggin_idx = -1
            self.update()


if __name__ == "__main__":
    app = QtGui.QApplication([])
    win = Canvas()
    win.showMaximized()
    sys.exit(app.exec_())
 

Комментарии:

1. @deepanshu Не изменяйте и не добавляйте больше проблем в свой пост, поскольку это сделает ваш вопрос неразрешимым. Ответы основаны на MRE, предоставленном OP, если вы измените MRE, у вас, вероятно, будет другой ответ, и это большой недостаток. Если у вас возникла новая проблема, создайте новое сообщение

2. @deepanshu Нет, если я помогу вам в вашем новом сообщении, другой пользователь возьмет его в качестве примера и выполнит то же самое неправильное действие

3. Даже если вы этого не знали, вы не можете задать вопрос с кодом, который не связан с тем, что вам нужно. Хотя примеры должны быть минимальными, они также должны отражать их контекст; проблема не в том, что вы не знали о разнице, а в том, что вы вообще ничего об этом не упомянули. Если вы спрашиваете о QPainter и показываете виджет с его paintEvent, то как мы можем даже представить, что вы пытаетесь сделать совершенно другое? И, да, мы могли бы вам помочь: создайте новый и подходящий вопрос, поскольку мы не будем отвечать здесь, потому что он полностью не соответствует теме того, что вы спросили.

4. @deepanshu Пожалуйста, не изменяйте свой пост, добавляя информацию из QGraphicsScene, поскольку в вашем MRE нет никаких следов этого, также вы уже указали, что опубликованный ответ решает вашу проблему. С помощью этих действий вы только препятствуете сообществу помогать вам

5. @deepanshu Точно, если у вас есть другая проблема (просто ввод другого элемента делает его еще одной проблемой), то что нужно сделать?: создать новое сообщение. Это нормально в SO, и я удивлен, что вы не знаете этого правила, поскольку у вас более 24 сообщений и более 3 лет на сайте

Ответ №1:

Это не имеет ничего общего с картиной (которая, очевидно, не может выходить «наружу»), а с тем, как вы получаете координаты.

Просто убедитесь, что точка находится на полях виджета:

     def _get_point(self, evt):
        pos = evt.pos()
        if pos.x() < 0:
            pos.setX(0)
        elif pos.x() > self.width():
            pos.setX(self.width())
        if pos.y() < 0:
            pos.setY(0)
        elif pos.y() > self.height():
            pos.setY(self.height())
        return np.array([pos.x(), pos.y()])
 

Комментарии:

1. @musicamanate Проблема была решена благодаря вам. Но не могли бы вы сказать мне одну вещь, когда я применяю все это «перетаскивание» над a QGraphicsView , тогда я не могу перетаскивать точки до углов и краев …. всегда остается некоторое количество отступов. Почему это происходит?

2. @deepanshu QGraphicsScene — это совершенно другое дело: границы сцены практически бесконечны (вот почему она прокручивается). Если ваш вопрос касался использования QGraphicsScene вместо стандартного QWidget, вы должны были спросить об ЭТОМ .