質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.49%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

2352閲覧

Python Tkinterでのスーパークラスのコンストラクタ用引数に関して。

chokokorone333

総合スコア32

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/06/29 13:16

編集2020/06/29 13:17

### 完成予定品
Tkinterを使用し、タブ機能(notebook)を付ける。

現在のコーディング状況

class Gui(tk.Frame) からタブ機能のついた画面を一つ表示しようとしています。
class Gui(tk.Frame) のコンストラクタ内にある、Tab(ttk.Notebook) のコンストラクタにより、タブを画面を実装しようとしています。

エラー内容

エラー内容の解釈として、Tab(ttk.Notebook) は、Frameクラスのオブジェクトしか受け付けない。と考えております。
ですが、Tab(ttk.Notebook) へ渡している tab1 = tk.Frame(self.master) の tab1 は <class 'tkinter.Frame'> であり、混乱しております。

text

1Traceback (most recent call last): 2 File "app.py", line 28, in <module> 3 app = Gui(master=root) 4 File "app.py", line 16, in __init__ 5 Tab(master=tab) 6 File "app.py", line 21, in __init__ 7 super.__init__(master) 8TypeError: descriptor '__init__' requires a 'super' object but received a 'Frame'

実行環境

・windows10 コマンドプロンプト
・Python3.8.3

Python

1 2#coding:utf-8 3 4import tkinter as tk 5from tkinter import ttk 6 7 8class Gui(tk.Frame): 9 def __init__(self, master): 10 super().__init__(master) 11 self.pack() 12 13 self.master.geometry("1100x600") 14 self.master.title("NoteBook Test") 15 16 tab = tk.Frame(self.master) 17 Tab(master=tab) 18 19 20class Tab(ttk.Notebook): 21 def __init__(self, master = None): 22 super.__init__(master) 23 24 self.add(master, text="tab") 25 26 27if __name__ == "__main__": 28 root = tk.Tk() 29 app = Gui(master=root) 30 app.mainloop() 31

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

返信遅くなってしまいました。
試行錯誤の結果、Guiクラスにノートブックを構成する動作を入れ、追加したい分をFrameクラスのインスタンスからaddする。といった具合にしてみました。

その他notebookにaddしたいウィジェットがある場合は、
Frameクラス以外にも、Frame2, Frame3...と作りインスタンスを生成しとすれば良いという考えに基づき作成しております。

Python

1#coding:utf-8 2 3import tkinter as tk 4from tkinter import ttk 5 6#import pub 7 8 9class Gui(ttk.Notebook): 10 def __init__(self, master): 11 super().__init__(master) 12 note = ttk.Notebook(master) 13 14 page1 = Frame(note, "page1") 15 page2 = Frame(note, "page2") 16 17 array = [page1, page2] 18 19 for i in array: 20 note.add(i, text=i.ret_name()) 21 22 note.pack(fill=tk.BOTH, expand=True) 23 self.pack() 24 25 26class Frame(tk.Frame): 27 name = "" 28 def __init__(self, master=None, txt=None): 29 super().__init__(master) 30 self.name = txt 31 page = tk.Frame(master) 32 self.widget(txt) 33 self.pack() 34 35 def widget(self, txt): 36 label = tk.Label(self, text=txt, font=("", 30)) 37 label.pack() 38 39 def ret_name(self): 40 return self.name 41 42def main(): 43 root = tk.Tk() 44 root.geometry("600x600") 45 root.title("tkinter test") 46 47 app = Gui(master=root) 48 app.pack() 49 50 root.mainloop() 51 52 53if __name__ == "__main__": 54 main() 55 56

投稿2020/07/05 14:43

編集2020/07/07 06:36
chokokorone333

総合スコア32

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2020/07/05 16:50

self.pack() は2か所ともなくても大丈夫、レイアウトは クラス外で呼び出した方がgrid()でも使えるようになります。 app.pack()でもう一度呼び出しているのと、 Notebookに追加するFrameは、Notebook側で表示してくれます。 (どちらも2重に呼び出している状態。但し動作に支障はありません) ---- もう一点。これも本題とは関係ない部分ですが class Frame(tk.Frame):   name = "" # <-- これはクラス変数(クラス間で共有する変数) になるので不要です。インスタンス変数 (self.name) に上書きされ 意味のない宣言になってます。
chokokorone333

