首页 > 解决方案 > 是否可以更新来自其他类的事件的对象?

问题描述

我有两个用于两个不同对象(mirrorbeam)的类。mirror基于滑块/比例beam绘制,最初基于 amirror的属性绘制,根据其他属性计算和更新mirror。我找到了一种mirror在滑块更改时重绘的方法,但不是beam. 我该怎么办?

mirror在创建时传递一个滑块,然后创建一个属性 ( self.distSlider = distSlider)。我已经尝试传递整个mirrorto beam(因为依赖属性需要一些其他的属性mirror),并且还从这个滑块创建了一个属性,但是更新事件从beam覆盖更新事件mirror。仅将滑块传递给两个对象具有相同的结果。

from tkinter import *

def drawCoords(point, distance):
    mirrorX = distance;
    mirrorY = point.y;
    mirrorLen = 50;
    return [mirrorX, mirrorY - mirrorLen, mirrorX, mirrorY + mirrorLen], mirrorLen;

def midpoint(coords):
    return Point(round((coords[2]+coords[0])/2),round((coords[3]+coords[1])/2));

class GUI:
    def __init__(self,master):
        frame = Frame(master)
        frame.pack(fill = BOTH, expand = 1)
        bg = Canvas(frame, width = 400, height = 400, background = "#F0F0F0", borderwidth = 3, relief = SUNKEN)
        bg.pack(fill = BOTH, expand = 1)
        dist = Scale(frame, from_ = 100, to = 200, orient=HORIZONTAL)
        dist.pack(fill = X, expand = 1)

class Mirror:
    def __init__(self, canvas, distSlider, point):
        self.canvas = canvas
        self.distSlider = distSlider
        distSlider.configure(command=self.updateDistEvent)
        self.distance = distSlider.get()
        self.point = point
        self.coords, self.length = drawCoords(self.point, self.distance)
        self.midpoint = midpoint(self.coords)
        self.id = canvas.create_line(self.coords, width = 2)
    def updateDistEvent(self, event):
        newDistance = self.distSlider.get()
        self.draw(newDistance)
    def draw(self, newDistance):
        self.canvas.delete(self.id)
        self.distance = newDistance
        self.coords, self.length = drawCoords(self.point, self.distance)
        self.midpoint = midpoint(self.coords)
        self.id = self.canvas.create_line(self.coords, width = 2)
        pass

class Point:
    def __init__(self, initx, inity):
        self.x = initx
        self.y = inity

class Beam:
    def __init__(self, canvas, start, end, endObj):
        self.canvas = canvas
        self.start = start
        self.end = end
        self.id = self.canvas.create_line(self.start.x, self.start.y, self.end.x, self.end.y)
    def draw(self):
        pass

root = Tk()
gui_r = GUI(root)
root.update()

mainCanvas = root.children['!frame'].children['!canvas'];
distSlider = root.children['!frame'].children['!scale'];

center = Point(round(mainCanvas.winfo_width()/2),round(mainCanvas.winfo_height()/2))
mirror = Mirror(mainCanvas, distSlider, center)
source = Point(0, center.y)
beam = Beam(mainCanvas, source, mirror.midpoint, mirror)

root.mainloop()

我已经省略了 Beam 类中的任何更新尝试,以避免代码部分更加臃肿,但实际上它只是将mirror对象的参数传递给beam,然后是与 Mirror 类中具有不同坐标的相同方法create_line()

标签: python-3.xtkinter

解决方案


我会在里面创建Mirrorand ,这样他们就可以直接访问and 。并且可以直接访问,因此我可以分配可以访问的函数来更改它,并获取其他它的属性并在.BeamGUICanvasScaleGUIMirrorBeamScaleMirrorBeam

也许这种方式Beam不直接依赖Mirror但更容易创建。

from tkinter import *

def drawCoords(point, distance):
    mirrorX = distance
    mirrorY = point.y
    mirrorLen = 50;
    return [mirrorX, mirrorY - mirrorLen, mirrorX, mirrorY + mirrorLen], mirrorLen;

def midpoint(coords):
    return Point(round((coords[2]+coords[0])/2),round((coords[3]+coords[1])/2));


class GUI:
    def __init__(self,master):
        frame = Frame(master)
        frame.pack(fill = BOTH, expand = 1)

        self.bg = Canvas(frame, width = 400, height = 400, background = "#F0F0F0", borderwidth = 3, relief = SUNKEN)
        self.bg.pack(fill = BOTH, expand = 1)

        self.dist = Scale(frame, from_ = 100, to = 200, orient=HORIZONTAL)
        self.dist.pack(fill = X, expand = 1)

        self.dist.configure(command=self.update_figures)

        root.update()

        self.center = Point(round(self.bg.winfo_width()/2),round(self.bg.winfo_height()/2))
        self.mirror = Mirror(self.bg, self.dist.get(), self.center)

        self.source = Point(0, self.center.y)
        self.beam = Beam(self.bg, self.source, self.mirror.midpoint, self.mirror)

    def update_figures(self, event):
        self.mirror.draw(self.dist.get())
        self.beam.draw(self.mirror.midpoint)


class Mirror:

    def __init__(self, canvas, distance, point):
        self.canvas = canvas
        self.distance = distance
        self.point = point
        self.coords, self.length = drawCoords(self.point, self.distance)
        self.midpoint = midpoint(self.coords)
        self.id = canvas.create_line(self.coords, width=2)

    def draw(self, distance):
        self.distance = distance
        self.coords, self.length = drawCoords(self.point, self.distance)
        self.midpoint = midpoint(self.coords)
        # move in new place without deleting
        self.canvas.coords(self.id, self.coords)


class Point:
    def __init__(self, initx, inity):
        self.x = initx
        self.y = inity


class Beam:

    def __init__(self, canvas, start, end, endObj):
        self.canvas = canvas
        self.start = start
        self.end = end
        self.id = self.canvas.create_line(self.start.x, self.start.y, self.end.x, self.end.y)

    def draw(self, end):
        self.end = end
        # move in new place without deleting
        self.canvas.coords(self.id, (self.start.x, self.start.y, self.end.x, self.end.y))


root = Tk()
gui_r = GUI(root)
root.mainloop()

其他方法只能

  • 放入所以可以Mirror改变镜子GUIScale
  • 放入所以可能会在更改Beam时更改MirrorMirrorBeam

推荐阅读