matplotlib - вы можете установить приоритет, если есть несколько обработчиков событий? - PullRequest
0 голосов
/ 12 февраля 2019

Я создаю инструмент с PyQt5, который позволит пользователям перетаскивать прямоугольники по клику в matplotlib_widget.Проблема в том, что я хочу знать, по какому прямоугольнику щелкнули.

Так как мой холст и мой прямоугольник - это два разных класса, мне трудно правильно общаться между ними.Чтобы решить эту проблему, я добавил обработчик событий в button_click_event холста моего прямоугольника, чтобы записать его положение в файл .txt.С другой стороны, я также подключился к «button_click_event» к своему холсту, который должен прочитать .txt и проверить в ранее сохраненном списке, есть ли позиция.Если это так, значит, именно этот прямоугольник был нажат.

Проблема : обработчик события холста, который читает файл .txt, вызывается перед обработчиком, который его записывает.

Можно ли установить приоритет дляevents of figure.canvas?

Вот минимально работающий пример моей конкретной проблемы.Вы заметите, что я сделал распечатки, когда функция, которую я хочу сделать что-то.Если вы дважды щелкнете мышью и создадите 2 прямоугольника, вы должны заметить, что если щелкнуть прямоугольник 0 после нажатия прямоугольника 1, он скажет, что вы щелкнули прямоугольник 1. Это демонстрация того, что функция «saveInFilie»После этого вызывается файл.

import matplotlib.pyplot as plt
from matplotlib import patches


class DraggableRectangle:
lock = None  # only one can be animated at a time

def __init__(self, rect):
    self.rect = rect
    self.press = None
    self.background = None

def connect(self):
    'connect to all the events we need'
    self.cidpress = self.rect.figure.canvas.mpl_connect(
        'button_press_event', self.on_press)
    self.cidrelease = self.rect.figure.canvas.mpl_connect(
        'button_release_event', self.on_release)

def on_press(self, event):
    'on button press we will see if the mouse is over us and store some data'
    if event.inaxes != self.rect.axes: return
    if DraggableRectangle.lock is not None: return
    contains, attrd = self.rect.contains(event)
    if not contains: return
    print('Held @', self.rect.xy)
    x0, y0 = self.rect.xy
    self.saveInFile(str(self.rect.xy))
    print("click write succeded")
    self.press = x0, y0, event.xdata, event.ydata
    DraggableRectangle.lock = self

    # draw everything but the selected rectangle and store the pixel buffer
    canvas = self.rect.figure.canvas
    axes = self.rect.axes
    self.rect.set_animated(True)
    canvas.draw()
    self.background = canvas.copy_from_bbox(self.rect.axes.bbox)

    # now redraw just the rectangle
    axes.draw_artist(self.rect)

    # and blit just the redrawn area
    canvas.blit(axes.bbox)

def on_release(self, event):
    'on release we reset the press data'
    if DraggableRectangle.lock is not self:
        return

    x0, y0 = self.rect.xy
    self.press = None
    DraggableRectangle.lock = None

    # turn off the rect animation property and reset the background
    self.rect.set_animated(False)
    self.background = None
    self.saveInFile(str(self.rect.xy))
    print("release write succeded\n")
    # redraw the full figure
    self.rect.figure.canvas.draw()
    #print("Realeased @", x0, y0)

def saveInFile(self, drop):
    filename = "pos.txt"
    with open(filename, "w") as file:
        file.write(drop)
        file.close()


class MyFigure:

def __init__(self):
    # Figure initialisation
    self.fig = plt.figure()
    self.axes = self.fig.add_subplot(1, 1, 1)
    self.fig.subplots_adjust(0, 0, 1, 1)
    self.axes.set_frame_on(False)
    self.axes.invert_yaxis()
    self.axes.axis('off')
    self.axes.xaxis.set_visible(False)
    self.axes.yaxis.set_visible(False)

    # Connections
    self.ciddouble = self.fig.canvas.mpl_connect('button_press_event', self.createRectangle)
    self.CheckClick = self.fig.canvas.mpl_connect('button_press_event', self.checkRectangleOnClick)
    self.CheckRelease = self.fig.canvas.mpl_connect('button_release_event', self.checkRectangleOnRelease)

    # Variables
    self.devices = []
    self.drs = []
    self.sensorPixelSize = [50, 50]

def createRectangle(self, event):
    relPosX = event.x / (self.fig.get_size_inches()[0] * self.fig.dpi)
    relPosY = 1 - (event.y / (self.fig.get_size_inches()[1] * self.fig.dpi))
    relSizeX = self.sensorPixelSize[0] / (self.fig.get_size_inches()[0] * self.fig.dpi)
    relSizeY = self.sensorPixelSize[1] / (self.fig.get_size_inches()[1] * self.fig.dpi)
    absPoxX = relPosX * (self.fig.get_size_inches()[0] * self.fig.dpi)
    absPosY = relPosY * (self.fig.get_size_inches()[1] * self.fig.dpi)
    absSizeX = self.sensorPixelSize[0]
    absSizeY = self.sensorPixelSize[1]

    if event.dblclick and event.button == 1:

        rect = self.axes.add_artist(
            patches.Rectangle((relPosX, relPosY), relSizeX, relSizeY, edgecolor='black', facecolor='black',
                              fill=True))
        dr = DraggableRectangle(rect)
        dr.connect()
        print(dr.rect.xy)
        self.drs.append(dr)
        self.fig.canvas.draw()
        local = ["", "", (relPosX, relPosY), relSizeX, relSizeY, (absPoxX, absPosY), absSizeX, absSizeY]
        self.devices.append(local)

def checkRectangleOnClick(self, event):
    filename = "pos.txt"
    with open(filename, "r") as file:
        varia = file.read()
        file.flush()

    for i in range(len(self.devices)):
        if str(varia) == str(self.devices[i][2]):
            print("Clicked rectangle #%i" % i)
            self.clickedIndex = i

        else:
            self.clickedIndex = None

def checkRectangleOnRelease(self, event):
    filename = "pos.txt"
    with open(filename, "r") as file:
        varia = file.read()
        file.flush()

    for i in range(len(self.devices)):
        if str(varia) == str(self.devices[i][2]):
            print("Realeased rectangle #%i" % i)
            self.clickedIndex = i

        else:
            self.clickedIndex = None


fig = MyFigure()
plt.show()

1 Ответ

0 голосов
/ 12 февраля 2019

Решил этот вопрос.Чтобы установить приоритет для обработчиков событий, я вызвал только одну функцию из события.С тех пор, когда обработчик завершает свое назначение, он вызывает другой обработчик, который больше не подключен, а затем второй вызывает третий, и т. Д.

Я добавил в класс DraggableRectangle входные данные myличный класс холста «MyFigure».Таким образом, теперь я могу вызывать функции MyFigure из DraggableRectangle.Итак, в On_Click, после функции saveInFile, я просто вызываю функцию checkRectangleOnClick напрямую, а затем checkRectangleOnRelease.Я отключил эту функцию от 'button_click_event'.Больше никаких проблем, все происходит, когда это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...