2020/07/07 01:58

self.pack()が必要ない理由として、 ・note.addはnoteに自動で貼り付ける。・Guiのインスタンスappを外でapp.pack()している。 ということでよろしかったでしょうか? また、クラス外で呼び出したほうがgirid()でも使えるようになる。という部分の理解が追いついていません。 name = ""で最初に宣言する必要がなく、self.name = txtでインスタンス変数nameが作られ、txtが入るということですね。
teamikl

2020/07/07 03:53

> note.addはnoteに自動で貼り付ける。・Guiのインスタンスappを外でapp.pack()している。 その通り。現行のコードでは特に問題はありませんが、省略可能です。 > クラス外で呼び出したほうがgirid()でも使えるようになる。 これは、クラスを再利用する場合を想定してます。 実際にこのような使い方はしないかもしれませんが、一例で frame = tk.Frame(parent) frame.grid() gui = Gui(parent) # 内部で self.pack() してると、grid() と競合する Tkinter のウィジェットの配置は、pack/grid/place の3種類あるのですが、 そのうち pack と grid は同一ウジェット上に互いに混在させるが出来ません。 クラス内部で self.pack() とすると、packのレイアウトにしか配置できないクラスになってしまいます。 出来ないといっても解決策は簡単で、一手間、間に grid() で配置したFrame を挟むと済む話ですが、 それよりもレイアウトは利用側に任せた方が自然な解決策になります。 レイアウトがどのように配置されるかについて、 クラス内部のコードを見に行く必要がある、というコードの可読性にも繋がる為。 label = tk.Label(self, text=txt, font=("", 30)) label.pack() 通常のウィジェットのように、独自のウィジェットを拡張したクラスを作る場合も同様、 そのクラスの利用側(インスタンスを生成した側)に配置は任せた方が良いです。 > name = ""で最初に宣言する必要がなく、 > self.name = txtでインスタンス変数nameが作られ、 はい。前者はクラス変数、実際に使っているのは後者のインスタンス変数のみです。
guest

0

無事解決することができました。ありがとうございます。
コメントですと、インデントがおかしくなるためこちらに貼らせていただきます。

Python

1#coding:utf-8 2 3import tkinter as tk 4from tkinter import ttk 5 6 7class Gui(ttk.Notebook): 8 def __init__(self, master): 9 super().__init__(master) 10 11 self.master.geometry("1100x600") 12 self.master.title("Tkinter with Class") 13 14 tab = tk.Frame(self.master, width=1100,height=600) 15 self.add(tab, text="tab1") 16 Tab(master=tab) 17 18 tab2 = tk.Frame(self.master, width=1100,height=600) 19 self.add(tab2, text="tab1") 20 Tab(master=tab) 21 22 self.pack(side = "top") 23 24class Tab(tk.Frame): 25 def __init__(self, master = None): 26 super().__init__(master) 27 28if __name__ == "__main__": 29 root = tk.Tk() 30 app = Gui(master=root) 31 app.mainloop()

投稿2020/06/29 14:18

chokokorone333

総合スコア32

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2020/06/29 14:21

Tab(master=tab) 戻り値を受け取っていない、pack()も呼ばれてないので、 ここは意図通りの動作になってないかもしれません。
chokokorone333

2020/06/29 14:25

申し訳ありません、理解ができていないのですが、 Tab(master=tab)の呼び出しをしても意味がないということでしょうか。 でしたら、class Tab(tk.Frame)以下に、tab, tab2の処理内容を記述しようと考えております。
teamikl

2020/06/29 15:13

一点見落としてましたが Gui(tk.Frame): -> Gui(ttk.Notebook) に変更してたのですね。 tab = tk.Frame(self.master, width=1100,height=600) のフレームが Notebook に追加されて、 Tab(master=tab) は、生成されて非表示のままになってます。 ここを後から実装されるというなら納得ですが、間の Frame が一つ余分です。 self.add(Tab(master=self), text="tab1") また、width=1100,height=600は 個別ではなく、親ウィジェットに指定した方が良いです。 Notebook 内に配置されるとサイズはNotebook任せになります。
guest

