У меня возникли проблемы с попыткой понять, как отобразить меню там, где находится его родительский элемент, с помощью TPython

Программы на Python
Ответить
Anonymous
 У меня возникли проблемы с попыткой понять, как отобразить меню там, где находится его родительский элемент, с помощью T

Сообщение Anonymous »

Может ли кто-нибудь помочь мне понять, как сделать так, чтобы виджет меню появлялся там, где расположена кнопка?
Я работаю над приложением, которое загружает видео из Интернета с помощью yt-dlp (я не поощряю пиратство, просто хочу прояснить это). Каждая загрузка внутри списка имеет кнопку, открывающую меню. Однако каждый раз, когда я нажимаю эту кнопку, меню открывается в верхнем левом углу экрана, а не там, где находится кнопка.

Код: Выделить всё

from tkinter import *
from tkinter import ttk

from swiperdl.utils.gui import get_icon, load_image_tkinter

class DownloadItem(ttk.Frame):
"""Class for a displayed download item"""
def __init__(self, master=None, title: str = "", dl_path: str = "", url: str = "", status: str = "", progress: dict = None) -> None:
super().__init__(master)

self.title = StringVar()
self.title.set(title)
self.window_coords: dict = {
"x": 0,
"y": 0
}
self.dl_path = dl_path
self.url = url
self.status = status
self.status_text = StringVar()
self.progress_bytes = IntVar()
self.progress_bytes.set(progress.get("bytes", 0))
self.progress_total = progress.get("total", 100)

self.setup_widgets()

def setup_widgets(self) -> None:
self.title_display = ttk.Label(self, textvariable=self.title)
self.status_display = ttk.Label(self, textvariable=self.status_text)
self.progress_bar = ttk.Progressbar(self, orient="horizontal", length=200, mode="determinate", variable=self.progress_bytes, maximum=self.progress_total)
self.info_button = ttk.Button(self, text="...", command=self.open_info_menu)
self.title_display.pack(side="left", anchor="center", padx=50)
self.status_display.pack(side="left", anchor="center", padx=50)
self.progress_bar.pack(side="left", anchor="center", padx=50)
self.info_button.pack(side="right", anchor="center", padx=50)
self.info_menu = Menu(self.info_button)
self.info_menu.add_command(label="Open with associated application")
self.info_menu.add_command(label="Open download link")
self.info_menu.add_command(label="View output")
self.info_menu.add_command(label="Cancel download")
self.info_menu.add_command(label="Remove from list")

def open_info_menu(self) -> None:
self.info_menu.tk_popup(self.window_coords["x"], self.window_coords["y"])

class MainWindow(Tk):
"""Class for the main window GUI."""
def __init__(self) -> None:
super().__init__()
# Basic window settings
self.title("SwiperDL")
self.icon = load_image_tkinter(get_icon("swiperdl"))
self.wm_iconphoto(True, self.icon)
self.geometry("1480x800")
self.protocol("WM_DELETE_WINDOW", self.close)

# A list of predefined formats to choose from.
self.formats = [
...
]

# A list of downloads to be displayed.
# Just a sample, I won't use this in production.
self.downloads = [
{
"title": "Me at the zoo.mp4",
"dl_path": "/home//Me at the zoo.mp4",
"status": "downloading",
"url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
"progress": {
"bytes": 0,
"total": 100
}
}
]

self.detect_clipboard = StringVar() # Configuration for automatic clipboard detection.
self.selected_format = StringVar() # Holds the selected format to download using the backend.
self.selected_format.set(self.formats[0])

# Start creating the widgets
self.create_menu()
self.create_widgets()

def create_widgets(self) ->  None:
self.main_frame = ttk.Frame(self)
self.main_frame.pack(anchor="center", side="top", expand=True, fill="both")

