2

我正在尝试使用它,以便可以使用旋转框调整 Tkinter 画布上的多个对象的大小/重新定位,旋转框中的值用作原始坐标的乘数。为了使事情稍微复杂一点,旋转框默认情况下是不可见的,它位于顶层窗口中,按下按钮时可以打开。

总结一下:
我需要使用旋转框值作为乘数(或其他方式)来更改画布上对象的坐标,该乘数本身位于顶层窗口中,并将这些更改“实时”显示在画布上。

对于上下文,我已经包含了负责设置对象等的关键外围代码。

UI模块的基本部分:


import Canvas_1 (module for drawing shapes)

root=Tk()

#root geometry, title set up
#UI then commands set up
canvasBlank=Canvas(root, width... etc) #Blank canvas that is drawn at start
canvasBlank.grid(row... etc)
canvasBlank.bind('Button-3', rightclickcanvas) #Right click function that opens a popup for canvas options
#Other misc commands, I'm using a menubar with drop down options over actual Tk.Buttons
#'New' option in menubar has Command to create objects in UI like:

def createObject():
     Objects=MyObjects(root, width... etc)
     Objects.grid(row... etc) #Same as layout for canvasBlank
     Objects.bind('<Button-3>', rightclickcanvas)
     Objectslist.append(Objects) #Stop garbage disposal and makes sure the canvas displays

-MyObjects 类(在单独的模块中)的形式类似于:

from Coordinate_Generator import * #imports coordinate arrays

class MyObjects(tk.Canvas)
    def __init__(self, master, **kw)
        tk.Canvas.__init__(self, master, **kw)
        self.create_oval(coordinates[0], dimensions[0], fill... etc)
        self.create_oval(coordinates[1], dimensions[1], fill... etc)
#A series of bindings relating to moving objects under mouse clicks

使用任意值“a”确定坐标。我尝试相乘:scaler=[] a=70*scaler[-1]

这种方法似乎也不起作用,如果它起作用了,它也意味着可能会在彼此之间绘制大量的画布,这是我想避免的。我希望这能证明我需要更清楚地尝试和使用的方法。我已经使用给出的建议编写了一些代码,虽然它可能对我正在计划的程序的另一部分有用,但它并没有完全实现我所追求的。所以我拼凑了这个“演示”来说明我正在尝试做的事情。

工作代码(解决方案)

from Tkinter import *
from numpy import *
import Tkinter as tk

scale=1

class Demonstrator:

   def __init__(self, master=None): 
      global full_coordinates, dimensions, scale
      self.master=master
      self.master.title( "Demonstrator 2")
      self.master.grid()
      self.master.rowconfigure(0, weight=1)
      self.master.columnconfigure(0, weight=1)

      self.canvas = Canvas(self.master, width=300, height=300, bg='grey')
      self.canvas.grid(row=0, rowspan=3, column=0)
      self.canvas.create_rectangle(full_coordinates[0],dimensions[0], activefill='blue', fill='red')
      self.canvas.create_rectangle(full_coordinates[1],dimensions[1], activefill='blue', fill='red')
      self.canvas.create_line(full_coordinates[0],full_coordinates[1], fill='red')

      a=9*scale
      Originx=10
      Originy=35
      coordinates1=[]
      coordinates2=[]

      x,y,i=Originx,Originy,1
      x1,y1,i=Originx,Originy,1

      while len(coordinates1)<=25:
       coordinates1.append((x,y))
       coordinates2.append((x1,y1))

       i+=1
       if i % 2 == 0:
            x,y=x+a,y
            x1,y1=x1,y1+a
       else:
            x,y=x,y+a
            x1,y1=x1+a,y1

       full_coordinates=list(set(coordinates1+coordinates2))
       b=array(full_coordinates)
       k=b+10
       dimensions=k.tolist()

