Меню файла Python Tkinter GUI не отображается, хотя графический интерфейс работает - PullRequest
0 голосов
/ 04 января 2019

Я относительно новичок в Python, и я уверен, что это ошибка в структуре моего кода, но я не могу отобразить меню файлов в моем графическом интерфейсе.Может кто-нибудь сказать мне, какие ошибки я допустил при включении файлового меню?Кроме того, я извиняюсь, но интервал после копирования и вставки немного отклонен.Уровень отступа класса является надлежащим с моей стороны.Я использую Python 3.71

Любые другие комментарии о лучших или более Pythonic способах достижения того, что у меня есть, также приветствуются и заранее благодарны за вашу помощь!

from tkinter import *
from tkinter import ttk
import tkinter.scrolledtext as tkst
import os
import tkinter as tk
from functools import partial
from PIL import Image, ImageTk

class UserGui(tk.Tk):

    def __init__(self,parent):
        self.parent=parent
        self.widgets()

    def widgets(self):
        self.parent.configure(bg='white')
        self.frame1_style = ttk.Style()
        self.frame1_style.configure('My.TFrame', background='white')
        self.frame2_style = ttk.Style()
        self.frame2_style.configure('My2.TFrame',background='white')
        self.parent.title("TGUI")


        self.frame1 = ttk.Frame(self.parent, style='My.TFrame') #Creating Total Window Frame 1
        self.frame1.grid(row=0, column=0, sticky=(N, S, E, W))

        self.frame2 = ttk.Frame(self.parent, width=100, height=20, style='My2.TFrame')
        self.frame2.grid(row=0, column=6, padx=20, pady=5)


        #Menu Creation
        self.menu1 = tk.Menu(self.parent, tearoff=0)
        self.parent.config(menu=self.menu1)
        self.fileMenu = tk.Menu(self.menu1, tearoff=0)
        self.fileMenu.add_command(label="Open", command=self.donothing)
        self.fileMenu.add_command(label="Save", command=self.donothing)

        self.fileMenu.add_separator()

        self.fileMenu.add_command(label="Exit", command=self.parent.quit)
        self.fileMenu.add_cascade(label="File", menu=self.menu1)

        self.editMenu = tk.Menu(self.menu1, tearoff=0)
        self.editMenu.add_command(label="Cut", command=self.donothing)
        self.editMenu.add_command(label="Copy", command=self.donothing)
        self.editMenu.add_command(label="Paste", command=self.donothing)
        self.editMenu.add_cascade(label="Edit", menu=self.menu1)    

    def donothing(self):
        filewin = Toplevel(self.parent)
        button = Button(filewin, text="Do nothing button")
        button.pack()



