python - 防止 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_())
解决方案
这与绘画无关(显然不能“向外”),而是与您获取坐标的方式有关。
只需确保该点位于小部件的边缘内:
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()])
推荐阅读
- sql - 为什么 JasperReports 忽略 $!P SQL-ingection?
- uml - UML用例图检查用户权限
- java - 路径形状Android中间的中心文本
- ios - path.stroke() 正在崩溃
- python - Python:尽可能快地向下转换数据帧
- windows - WTSIsRemoteSession 始终返回 TRUE
- reactjs - 如何使用 React 组件作为增强器?
- javascript - 使用 Axios 对图像发出 API 请求,接收未知字符作为响应
- javascript - 如何在 v-for 中可视化 v-chart,其中每个对象都是 v-chart 的数据?
- javascript - 具有“**”模式匹配的角度路由重定向目录路径