LoginSignup
1
3

More than 3 years have passed since last update.

Tkinter 相互関連があるCallbackをテストする

Posted at

Hex SpinBoxとBin Editorを相互に操作させる

やりたい事

hextobin.png
あっちを変えれば、こっちも変わる こっちを変えれば あっちも変わる
GUIを相互で操作させるのはちょっと面倒?

やった事

互いのハンドラにコールバック関数を登録させることで
お互いの変更を連絡できるようにしてみました。
もっと素直な実装方法があるかもしれませんが、先ずは相互動作ができました。

hextobin2.png

def callback(i): #コールバック関数の生成 それぞれのボックスに値を設定
hx.set(i)
be.set(i)

hx.setCallback(callback) #HexSpinboxにハンドラ登録 変更があった段階で callbackを呼出し
be.setCallback(callback) #BinEditorにハンドラ登録 変更があった段階で callbackを呼出し

MultiBinEditor.py
import tkinter as tk

class HexSpinbox(tk.Spinbox):
    def __init__(self, *args, **kwargs):
        self.var = tk.StringVar()
        self.bytenum = kwargs.pop('bytenum', 1)
        self.add_callback = None
        max_val = 0x1<<(self.bytenum*8)
        super().__init__(*args, **kwargs, textvariable=self.var, from_=0,to=max_val,
                         increment=1, command=self.callback )

    def set(self, val):
        s = "0x{:0%dx}" % (self.bytenum*2)
        self.var.set(s.format(int(val)))

    def get(self):
        hstr = super().get()
        return int(hstr, 16)

    def callback(self):
        val = super().get()
        self.set(val)
        self.add_callback(val) if self.add_callback != None else None

    def setCallback(self, func):
        self.add_callback = func

class BinEditFrame(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.val = 0x00
        self.bits = []
        self.add_callback = None
        for i in range(8):
            btn = tk.Button(self,text=str(i), relief='raised', command=self.callback(i))
            btn.pack(sid='right')
            self.bits.append(btn)

    def callback(self, i):
        def push():
            self.val ^= (1<<i)
            self.redraw()
            self.add_callback(self.val) if self.add_callback != None else None
        return push

    def redraw(self):
        #All Button Delete
        for bit in self.bits:
            bit.destroy()
        self.bits.clear()

        #All Button ReCreate
        for i in range(8):
            if (self.val & (1<<i) > 0):
                btn = tk.Button(self,text=str(i), relief='sunken',
                                command=self.callback(i) )
            else:
                btn = tk.Button(self,text=str(i), relief='raised',
                                command=self.callback(i) )
            btn.pack(sid='right')
            self.bits.append(btn)


    def setCallback(self, func):
        self.add_callback = func

    def set(self, val):
        self.val = int(val)
        self.redraw()

if __name__ == "__main__":
    print("BinHexEditor")
    win = tk.Tk()
    hx = HexSpinbox(win)
    hx.pack(side=tk.LEFT)
    be = BinEditFrame(win)
    be.pack(side=tk.LEFT)

    def callback(i):
        hx.set(i)
        be.set(i)

    hx.setCallback(callback)
    be.setCallback(callback)

    win.mainloop()
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3