self.toolbar = ttk.Frame(self.main_frame)
self.toolbar.pack(side="top", anchor="n", fill="x", ipady=20)
self.toolbar_left_spacer = ttk.Frame(self.toolbar, height=1)
self.toolbar_left_spacer.pack(side="left", anchor="w", expand=True, fill="y")
self.url_bar = ttk.Frame(self.toolbar, height=125)
self.clipboard_toggle_icon = load_image_tkinter(get_icon("clipboard_enabled"))
self.clipboard_toggle = ttk.Button(self.url_bar, text="Toggle Clipboard", image=self.clipboard_toggle_icon)
self.clipboard_toggle.pack(side="left", anchor="w")
self.default_text = StringVar()
self.default_text.set("Enter URL or search query here")
self.url_field = ttk.Entry(self.url_bar, textvariable=self.default_text)
self.url_field.pack(side="right", anchor="e", fill="x", padx=50, ipadx=86)
self.url_bar.pack(side="left", anchor="center", expand=False, ipadx=10)

self.basic_config_frame = ttk.Frame(self.toolbar, height=125)
self.basic_config_frame.pack(side="left", anchor="e")
self.format_selection_box = ttk.Combobox(self.basic_config_frame, textvariable=self.selected_format, value=self.formats)
self.format_selection_box.pack(side="left", anchor="w", padx=25)
self.cookies_icon = load_image_tkinter(get_icon("cookies"))
self.cookies_from_browser_toggle = ttk.Button(self.basic_config_frame, text="Use browser cookies", image=self.cookies_icon)
self.cookies_from_browser_toggle.pack(side="left", anchor="e")
self.metadata_icon = load_image_tkinter(get_icon("metadata_enabled"))
self.extract_metadata_toggle = ttk.Button(self.basic_config_frame, text="Extract metadata", image=self.metadata_icon)
self.extract_metadata_toggle.pack(side="left", anchor="e")
self.settings_icon = load_image_tkinter(get_icon("settings"))
self.toolbar_settings_shortcut = ttk.Button(self.basic_config_frame, text="Open settings", image=self.settings_icon)
self.toolbar_settings_shortcut.pack(side="left", anchor="e")
self.toolbar_right_spacer = ttk.Frame(self.toolbar, height=1)
self.toolbar_right_spacer.pack(side="right", anchor="e", expand=True, fill="y")
self.toolbar_separator = ttk.Separator(self.main_frame, orient="horizontal")
self.toolbar_separator.pack(side="top", anchor="n", fill="x")

self.centre_frame = ttk.Frame(self.main_frame)
self.centre_frame.pack(side="top", anchor="center", expand=True, fill="both")
self.download_view_frame = ttk.Frame(self.centre_frame)
self.download_view_frame.pack(side="top", anchor="center", expand=True, fill="both")
for dl in self.downloads:
self.download = DownloadItem(self.download_view_frame, dl.get("title", ""), dl.get("dl_path", ""), dl.get("url", ""), dl.get("status", ""), dl.get("progress", {"bytes": 0, "total": 0}))
self.download.pack(side="top", anchor="n", fill="x")

def create_menu(self) ->  None:
# This is to make sure the menu stays in place.
self.option_add("*tearOff", FALSE)

self.menubar = Menu()
self['menu'] = self.menubar

# Menu for doing stuff with the program
self.appmenu = Menu(self.menubar)
self.appmenu.add_command(label="Add download")
self.appmenu.add_checkbutton(label="Clipboard detection", variable=self.detect_clipboard,
onvalue=1, offvalue=0)
self.appmenu.add_separator()
self.appmenu.add_command(label="Open settings")
self.appmenu.add_separator()
self.appmenu.add_command(label="Quit", command=self.close)
self.menubar.add_cascade(label="SwiperDL", menu=self.appmenu)

# Menu for getting information about the program
self.aboutmenu = Menu(self.menubar)
self.aboutmenu.add_command(label="About SwiperDL")
self.aboutmenu.add_separator()
self.aboutmenu.add_command(label="Support")
self.aboutmenu.add_command(label="Website")
self.aboutmenu.add_command(label="GitHub")
self.aboutmenu.add_command(label="PyPI.org")
self.menubar.add_cascade(label="About", menu=self.aboutmenu)

def open(self) -> None:
self.mainloop()

def close(self) -> None:
self.destroy()
Если бы кто-нибудь мог дать мне какой-нибудь совет, я был бы очень признателен! :)
Спасибо

Подробнее здесь: https://stackoverflow.com/questions/798 ... re-its-par
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»