나는 PyQt5 GUI에서 활용하려고하는 draggable matplotlib 객체 라이브러리를 가지고 있습니다. 객체 'event listeners은 독립형 matplotlib Figure 창에서 올바르게 작동하지만 그림이 QT 위젯에 포함되어있을 때는 작동하지 않습니다. QT 위젯에서 패치를 드래그하려고하면 두 플롯이 올바르게 렌더링되고 오류 메시지가 표시되지 않습니다.matplotlib PyQT 위젯에서 Funcitoning하지 않는 이벤트 리스너
객체 MCVE :
import matplotlib.patches as patches
class _DragObj:
def __init__(self, ax):
self.parentcanvas = ax.figure.canvas
self.parentax = ax
self.clickpress = self.parentcanvas.mpl_connect('button_press_event', self.on_click)
self.clicked = False
def on_click(self, event):
if event.inaxes != self.parentax: return
self.mousemotion = self.parentcanvas.mpl_connect('motion_notify_event', self.on_motion)
self.clickrelease = self.parentcanvas.mpl_connect('button_release_event', self.on_release)
self.clickx = event.xdata
self.clicky = event.ydata
self.clicked = True
def on_release(self, event):
self.clicked = False
self.disconnect()
def disconnect(self):
self.parentcanvas.mpl_disconnect(self.mousemotion)
self.parentcanvas.mpl_disconnect(self.clickrelease)
self.parentcanvas.draw()
def stopdrag(self):
self.myobj.set_url('')
self.parentcanvas.mpl_disconnect(self.clickpress)
class _DragPatch(_DragObj):
def __init__(self, ax, xy):
super().__init__(ax)
self.oldxy = xy
def on_motion(self, event):
if not self.clicked: return
if event.inaxes != self.parentax: return
oldx, oldy = self.oldxy
dx = event.xdata - self.clickx
dy = event.ydata - self.clicky
newxy = [oldx + dx, oldy + dy]
self.myobj.xy = newxy
self.parentcanvas.draw()
def on_release(self, event):
self.clicked = False
self.oldxy = self.myobj.xy
self.disconnect()
class DragRectangle(_DragPatch):
def __init__(self, ax, xy, width, height, angle=0.0, **kwargs):
self.myobj = patches.Rectangle(xy, width, height, angle, **kwargs)
ax.add_artist(self.myobj)
super().__init__(ax, xy)
작용하기 matplotlib 예 :
import minidrag
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
rect = minidrag.DragRectangle(ax, (0, 0), 2, 1)
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
plt.show()
비 기능적 PyQt는 예 :
import sys
from PyQt5 import QtWidgets as QtW
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import minidrag
class windowGUI(QtW.QDialog):
def __init__(self):
super().__init__()
# Set up figure
width_px = 800
height_px = 600
rect = QtW.QDesktopWidget().availableGeometry()
screenrez = (rect.width(), rect.height())
left_px = (screenrez[0] - width_px)/2
top_px = (screenrez[1] - height_px)/2
self.setGeometry(left_px, top_px, width_px, height_px)
self.canvas = PlotCanvas()
layout = QtW.QVBoxLayout()
layout.addWidget(NavigationToolbar(self.canvas, self))
layout.addWidget(self.canvas)
self.setLayout(layout)
class PlotCanvas(FigureCanvas):
def __init__(self):
fig = Figure(frameon=False)
super().__init__(fig)
super().setSizePolicy(QtW.QSizePolicy.Expanding, QtW.QSizePolicy.Expanding)
super().updateGeometry()
ax = fig.add_subplot(111)
rect = minidrag.DragRectangle(ax, (0, 0), 2, 1)
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
app = QtW.QApplication(sys.argv)
window = windowGUI()
window.show()
sys.exit(app.exec_())
내가 파이썬 3.6.0를 사용하고,하기 matplotlib (2.0 .0), PyQt5 (5.8)
무엇이 누락 되었습니까?
당신이 구현하는 시도 되세요'데프 dragEnterEvent (자체 이벤트) event.acceptProposedAction()'모든 _embedding_'QWidget'에 대해? 그렇지 않으면 이벤트가 내장 된 위젯에 전파 될 수 없습니다. Btw 당신은'dropEvent'에 대해서도 똑같이해야 할 수도 있습니다. [QWidget.dragEnterEvent] (http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html#dragEnterEvent)를 참조하십시오. –
나는 내가 이해할 지 모르겠다. matplotlib의 표준 이벤트 기능 (마우스 오버 좌표 디스플레이, 패닝/확대/축소 등)은 위젯의 이벤트를 재정의 할 필요없이 올바르게 작동합니다. 왜 다른가? – excaza
AFAIK 끌기 이벤트는 기본적으로 무시되므로 아마도 [setAcceptDrops (True)'] (http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html#setAcceptDrops)를 설정하는 것만으로 충분할 것입니다 (최소한 해당 속성은 기본적으로'False'입니다; C++ 문서] (http://doc.qt.io/qt-5/qwidget.html#acceptDrops-prop)). 드래그 앤 드롭이 Qt 내에서 어떻게 작동하는지에 대한 더 자세한 정보는 [C++ drag & drop docs] (http://doc.qt.io/qt-5/dnd.html)에서도 읽을 수 있습니다 (pyqt 참조는 때때로 더 구체적인 주제에 관해서는 약간 희소 함). –