class Settings:
    def __init__(self, parent):

        top = self.top = tk.Toplevel(parent)
        self.top.title('Settings')

        self.spinbox_Label= tk.Label(top, text='Change Scale Factor?')
        self.spinbox_Label.grid(row=0, column=0, columnspan=2)

        self.spinbox_Label= tk.Label(top, width=30, text='Scale factor:')
        self.spinbox_Label.grid(row=1, column=0)

        self.spinbox= tk.Spinbox(top, from_=1, to=10, increment=0.1, command=self.change)
        self.spinbox.grid(row=1, column=1)


    def change(self):
        global scale
        scale=float(self.spinbox.get())
        MG=Demonstrator(root) #This just generates a new Demonstrator with original coordinates

def onClick():
    inputDialog = Settings(root)
    root.wait_window(inputDialog.top)

def onClick2():
    print scale

class coords:
    global full_coordinates, dimensions, scale
    print scale
    a=9*scale
    Originx=10
    Originy=35
    coordinates1=[]
    coordinates2=[]

    x,y,i=Originx,Originy,1
    x1,y1,i=Originx,Originy,1

    while len(coordinates1)<=25:
       coordinates1.append((x,y))
       coordinates2.append((x1,y1))

       i+=1
       if i % 2 == 0:
            x,y=x+a,y
            x1,y1=x1,y1+a
       else:
            x,y=x,y+a
            x1,y1=x1+a,y1

       full_coordinates=list(set(coordinates1+coordinates2))
       b=array(full_coordinates)
       k=b+10
       dimensions=k.tolist()    




root=Tk()
root.minsize=(700,700)
root.geometry=('600x600')
MG=Demonstrator(root)
mainButton2 = tk.Button(root, width=20, text='Print "scale"', command=onClick2)
mainButton2.grid(row=1, column=1)
mainButton = tk.Button(root, width=20, text='Settings', command=onClick)
mainButton.grid(row=2, column=1)
root.mainloop()
mainButton2.grid(row=1, column=1)
mainButton = tk.Button(root, width=20, text='Settings', command=onClick)
mainButton.grid(row=2, column=1)
root.mainloop()

问题
使用旋转框更改画布上对象的大小(通过更改坐标)的最佳方法是什么?
我希望这足以提供信息,当然如果需要我可以提供更多信息。我也提前为这个问题的格式道歉,我是新手 :)
(添加的解决方案)任何帮助都会很棒。干杯。
标记

4

1 回答 1

3

解决方案没有什么特别之处。您只需为调整画布项目坐标的微调框定义一个回调(可以通过coords画布的方法完成)。

首先,您可能想要创建一个 dict 来包含每个项目的基本宽度和高度。这个字典的键也可以是与画布项目相关联的标签。例如:

self.base_dimensions = {
    "obj1": (10,10),
    "obj2": (20,20),
    ...
}

接下来,使用这些键作为标签在画布上创建项目。例如:

...
self.canvas.create_rectangle(..., tags=("obj1",))
self.canvas.create_rectangle(..., tags=("obj2",))
...

最后,您可以使用相同的键将微调框小部件保存在字典中(这样您就可以将微调框与画布对象关联起来),并为微调框分配一个回调来调整大小。例如:

self.spinbox = {
    "obj1": tk.Spinbox(..., command=lambda self.do_resize("obj1")),
    "obj2": tk.Spinbox(..., command=lambda self.do_resize("obj2")),
    ...
}

给定一个标签,您的回调可以使用它来获取对 spinbox 小部件的引用并获取它的值,然后使用该标签告诉画布对象要调整哪些项目的大小。例如:

def do_scale(self, tag):
    factor = int(self.spinbox[tag].get())
    (width, height) = self.default[tag]
    (x0,y0,x1,y1) = self.canvas.coords(tag)
    width = factor * width
    height = factor * height
    x1 = x0 + width
    y1 = y0 + height
    self.canvas.coords(tag, x0,y0,x1,y1)

当然,组织数据的方法有很多。我所展示的不是最好的方法,也不是唯一的方法。它甚至可能不适用于您组织代码的方式。无论您选择什么,归结为能够从旋转框中获取值并使用它来调整画布项目的坐标。

于 2012-09-04T14:32:45.420 回答