エラー文の読み方が分からない、また、文法がどう間違っているのか、ご教授いただきたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,269

Kaiji.Anabuki

score 30

 前提・実現したいこと

文法ミスがなぜ起こっているのか理解したい。

参考サイト

https://pythonprogramming.net/change-show-new-frame-tkinter/

 発生している問題・エラーメッセージ

frame = F(container, self) ← このコードにエラー文がでるのだが、間違っている理由が、分からない。

 該当のソースコード

# -*- coding: utf-8 -*-

#=========================================================================
# ライブラリ
#=========================================================================
# GUIを扱う
import tkinter as tk
# tkinterよりデザインが良くなる
from tkinter import ttk

#=========================================================================
# クラス定義
#=========================================================================
#-------------------------------------------------------------------------
# メインクラス (継承 : tk.Tk)
#-------------------------------------------------------------------------
class WordPracticeApp(tk.Tk):

    #---  コンストラクタ
    def __init__(self, *args, **kwargs):

        # 初期化
        tk.Tk.__init__(self, *args, **kwargs)

        # コンテナのフレームを生成
        container = tk.Frame(self)

        # コンテナ配置
        container.pack(side="top", fill="both", expand=True)

        # コンテナのグリッドを 1x1 にする
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # フレームを格納する配列
        self.frames = {}

        # ページを格納する配列
        pages = (
                    StartPage, 
                    InputNamePage,
                    OptionSelectPage
                )

        # それぞれのページに対して
        for F in pages:
            # フレームを生成
            frame = F(container, self)

            # フレームを格納
            self.frames[F] = frame

            # フレームを配置
            frame.grid(row=0, column=0, sticky="nsew")


        # スタートページを表示
        self.show_frame(StartPage)


    #---  フレームを表示
    def show_frame(self, cont):

        # WordPracticeAppのcontのフレームを格納
        frame = self.frames[cont]

        # そのフレームを上位層へ
        frame.tkraise()


#-------------------------------------------------------------------------
# スタートページクラス (継承 : tk.Frame)
#-------------------------------------------------------------------------
class StartPage(tk.Frame):

    #---  コンストラクタ
    def __init__(self, parent, contoroller):

        # 初期化
        tk.Frame.__init__(self, parent)

        ### タイトル表示
        #--- ラベル生成
        # 空白
        spaceLabel1 = [tk.Label(self, text="") for column in range(10)]
        spaceLabel2 = [tk.Label(self, text="") for column in range(3)]
        # タイトル
        titleLabelFont  = ("Helevetice", 32, "bold")
        titleLabel      = ttk.Label(self,\
                                    text="WORDPRACTICE",\
                                    font=titleLabelFont)

        #--- ラベル配置
        # 空白
        for index in range(10):
            spaceLabel1[index].pack()
        # タイトル
        titleLabel.pack()

        ### ボタン表示
        #---  ボタン生成
        startButton =\
         ttk.Button( self, text="           Start           ",\
                     command=lambda : controller.show_frame(InputNamePage) )

        #---  ボタン配置
        # 空白
        for index in range(3):
            spaceLabel2[index].pack()
        # ボタン
        startButton.pack()



#-------------------------------------------------------------------------
# 名前入力ページクラス (継承 : tk.Frame)
#-------------------------------------------------------------------------
class InputNamePage(tk.Frame):

    #---  コンストラクタ
    def _init__(self, parent, controller):

        # 初期化
        tk.Frame.__init__(self, parent)

        ###  タイトル表示
        #---  ラベル生成
        #  空白
        spaceLabel1 = [tk.Label(self, text="") for column in range(5)]
        # タイトル
        titleLabelFont  = ("Helevetice", 18)
        titleLabel      =\
           ttk.Label(self,\
                     text="ユーザー名を入力してください。",\
                     font=titleLabelFont)

        #---  ラベル配置
        # 空白
        for index in range(5):
            spaceLabel1[index].pack()
        # タイトル
        titleLabel.pack()


        ### フレーム表示
        #---  フレーム生成
        frame = ttk.Frame(self)
        #---  フレーム配置
        frame.pack()


        ### ユーザー名入力表示
        #--- ラベル生成
        # 空白
        spaceLabel2 = [tk.Label(frame, text="") for column in range(3)]

        # ユーザー名
        userNameLabelFont  = ("Helevetice", 14)
        userNameLabel      =\
          ttk.Label(frame, text="ユーザー名:", font=userNameLabelFont)

        #--- ラベル配置
        # 空白
        for index in range(3):
            spaceLabel2[index].grid(row=index, column=0)
        # ユーザー名
        userNameLabel.grid(row=4, column=0)

        #---  エントリー生成
        userName = tk.StringVar()
        userNameEntry = ttk.Entry(frame, textvariable=userName, width=30)

        #---  エントリー配置
        userNameEntry.grid(row=4, column=1)


        ### ボタン表示
        #---  ボタン生成
        okButton = ttk.Button( frame, text="  OK  ",\
                               command=lambda :\
                               controller.show_frame(OptionSelectPage) )

        #---  ボタン配置
        okButton.grid(row=4, column=3)


#-------------------------------------------------------------------------
# 問題形式選択ページクラス (継承 : tk.Frame)
#-------------------------------------------------------------------------
class OptionSelectPage(tk.Frame):

    #---  コンストラクタ
    def _init__(self, parent, controller):

        # 初期化
        tk.Frame.__init__(self, parent)

        ###  タイトル表示
        #---  ラベル生成
        #  空白
        spaceLabel1 = [tk.Label(self, text="") for column in range(5)]
        # タイトル
        titleLabelFont  = ("Helevetice", 18)
        titleLabel      =\
           ttk.Label(self,\
                     text="問題形式を選択してください。",\
                     font=titleLabelFont)

        #---  ラベル配置
        # 空白
        for index in range(5):
            spaceLabel1[index].pack()
        # タイトル
        titleLabel.pack()



