按下按钮时如何查看菜单? [英] How to view a menu when a button is pressed?

查看:35
本文介绍了按下按钮时如何查看菜单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

跟进这个问题,我试图查看(与用鼠标左键单击时相同)menu,sub1,当一个按钮Test被按下时,但我不能.在以下代码中,按钮似乎反而冻结了 GUI:

Following up on this question, I am trying to view (same as in when clicked with left mouse button) a menu,sub1, when a button,Test, is pressed, but I can't. In the following code button seems to instead freeze the GUI:

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()

我也试过 update_idletasks() 无济于事.我该如何解决这个问题?

I have also tried update_idletasks() to no avail. How can I fix this?

尝试过:

Windows7、Python 3.6、Tkinter 8.6.

Windows7, Python 3.6, Tkinter 8.6.

推荐答案

琐事

这个技巧在 X Window 系统(读为 Unix)中有效,因为Alt-keying"由 tk 自己通过 tk::TraverseToMenu 函数处理,至在这种情况下绑定到 all 绑定标签.

Trivia

This trick works within the X Window System (read as Unix), because "Alt-keying" is handled by tk itself via tk::TraverseToMenu function, wich is binded to the all bind-tag in that case.

在您的情况下,tk 检测到它在 Win 环境中工作,并且仅将 tk::TraverseToMenu 函数绑定到 Menubutton 绑定标签,因为在这种情况下,Alt-keying"由原生 Win wm 处理.

In your case tk detects, that it works in Win environment, and binds tk::TraverseToMenu function only to the Menubutton bind-tag, because in such circumstances "Alt-keying" is handled by native Win wm.

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

What was said is represented by the source code in 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 发送消息,表明按下 Alt 键,并等待 用于另一条消息,其中包含指定的字符作为 ANSI 代码.接收到指定字符后,wm 正在尝试查找要打开的菜单.

Solution

When you press Alt key, Windows sends a message, which signaling that the Alt-key is pressed down, and waits for another message, which contains specified character as ANSI-code. After a specified character is received, wm is trying to find a menu to open.

同时 tk::TraverseToMenu 运行良好 - 尝试传递一个空字符串或任何任意字符作为 char 参数,但找不到菜单.只有当您尝试在 Windows 屋附近的草坪上玩耍时才会出现此问题.

In same time tk::TraverseToMenu works well - try to pass an empty string or any arbitrary char as a char parameter, with wich menu cannot be found. The problem only occurs when you're trying to play on the lawn near the Windows house.

您在这种情况下的最佳选择:SendMessagekeybd_event.

Your best bets in this situation: SendMessage or keybd_event.

所以一个完整的黑客(如@Donal Fellows 所说)是这样的:

So a complete hack (as @Donal Fellows said) is this:

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()

这篇关于按下按钮时如何查看菜单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