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")),
    ...
}

タグを指定すると、コールバックはそれを使用してスピンボックスウィジェットへの参照を取得し、その値を取得してから、タグを使用してサイズ変更するアイテムをキャンバスオブジェクトに指示できます。例えば:

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 に答える