按下按钮时如何查看菜单?

时间:2017-12-20 18:17:14

标签: python windows tkinter tcl tk

跟进this question,当我按下按钮import pandas as pd names = pd.DataFrame(data={'id_a': ['ben', 'jack', 'jill', 'wilma', 'amir'], 'id_b': ['jack', 'ben', 'amir', 'jill', 'wilma']}) interactions = pd.DataFrame(data={'individual1': ['jill', 'jack', 'wilma', 'amir', 'amir', 'jack', 'jill'], 'individual2': ['jack', 'jill', 'jill', 'jill', 'jack', 'amir', 'amir']}) 时,我正在尝试查看(与鼠标左键单击时相同)菜单sub1,但我不能。在下面的代码按钮似乎冻结了GUI:

Test

我也试过import tkinter as tk root = tk.Tk() menubar = tk.Menu(root) sub1 = tk.Menu(menubar, tearoff=0) sub1.add_command(label="Item 1", command=lambda : print("item 1")) sub1.add_command(label="Item 2", command=lambda : print("item 2")) menubar.add_cascade(menu=sub1, label="Sub1", underline=0) root.config(menu=menubar) def cb(*args): root.tk.call('::tk::TraverseToMenu', root, 'S') tk.Button(root, text="Test", command=cb).pack() root.mainloop() 无济于事。我该如何解决这个问题?

尝试:

  

Windows7,Python 3.6,Tkinter 8.6。

2 个答案:

答案 0 :(得分:1)

Tkinter按钮不应该以这种方式工作; 这就是menubutton的用途。但是,如果您要继续攻击按钮,则需要绑定按钮上的事件而不仅仅是使用命令回调(当按钮被布防时,在按钮上释放鼠标按钮-1时触发;当按下按钮上的鼠标按钮-1时发生布防)。

我真的建议使用menubutton(tk.Menubutton)代替。它对用户来说更容易,因为它设计为看起来就像它会在按下时发布菜单一样。

答案 1 :(得分:1)

琐事

这个技巧在X Window系统中运行(读作Unix),因为“Alt-keying”由tk本身通过tk::TraverseToMenu函数处理,绑定到all在这种情况下绑定标签。

tk检测到的情况下,它在Win环境中有效,并且仅将tk::TraverseToMenu函数绑定到Menubutton绑定标记,因为在这种情况下“Alt -keying“由本地Win wm处理。

所说的内容由menu.tcl中的源代码表示:

if {[tk windowingsystem] eq "x11"} {
    bind all <Alt-KeyPress> {
    tk::TraverseToMenu %W %A
    }

    bind all <F10> {
    tk::FirstMenu %W
    }
} else {
    bind Menubutton <Alt-KeyPress> {
    tk::TraverseToMenu %W %A
    }

    bind Menubutton <F10> {
    tk::FirstMenu %W
    }
}

解决方案

按Alt键,Windows sends a message,表示the Alt-key is pressed down,并等待for another message,其中包含指定字符作为ANSI代码。 收到指定的字符后,wm正试图找到要打开的菜单。

同时tk::TraverseToMenu效果很好 - 尝试将空字符串或任意字符作为char参数传递,无法找到菜单。问题只发生在你试图在Windows房子附近的草坪上玩耍时。

在这种情况下你最好的赌注:SendMessagekeybd_event

完全黑客(如@Donal Fellows所说)是这样的:

import tkinter as tk

root = tk.Tk()

if root._windowingsystem == 'win32':
    import ctypes

    keybd_event = ctypes.windll.user32.keybd_event
    alt_key = 0x12
    key_up = 0x0002

    def traverse_to_menu(key=''):
        if key:
            ansi_key = ord(key.upper())
            #   press alt + key
            keybd_event(alt_key, 0, 0, 0)
            keybd_event(ansi_key, 0, 0, 0)

            #   release alt + key
            keybd_event(ansi_key, 0, key_up, 0)
            keybd_event(alt_key, 0, key_up, 0)

else:
    #   root._windowingsystem == 'x11'
    def traverse_to_menu(key=''):
        root.tk.call('tk::TraverseToMenu', root, key)

menubar = tk.Menu(root)

sub1 = tk.Menu(menubar, tearoff=0)
sub1.add_command(label='Item 1', command=lambda: print('item 1'))
sub1.add_command(label='Item 2', command=lambda: print('item 2'))

menubar.add_cascade(menu=sub1, label='Sub1', underline=0)
root.config(menu=menubar)

traverse_button = tk.Button(root, text='Test', command=lambda: traverse_to_menu('S'))
traverse_button.pack()

root.mainloop()