2017-03-26 13 views
0

私はかなりpythonとtkinterの新機能です。私は私のスキルを構築するために努力していますので、私はラズベリーパイをプログラムすることができます。私の現在の問題は私に悩まされました:私は、エントリフィールドをクリックすると、ダイアログボックス(画面キーボード)を表示したい。呼び出し可能なTkinterのToplevelポップアップダイアログ

私はこれを実現するためにいくつかの方法を試しました。キーボードを最初に表示するか、まったく表示しないようにすることができます。しかし、クリックイベントではありません。私は、キーボードクラスがそれ自身で作業していることを知っているので、私はそれをどのように呼び出すのか(popout.pyの29行目)でなければなりません。

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "E:\Programs\Python3\lib\tkinter\__init__.py", line 1533, in __call__ 
    return self.func(*args) 
TypeError: keyboard() takes from 1 to 3 positional arguments but 4 were given 

または

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "E:\Programs\Python3\lib\tkinter\__init__.py", line 1533, in __call__ 
    return self.func(*args) 
TypeError: 'Keyboard' object is not callable 

を私は本当にこれらの例外を取得するために何が起こっているのか理解していない:私は、私が実装しようとする方法に基づいて2つのエラーメッセージのいずれかを取得します。以下は私のコードです:

Popup.py

import tkinter as tk 
import keyboard as k 
# 
from time import sleep 
# needs Python25 or higher 
from functools import partial 

class Application(tk.Frame): 
    def __init__(self, master=None): 
     super().__init__(master) 
     self.pack() 
     #variable to update counter text 
     self.num = tk.StringVar() 
     self.create_widgets() 

    def create_widgets(self): 
     # button to start counting 
     self.startbtn = tk.Button(self) 
     self.startbtn["text"] = "Start counting\n(Click)" 
     self.startbtn["command"] = self.counting 
     self.startbtn.pack(side="top") 

     #Label to view counter 
     self.counter = tk.Label(self, textvariable=self.num) 
     self.counter.pack() 

     #Entry box 
     self.e = tk.StringVar() 
     self.entry = tk.Entry(self, textvariable=self.e) 
     #launch_kbd = partial(self.keyboard, "MyKeyboard", self.e) 
     #self.entry.bind("<Button-1>", launch_kbd) 
     self.entry.bind("<Button-1>", k.Keyboard(self, "MyKeyboard", self.e)) 
     self.entry.pack() 

     #Exit 
     self.quit = tk.Button(self, text="Quit", fg="red", command=root.destroy) 
     self.quit.pack(side="bottom") 

    #count for 10 seconds 
    def counting(self): 
     self.startbtn["state"] = "disabled" 
     root.update() 
     #loop from 1-10 
     for x in range(1,11): 
      self.num.set(str(x)) #update the label's variable 
      root.update() #important to make changes visible 
      sleep(1) #sleep for 1 second 
     #Clear text when done 
     self.num.set("") 
     self.startbtn["state"] = "enabled" 
     root.update() 
    #def keyboard(self, title=None, target=None): 
    # k.Keyboard(self, title, target) 
''' 
This starts the root window 
''' 
root = tk.Tk() 
root.title("myGUI") 
root.geometry("200x100") 

app = Application(master=root) 
app.mainloop() 

keyboard.py

''' 
# Built with examples from: 
- http://effbot.org/tkinterbook/tkinter-dialog-windows.htm 
- https://www.daniweb.com/programming/software-development/threads/300867/on-screen-keyboards-in-tkinter 

# Desc: Creates a pop-up on-screen Keyboard for text entry. 
     Writes entry to Target upon pressing Enter. 
''' 
# use tkinter for GUI application 
import tkinter as tk 

# used for button click 
from functools import partial 

class Keyboard(tk.Toplevel): 
    def __init__(self, parent, title=None, target=None): 

     tk.Toplevel.__init__(self, parent, bg='black') 
     # associate this window with a parent window 
     self.transient(parent) 

     if title: 
      self.title(title) 
     if target: 
      self.target = target 
      self.init_txt = target.get() 
     self.parent = parent 

     body = tk.Frame(self) 
     self.body(body) 
     body.pack(padx=5, pady=5) 

     self.buttonbox() 

     #make the dialog modal 
     self.grab_set() 

     # safely handle WM_DELETE_WINDOW event 
     self.protocol("WM_DELETE_WINDOW", self.close) 

     # position the dialog relative to the parent window 
     self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50)) 

     # Hold captive control until window is closed 
     # prevent parent from accepting input while window is open 
     self.wait_window(self) 

    # END Init 

    def body(self, master): 
     #Text input at the top 
     self.txt = tk.StringVar() 
     self.txt.set(self.init_txt) 
     self.tx = tk.Entry(self, bg='black', fg='white', insertbackground='gray', insertwidth=2, textvariable=self.txt) 
     self.tx.focus_set() 
     self.tx.pack(fill="x", padx=5, pady=5) 

    def buttonbox(self): 
     # create a frame for the keypad buttons 
     bf = tk.Frame(self) 
     bf.pack() 

     # button layout 
     btn_list = [ 
     'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 
     'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', 
     'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '?', 
     'Num', '+', '-', ' ', ' ', ' ', '<-', '->', 'BKS', 'ETR', ] 

     # create and position all buttons with a for-loop 
     # r, c used for row, column grid values 
     r = 1 
     c = 0 
     n = 0 
     # list(range()) needed for Python3 
     btn = list(range(len(btn_list))) 

     for label in btn_list: 
      # partial takes care of function and argument 
      cmd = partial(self.click, label) 
      # create the button (and style it) 
      btn[n] = tk.Button(bf, text=label, width=5, height=3, command=cmd, bg='#333333', fg='white', activebackground='#666666', activeforeground='white') 
      # position the button 
      btn[n].grid(row=r, column=c) 
      # increment button index 
      n += 1 
      # update row/column position 
      c += 1 
      if c > 9: 
       c = 0 
       r += 1 

    def click(self, btn): 
     if btn == 'Num': 
      # Switch to number pad 
      pass 
     elif btn == '<-': 
      # Move cursor to the left 1 character 
      self.tx.icursor(self.tx.index('insert')-1) 
     elif btn == '->': 
      # Move cursor to the right 1 character 
      #icursor(index) 
      self.tx.icursor(self.tx.index('insert')+1) 
     elif btn == 'BKS': 
      # truncate entry by 1 character 
      self.tx.delete(self.tx.index('insert')-1) 
     elif btn == 'ETR': 
      # return entered value to the input 
      self.apply() 
      self.close() 
     else: 
      # DEFAULT: append entry with btn 
      self.tx.insert('insert', btn) 

    def close(self, event=None): 

     # put focus back to the parent window 
     self.parent.focus_set() 
     self.destroy() 

    def apply(self): 

     self.target.set(self.tx.get()) 

# if called directly 
if __name__ == "__main__": 
    root = tk.Tk() 
    t = tk.StringVar() 
    k = Keyboard(root, "MyKeyboard", target=t) 
    print(t.get()) 

答えて

0

Button-1イベント関数に引数を渡すためにlambda機能を使用してください。 Popup.pyのライン33上

、変更:

self.entry.bind("<Button-1>", k.Keyboard(self, "MyKeyboard", self.e))

に:

self.entry.bind("<Button-1>", lambda event: k.Keyboard(self, "MyKeyboard", self.e))

また、counting方法下self.startbtn["state"] = "enabled"self.startbtn["state"] = "normal"

なければなりません
関連する問題