#=========================================================================
# 本体処理
#=========================================================================
application = WordPracticeApp()
app.mainloop()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2018/03/08 08:57

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

  • 退会済みユーザー

    退会済みユーザー

    2018/03/08 09:49

    エラーのスタックとレースは残しておいてください。

    キャンセル

  • 退会済みユーザー

    2018/03/08 09:55

    複数のユーザーから「意図的に内容が抹消された質問」という意見がありました
    解決後に編集機能を用いて質問内容を改変し関係のない内容にしたり、内容を削除する行為は禁止しています。
    投稿していただいた質問は、後に他の誰かが困ったときに助けになる情報資産になると考えるからです。
    「質問を編集する」ボタンから編集を行い、他のユーザにも質問内容が見えるように修正してください。

回答 2

checkベストアンサー

+2

エラー文の読み方ですが。

Traceback (most recent call last):
  File "Window_ver1.1.py", line 210, in <module>
    application = WordPracticeApp()
  File "Window_ver1.1.py", line 48, in __init__
    frame = F(container, self)
  File "C:\Users\kaiji\Anaconda3\lib\tkinter\__init__.py", line 2738, in __init__
    Widget.__init__(self, master, 'frame', cnf, {}, extra)
  File "C:\Users\kaiji\Anaconda3\lib\tkinter\__init__.py", line 2293, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: unknown option "-menu"

これはスタックトレースといい実行時エラーが発生した時点でのプログラムの呼び出しツリー情報を表示しています。

今回の場合、ソースコードのframe = F(container, self)この行でエラーが発生した事を表しています。
Widget.__init__(self, master, 'frame', cnf, {}, extra)
Widget.__init__関数はコンストラクタ(※1)クラスの初期化時にエラーが発生した事を表しています。
※1 正確には違いますが便宜上このように表記します。

質問文のプログラムはStartPageInputNamePageOptionSelectPageの3つのクラスの生成を行っているので、どのクラスでエラーが発生したのかを特定します。
それは WordPracticeApp#__init__関数のpages 変数の各値をコメントアウトして実行すれば分かります。

コメントアウトして実行すると、InputNamePageOptionSelectPageの2つのクラスの生成処理で質問文のエラーが発生することが分かります。

ではクラスのどの部分まで正しく実行できているのかを確認するために、
InputNamePageの__init__関数にその行まで実行したかどうかを確認するprint文を追加します。

そうすると、追加したprint文が表示されない事から「__init__関数が呼び出されていない」事が分かります。

では一体2つのクラスのどこが問題なのかそれはこの__init__の関数定義です。
先頭のアンダーラインが1個抜けています。

def _init__(self, parent, controller):


def __init__(self, parent, controller):

■長くなったので結論

  • 原因 
    __init__関数のスペルミスによりtk.Frame.__init__(self, parent)の呼び出しが行われず質問文表記のエラーが発生した。
  • 対策方法
    スペルミスを治す。

このスペルミス以外にも2点スペルミスがあります。
1,StartPageクラスの__init__関数の引数contoroller → controller
2,質問文のソースコード最終行のapp.mainloop() → application.mainloop()

よって合計4箇所のスペルミスがあります。

プログラムを修正した時は、似たような問題を発生させないために修正すると共に1個以上のこの問題が発生しないための何かをしてください。

今回、私がオススメするのはIDEの導入の検討とSoftware Debugging Class Onlineについてです。

IDEを使っていないなら導入の検討をしてくださいな。
IDEを導入しているなら赤文字で警告のメッセージがでます。

IDEはPython言語ならPyCharm Community Editionがおすすめです。

科学的なデバック方法については
udacityの無料コースのSoftware Debugging Class Onlineが考え方として纏まっているのでかなりおすすめです。

■余談
質問文は追記する形にしてくださいな。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/08 18:15

    一つのミスだけでなく、他のミスまで発見いただいて、本当にありがとうございました。
    今後このようなミスをしないように、IDEを導入させていただき、ミスを防ぎたいと思います。ご回答ありがとうございました。
    余談についても、次から気を付けたいと思います。

    キャンセル

  • 2018/03/08 18:51

    プログラムを始めたばかりの時は分からない事が多いと思いますが。1個ずつ学習していけば少しずつ上達します。
    私的なお勧めは回答文にあげたようにudacityの無料コースのSoftware Debugging Class Onlineです。
    プログラムを始めた頃にこのコースの内容について知っていたら防げたバグが大量にあります。

    キャンセル

+1

most recent call last
最後の行が最後に呼ばれました

unknown option "-menu"
「-menu」というオプションは知りません

追記

最初は「エラーの意味がわからない」という質問でした。
何も言及なくこっそり質問編集されるとまるで私が頓珍漢な回答をしているように見えます。

またエラー文を消す意味が分かりません。
新しい質問文では文法エラーとなっていますが、ソース中に「-menu」という記述はありません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/08 18:09

    申し訳ございません、この質問を第三者が見ることを前提に考えることが出来ていませんでした。
    以後、質問内容を変更するときは、追記の形を取りたいと思います。
    また、エラー文を削除したのは、変更後の質問内容には、必要ないと考えてしまったからです。
    これからは、第三者の目に気を付けて、質問したいと思います。
    長文失礼いたしました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる