Динамически обновлять и передавать атрибут класса из одного класса в другой - PullRequest
0 голосов
/ 03 июня 2018

У меня есть класс A, который содержит холст matplotlib.Этот холст кликабелен, т.е. я нажимаю на график, это вызывает функцию, которая сохраняет event.x = self.x.У меня есть другой класс B, который должен получать атрибуты от класса A каждый раз, когда они меняются .Я видел шаблон наблюдателя в этом посте Как вызвать функцию при изменении значения? , и я думаю, что это может быть тем, что мне нужно, но я не смог заставить его работать (см. Код ниже).

Оба класса находятся в двух кадрах tkk, но я думаю, что это не имеет отношения к проблеме.

Ясно, что в этом минимальном примере я хотел бы передать plotFrame.x, plotFrame.y в класс WorkFrame().Каждый раз, когда я нажимаю на график, я хотел бы видеть новые значения, всплывающие в маленьких ярлыках справа!

import Tkinter as tk
import ttk

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2TkAgg)

import matplotlib.pyplot as plt
import numpy as np 

class Frame_examples_program():
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Amazing GUI 5000")
        self.create_widgets()


    def create_widgets(self):
        self.window['padx'] = 10
        self.window['pady'] = 10

        # - - - - - - - - - - - - - - - - - - - - -
        # Frame
        frame1 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame1.grid(row=0, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)

        frame2 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame2.grid(row=1, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)        
        self.plotFrame = self.PlotFrame(frame1, frame2)

        frame3 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame3.grid(row=2, column=2, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)   

        self.workFrame = self.WorkFrame(frame3, self.plotFrame)

    class PlotFrame():
        # The plot
        def __init__(self, parent1, parent2):
            self.parent1 = parent1
            self.parent2 = parent2
            self.observers = []
            self.x = 0
            self.y = 0
            canvas = self.plot()
            self.plot_toolbar(canvas)

        def plot(self):
            # the actual plot
            fig, ax = plt.subplots()
            plt.imshow(np.ones((100,100)),picker=True)
            canvas = FigureCanvasTkAgg(fig, self.parent1)
            canvas.mpl_connect('button_press_event', self.onclick)
            return(canvas)

        def plot_toolbar(self, canvas):
            # the tool bar to the plot
            toolbar = NavigationToolbar2TkAgg(canvas, self.parent2)
            toolbar.update()
            canvas.get_tk_widget().grid(row=1, column=1)
            canvas.draw()

        def onclick(self, event):
            # the devilish thing that does nothing!
            self.x = event.x
            self.y = event.y
            self.position()

        @property
        def position(self):
            return(self.x,self.y)

        @position.setter
        def position(self, x, y):
            self.x = x
            self.y = y
            for callback in self.observers:
                self.observers.append(callback)

        def bind_to(self, callback):
            self.observers.append(callback)

    class WorkFrame():
        def __init__(self, parent, plot_frame):
            self.parent =  parent
            self.x = 0
            self.y = 0
            self.plot_frame = plot_frame
            self.plot_frame.bind_to(self.update_position)
            self.display()


        def update_position(self, x, y):
            self.x = x
            self.y = y

        def display(self):
            l_x = tk.Label(self.parent, text ='Xposition: ' + str(self.x))
            l_y = tk.Label(self.parent, text ='Yposition: ' + str(self.y))
            l_x.grid(row = 0,  column=0)
            l_y.grid(row = 0,  column=1)



# Create the entire GUI program
program = Frame_examples_program()

# Start the GUI event loop
program.window.mainloop()

Возникает исключение:

File "test_xy_positions.py", line 65, in onclick
    self.position()
TypeError: 'tuple' object is not callable

Что относитсяна то, что я возвращаю кортеж (self.x,self.y), position(self).

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Я работаю с python3 и изменил импорт для работы с вашим исходным примером, но это прекрасно работает для меня, дайте мне знать, как это работает для вас.Я пытался прокомментировать все места, которые я изменил, но, возможно, пропустил одно:

import Tkinter as tk
import ttk

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2TkAgg)

import matplotlib.pyplot as plt
import numpy as np

class Frame_examples_program(object):
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Amazing GUI 5000")
        self.create_widgets()


    def create_widgets(self):
        self.window['padx'] = 10
        self.window['pady'] = 10

        # - - - - - - - - - - - - - - - - - - - - -
        # Frame
        frame1 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame1.grid(row=0, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)

        frame2 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame2.grid(row=1, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)
        self.plotFrame = self.PlotFrame(frame1, frame2)

        frame3 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame3.grid(row=2, column=2, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)

        self.workFrame = self.WorkFrame(frame3, self.plotFrame)

    class PlotFrame(object):
        # The plot
        def __init__(self, parent1, parent2):
            self.parent1 = parent1
            self.parent2 = parent2
            self.observers = []
            self.x = 0
            self.y = 0
            canvas = self.plot()
            self.plot_toolbar(canvas)

        def plot(self):
            # the actual plot
            fig, ax = plt.subplots()
            plt.imshow(np.ones((100, 100)), picker=True)
            canvas = FigureCanvasTkAgg(fig, self.parent1)
            canvas.mpl_connect('button_press_event', self.onclick)
            return canvas

        def plot_toolbar(self, canvas):
            # the tool bar to the plot
            toolbar = NavigationToolbar2TkAgg(canvas, self.parent2)
            toolbar.update()
            canvas.get_tk_widget().grid(row=1, column=1)
            canvas.draw()

        def onclick(self, event):
            # Here I am now setting the position
            self.set_new_position(event.x, event.y)

        def set_new_position(self, x, y):
            self.x = x
            self.y = y
            for callback in self.observers:
                # Here I am now calling the methods that have been captured so far
                # and passing them the arguments of x, y to do with as they please
                callback(self.x, self.y)

        def bind_to(self, callback):
            self.observers.append(callback)

    class WorkFrame():
        def __init__(self, parent, plot_frame):
            self.parent =  parent
            self.x = 0
            self.y = 0
            self.plot_frame = plot_frame
            self.plot_frame.bind_to(self.update_position)
            self.display()

        def update_position(self, x, y):
            self.x = x
            self.y = y
            # Here I have added the requirement to run the display code again
            # after an update
            self.display()

        def display(self):
            l_x = tk.Label(self.parent, text ='Xposition: ' + str(self.x))
            l_y = tk.Label(self.parent, text ='Yposition: ' + str(self.y))
            l_x.grid(row = 0,  column=0)
            l_y.grid(row = 0,  column=1)



# Create the entire GUI program
program = Frame_examples_program()

# Start the GUI event loop
program.window.mainloop()
0 голосов
/ 03 июня 2018

Просто выстрел из бедра, вы пытались удалить декоратор @property сверху методом position?Тогда функция будет вызываться вместо свойства, которое не может быть вызвано.

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