When I run the following test program using the Python interpreter from the MacOS Terminal, it works as expected. When I Cython it and create an executable using PyInstaller, and run it from the Terminal, the application menu bar becomes unclickable. An equivalent program created using the same process on Windows also works correctly. I'm using Python 3.8.2, Cython 3.0.0, PyInstaller 5.13.0.
This problem happens whether I create a single-file or multiple-files executable; when running as a .app file, the menus aren't even present (that is, I see the Finder menus).
For reference, I used some techniques suggested in the documentation cited in this article: Tkinter Menubars doesn't show up on Mac OS
Any ideas? Thank you.
UPDATE: It appears that if I click away from this app onto another part of the screen, and then click back, the menus become enabled. However I thought they should be enabled from the start. The issue with menus not appearing at all when using a .app file isn't yet resolved.
import tkinter as tk
from tkinter import *
import sys
import tkinter.messagebox as mb
import os.path
def show_dialog(e=None, title='Just some dialog'):
dlog = tk.Toplevel(root)
dlog.geometry('300x75')
dlog.title(title)
dlog.bind('<Escape>', lambda e:dlog.destroy())
dlog.focus_set()
def showinfo(e=None):
my_path = os.path.dirname(os.path.abspath(__file__))
mb.showinfo('Test', my_path)
def create_menus():
menu_bar = Menu(root)
appmenu = Menu(menu_bar, name="apple")
menu_bar.add_cascade(menu=appmenu)
appmenu.add_command(label="About Me", command=showinfo)
appmenu.add_separator()
global file_menu
global edit_menu
file_menu = Menu(menu_bar, tearoff=0)
edit_menu = Menu(menu_bar, tearoff=0)
window_menu = Menu(menu_bar, name="window")
menu_bar.add_cascade(menu=window_menu, label="Window")
file_menu.add_command(
label='Open...',
command=lambda:show_dialog(title='Open'),
accelerator="Command+O"
)
file_menu.add_command(
label='Exit',
command=sys.exit,
accelerator="Command+Q"
)
menu_bar.add_cascade(
label="File",
menu=file_menu,
underline=0
)
edit_menu.add_command(
label='Find...',
command=lambda:show_dialog(title='Find'),
accelerator="Command+F"
)
menu_bar.add_cascade(
label="Edit",
menu=edit_menu,
underline=0
)
root['menu'] = menu_bar
def main():
global root
root = tk.Tk()
root.title("Simple Editor")
create_menus()
input_text = tk.Text(root, height=10, width=30 )
input_text.pack(expand=True, fill=tk.BOTH)
root.bind('<Command-o>', lambda e:show_dialog(title='Open'))
root.bind('<Command-f>', lambda e:show_dialog(title='Find'))
root.bind('<Command-q>', lambda e:sys.exit)
root.bind('<Command-i>', showinfo)
root.mainloop()
if __name__ == "__main__":
main()
Solved the problem of the menus not appearing when the .app was run. The Info.plist file generated by PyInstaller had the LSBackgroundOnly
key set to true
; resetting it to false
made the menus available.
The problem with needing to click outside the app to activate the menus was resolved with an upgrade of the Python version.