2017-10-21 7 views
1

私は、グリッドからボタンをクリックすると色が塗りつぶされる、シンプルなプログラムがあります。すべてのボタンをクリックしなければならないときとは違って、ボタンの上をドラッグしていっぱいになりたいと思っています。これはできますか?tkinter、どのようにボタン間をドラッグできますか?

from tkinter import * 

root=Tk() 

grid= Frame(root) 
grid.pack() 

img0=PhotoImage(file="0.png") 
img1=PhotoImage(file="1.png") 
img2=PhotoImage(file="2.png") 

fill = 1 

class button: 

    def __init__(self, x, y): 

     self.type=0 

     self.but=Button(grid,command=self.change, image=img0, borderwidth=0) 
     self.but.grid(row=y, column=x) 

    def change(self): 

     if self.type==fill: 
      self.but.config(image=img0) 
      self.type=0 
     else: 
      self.but.config(image=eval("img"+str(fill))) 
      self.type=fill 

def create(x,y): 

    grid_buttons = [] 

    for Y in range(y): 
     grid_buttons.append([]) 
     for X in range(x): 
      grid_buttons[Y].append(button(X, Y)) 

create(15,15) 

root.mainloop() 
+0

すべてのボタンを保持し、いずれかのボタンでマウスが押されたかどうかを追跡するコンテナクラスを持つことができます。次に、ボタンはそれぞれ ''イベントにバインドすることができます。マウスを押すと色が変わります。 – anonymoose

+0

申し訳ありませんが、私はそれを働かせることはできません。あなたは時間があれば例を見せてもらえますか? –

答えて

2

ここに1つの方法です:

from tkinter import * 

root=Tk() 

grid= Frame(root) 
grid.pack() 

img0=PhotoImage(file="0.png") 
img1=PhotoImage(file="1.png") 
img2=PhotoImage(file="2.png") 

fill = 1 

class button: 

    def __init__(self, x, y): 

     self.type=0 

     self.but=Button(grid,command=self.change, image=img0, borderwidth=0) 
     self.but.grid(row=y, column=x) 

     #Changed 
     self.already_changed = False 

    def change(self): 
     if self.type==fill: 
      self.but.config(image=img0) 
      self.type=0 
     else: 
      self.but.config(image=eval("img"+str(fill))) #I left this in here, but you should NEVER use eval(). It's unsafe. 
      self.type=fill 

    #Changed 
    def mouse_entered(self): 
     if not self.already_changed: 
      self.change() 
      self.already_changed = True 

    def mouse_up(self): 
     self.already_changed = False 

#Changed 
class Container: 
    def __init__(self, x, y): 
     grid_buttons = [] 

     for Y in range(y): 
      grid_buttons.append([]) 
      for X in range(x): 
       grid_buttons[Y].append(button(X, Y)) 

     self.buttons = grid_buttons 
     grid.bind_all("<Button-1>", self.mouse_down) 
     grid.bind_all("<ButtonRelease-1>", self.mouse_up) 
     grid.bind_all("<B1-Motion>", self.mouse_motion) 
     self.mouse_pressed = False 

    def mouse_down(self, e): 
     self.mouse_pressed = True 

    def mouse_up(self, e): 
     self.mouse_pressed = False 
     for row in self.buttons: 
      for but in row: 
       but.mouse_up() 

    def mouse_motion(self, e): 
     for row in self.buttons: 
      for but in row: 
       if grid.winfo_containing(e.x_root, e.y_root) is but.but: 
        but.mouse_entered() 

container = Container(15,15) 

root.mainloop() 

さて、私はあなたがやったことのいくつかは非常にPythonのスタイルではないことに気づい

はここでおそらく最高ではない私のコードです。ですから、ここではPythonの規約に厳密に従ったバージョンがあります。それは全く異なっていることに注意してください。

from tkinter import * 

root = Tk() 

images = {0: PhotoImage(file="0.png"), 
      1: PhotoImage(file="1.png"), 
      2: PhotoImage(file="2.png")} 

fill = 1 

class MyButton(Button): #Convention is for class names to start with uppercase letters 
    def __init__(self, master): 
     super(MyButton, self).__init__(master, image = images[0], borderwidth = 0) 
     self.type = 0 
     self.already_changed = False 

    def change(self): 
     if self.type == fill: 
      self.type = 0 
     else: 
      self.type = fill 
     self.config(image=images[self.type]) 

    def mouse_entered(self): 
     if not self.already_changed: 
      self.change() 
      self.already_changed = True 

    def mouse_up(self): 
     self.already_changed = False 

class Container(Frame): 
    def __init__(self, master, width, height): 
     super(Container, self).__init__(master) 

     buttons = [] 

     for y in range(height): 
      buttons.append([]) 
      for x in range(width): 
       button = MyButton(self) 
       button.grid(row = x, column = y) 

       buttons[y].append(button) 

     self.buttons = buttons 

     self.bind_all("<Button-1>", self.mouse_down) 
     self.bind_all("<ButtonRelease-1>", self.mouse_up) 
     self.bind_all("<B1-Motion>", self.mouse_motion) 

     self.mouse_pressed = False 

    def mouse_down(self, e): 
     self.update_containing_button(e) 
     self.mouse_pressed = True 

    def mouse_up(self, e): 
     self.mouse_pressed = False 
     for row in self.buttons: 
      for button in row: 
       button.mouse_up() 

    def mouse_motion(self, e): 
     self.update_containing_button(e) 

    def update_containing_button(self, e): 
     for row in self.buttons: 
      for button in row: 
       if self.winfo_containing(e.x_root, e.y_root) is button: 
        button.mouse_entered() 

grid = Container(root, 15, 15) 
grid.pack() 

root.mainloop() 

なぜ両方を投稿するのですか?実際のアプリケーションにもっと多くのコードがあるように見えます(これは良い例です)。コードの残りの部分を動作させるためにコードを書き直すことを強要したくなかったのですが、その逆もありませんでした。 2つのバージョン間

機能の違い:それはより柔軟かつ容易に変更することはなく、グローバル変数のオブジェクト指向の機能を使用するよう

  • 第二のバージョンが変更されています。

  • 第2のバージョンでは、コンテナですべてを処理する代わりに、ボタン自体のバインディングが削除されます。

+0

ありがとうございました。 –

関連する問題