def main():
    root=tk.Tk()
    ug=UserGui(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Редактировать 1,2,3: я исправил параметр add_cascade для menu с menu=self.menu1, и у меня все еще не отображается меню файла.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Я опубликую этот ответ для полноты, учитывая, что @JasonHarper не скопировал его в формат ответа, и я хочу, чтобы другие могли воспользоваться этой публикацией.

Ключом был объект, который я вызывал add_cascade для дочернего объекта Menu виджета вместо основного Menu объекта виджета с именем self.menu1.Ключ менялся:

self.fileMenu.add_cascade(label="File", menu=self.menu1)

на:

self.menu1.add_cascade(label="File", menu=self.fileMenu)

Это был правильный способ добавления объекта fileMenu Menu к общему количеству Menu объект виджета self.menu1.

0 голосов
/ 04 января 2019

РЕДАКТИРОВАТЬ: Извините, я не заметил тег Python-3 во времени, это все то же самое, за исключением того, что при наследовании вы бы вызывали super().__init__ вместо Frame.__init__ напрямую.Это сделало бы его более похожим на Py3.Тем не менее, это все равно должно работать.

Странно, но нажатие menu.config до функции run сработало для меня - хотя, похоже, все должно работать так, как вы это сделали.

def main():
    root=tk.Tk()
    ug=UserGui(root)
    root.config(menu=ug.fileMenu)
    root.mainloop()

if __name__ == '__main__':
    main()

В противном случае есть некоторые вещи, над которыми вы можете работать, чтобы сделать их более понятными и читаемыми.Так я обычно делаю GUI.Идея состоит в том, чтобы разделить GUI на Frames, которые затем делают схожие вещи.Т.е. ваше приложение могло бы иметь левый и правый фрейм, где правый фрейм содержал бы текстовое поле, а левый фрейм фактически имел бы 2 субкадра - один для имен и выпадающих меню, а другой для кнопок.Таким образом, каждая отдельная функциональность обрабатывается самими фреймами, и не все в одном гигантском классе, элементы в этих фреймах размещаются относительно самой сетки фрейма, а все фреймы размещаются в сетке мэйнфрейма.Это позволяет вам разбивать большой объем кода на модули и помогает с удобством сопровождения.

Подкадры генерируют «глобальные» события (события, мешающие другим кадрам), распространяя их через MainFrame, поэтому все они переносятself.parent - их родительский фрейм, а self.root - основной фрейм.MainFrame также является фреймом, в который я хотел бы поместить что-то вроде self.data, которое само по себе является классом (за пределами Tkinter), который обрабатывает весь ввод / вывод данных и логику, чтобы вы не загромождали логику кода GUI.с расчетами данных и логикой.В идеале класс Data будет обрабатывать ошибки данных, а GUI только тогда должен будет обрабатывать любые ошибки в логике (такие как выбор двух невозможных для объединения параметров из раскрывающихся меню.

from tkinter import *
from tkinter import ttk

class SubFrame(Frame):
    def __init__(self, parent, text="Top Right"):
        Frame.__init__(self)
        self.pack()  
        self.parent = parent
        self.root = parent.root
        self.label=Label(self, text=text).pack()


class RightFrame(Frame):
    def __init__(self, parent):
        Frame.__init__(self, relief=RAISED, borderwidth=1)
        self.pack(side=RIGHT, fill=BOTH, expand=1)
        self.root = parent
        self.label = Label(self, text="Right Frame").pack()


class LeftFrame(Frame):
    def __init__(self, parent):
        Frame.__init__(self, relief=RAISED, borderwidth=1)
        self.pack(side=LEFT, fill=BOTH, expand=1)
        self.root = parent
        self.label = Label(self, text="Left Frame").pack()

        #again Frames which would have a parent class RightFrame and root MainFrame
        self.subFrame1 = SubFrame(self)
        self.subFrame2 = SubFrame(self, text="Top Right SubFrame 2") 

class MainFrame(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.geometry("1100x600")
        self.title("Working Example")

        self.leftFrame = LeftFrame(self)
        self.rightFrame = RightFrame(self)
        #self.data = MagicalDataHandlingClass()



def run():
    app = MainFrame()
    app.mainloop()

EDIT ответ на комментарии, которые слишком длинны, чтобы уместиться

Вызов Frame.__init__(...) сделан потому, что определение класса выглядит как class LeftFrame(Frame). Обычно для объявления класса то, что вы пишете, это просто class LeftFrame.Когда вы добавляете бит в (), то, что происходит, называется наследованием. Когда вы наследуете от класса (называемого родительским), ваш класс (называемый дочерним) наследует все методы и атрибуты родительского элемента. Но так же, как вы должныинициализируйте ваш класс, чтобы получить объект, то есть lf = LeftFrame(...) родительский класс тоже должен быть инициализирован. В Python эта инициализация выполняется путем вызова специальной функции dunder __init__(...). Так что вызов Frame.__init__(...) происходит потому, что вам нужно сказатьродительский класс, каковы все значения, необходимые для правильной работы.В Python 3, однако, рекомендуется вместоДля создания экземпляра родительского элемента по имени вы используете функцию super, например super().__init__(....).Это происходит по многим сложным причинам, по большинству из которых вам, вероятно, пока не придется беспокоиться (например, что если вы наследуете от нескольких классов одновременно, что если вы наследуете от класса, унаследованного отдругой и т.д ...).Я бы не стал чувствовать себя ошеломленным, понимая всю мощь super(), если вы только начинаете, потому что в 99% случаев в Python 3 просто выполнение super().__init__(...) будет делать именно то, что вы хотите, даже если вы не понимаете,Если вам хочется взбодриться над головой У Раймонда Хеттингера есть хорошее описание Super is Super, и почему именно он намного лучше старого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...