0

ベストアンサー

記述ミスです。親クラスのコンストラクタ呼び出しになってません。

  • super().__init__(master) OK
  • super.__init__(master) NG

super はクラスとして実装されコンストラクタ__init__があるので
エラーメッセージが解り難くなっているようです。

投稿2020/06/29 13:35

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chokokorone333

2020/06/29 13:54

ご指摘ありがとうございます。 無事、エラーは無くなったようです。 しかし、プロンプトが固まったまま望む画面も出ずの結果になってしまいました。 現在調査中ですが、訂正が必要なコードになっていた場合、レビューをしていただけますと幸いです。
teamikl

2020/06/29 14:00

見た感じ、他の問題点は2点 - Tabオブジェクトの pack()やgrid() が呼ばれてない為、非表示になってます - オブジェクトの親子関係がおかしい。親ウィジェットを add しようとしてますが、  通常は、小ウィジェットをaddで追加するようにします
chokokorone333

2020/06/29 14:08

ありがとうございます。 その2点を踏まえてもう少し知らべてみようと思います。
chokokorone333

2020/06/29 14:17

ありがとうございます。 以上を踏まえ改定しました。 ポイントとなった点としては、オブジェクトの親子関係を指摘していただいた点です。 以下の通りにコーディングしました。 ```Python #coding:utf-8 import tkinter as tk from tkinter import ttk class Gui(ttk.Notebook): def __init__(self, master): super().__init__(master) self.master.geometry("1100x600") self.master.title("Tkinter with Class") tab = tk.Frame(self.master, width=1100,height=600) self.add(tab, text="tab1") Tab(master=tab) tab2 = tk.Frame(self.master, width=1100,height=600) self.add(tab2, text="tab1") Tab(master=tab) self.pack(side = "top") class Tab(tk.Frame): def __init__(self, master = None): super().__init__(master) if __name__ == "__main__": root = tk.Tk() app = Gui(master=root) app.mainloop() ```
guest

0

ウィジェット構造 - root : tkinter.Tk - app : Gui (tk.Frame) - tab : Tab (ttk.Notebook) - page : tk.Frame - label : tk.Label

のようなツリー形式で各ウィジェットを構成してください。

tab に入れるウィジェットは通常 tk.Frame(tab)tk.Frame(master=tab) と同じ。
として、生成したウィジェットを add で配置します。

python

1#!/usr/bin/env python3.8 2 3import tkinter as tk 4from tkinter import ttk 5 6 7class Gui(tk.Frame): 8 def __init__(self, master): 9 super().__init__(master) 10 11 tab = Tab(master=self) 12 13 page = tk.Frame(tab) 14 label = tk.Label(page, text="Page1", font=("", 30)) 15 label.pack() 16 tab.add(page, text="page1") 17 # NOTE: page.pack は不要。ttk.Notebook内部で処理されます。 18 19 tab.pack(fill=tk.BOTH, expand=True) # <- Tab クラス内では呼び出さない。利用側で grid()/pack() を呼び出す 20 21 self.tab = tab 22 23 24class Tab(ttk.Notebook): 25 def __init__(self, master=None): 26 super().__init__(master) 27 28 29 30if __name__ == "__main__": 31 root = tk.Tk() 32 root.geometry("1100x600") 33 root.title("NoteBook Test") 34 # geometry, title は外部で呼び出すと、 35 # Guiのmaster に root 以外の任意のウィジェットを渡せます。 36 37 app = Gui(master=root) 38 app.pack(fill=tk.BOTH, expand=True) # 外部で呼び出す事で、 Gui オブジェクトを pack/grid/place で使えるようになります 39 40 root.mainloop() 41

投稿2020/06/29 14:24

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chokokorone333

2020/07/05 14:44

ウィジェットの構成をそちらの図で理解することができました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問