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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Tkinter

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

Python

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

Q&A

解決済

2回答

1406閲覧

python pyファイルの合成でエラー

shin0859

総合スコア15

Tkinter

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

Python

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

1グッド

0クリップ

投稿2021/06/03 11:42

pythonの初心者です。初歩的な内容ですがご回答をお願いします。
前回の続き作業ですが、画像1と画像2のコードを合成したいのですが、
コード1+2の合成コードでいろいろエラーが有りまして
どこをどう直したらいいか、教えて頂きたいのですが。
コード1+2の中に、エラー表示をしています。
突っ込み所沢山あろうかと思いますが、宜しくご指示ください
(クラスを使わない方が、分かり易いのでしょうか?
クラスもグローバル変数もちょっと理解できていません)

前回の問い合わせの続きになります https://teratail.com/questions/340386

画像1

画像1

画像2

画像2

※コード1とコード2は文字数オーバーで省略してます

コード1+2

python

1from types import SimpleNamespace 2import tkinter as tk 3from tkinter import ttk 4from PIL import Image, ImageTk 5import cv2 6 7class MainWindow(): 8 def __init__(self, window): 9 self.win = window 10 self.win.geometry("1000x480") 11 self.menu_frame = tk.Frame(self.win, width=200) 12 self.main_frame = tk.Frame(self.win, width=800, bg="black") 13 14 # コントロール作成 15 # title_Label 16 icon0 = Image.open('./inifile/titleLogo.png') 17 icon0 = icon0.resize(size=(208, 34)) 18 icon0 = ImageTk.PhotoImage(icon0) 19 title_la = ttk.Label(self.menu_frame, image=icon0) 20 21 # info_Label 22 info_la = ttk.Label(self.menu_frame, 23 text="menu select", width=10, font=("メイリオ", "9")) 24 25 # select Folder_Combobox 26 List = ['all select', 'folder1', 'folder2', 'folder3'] 27 str = tk.StringVar() 28 folder_cmb = ttk.Combobox(self.menu_frame, 29 values=List, width=10, font=("Meiryo UI", 12), textvariable=str, state='readonly') 30 folder_cmb.set(List[0]) 31 folder_cmb.bind('<<ComboboxSelected>>', lambda e: print('str=%s' % str.get())) 32 # folder_cmb.bind('<<ComboboxSelected>>', selectFile_changed) 33 34 # LabelFrame 35 label_fl = ttk.Labelframe(self.menu_frame, 36 text='Order Check', padding=3, style='My.TLabelframe') 37 38 # Order_Radiobutton 39 Order_rb1 = tk.Radiobutton(label_fl, 40 value=0, text="shuffle", font=("Meiryo UI", "12")) 41 Order_rb1.select() 42 43 # Order_Radiobutton 44 Order_rb2 = tk.Radiobutton(label_fl, 45 value=1, text="normal", font=("Meiryo UI", "12")) 46 Order_rb2.deselect() 47 48 # load_button 49 icon1 = Image.open('./inifile/start.png') 50 icon1 = icon1.resize(size=(60, 57)) 51 icon1 = ImageTk.PhotoImage(icon1) 52 load_btn = tk.Button(self.menu_frame, image=icon1, relief=tk.FLAT) 53 54 # exit_button 55 icon2 = Image.open('./inifile/exit.png') 56 icon2 = icon2.resize(size=(44, 57)) 57 icon2 = ImageTk.PhotoImage(icon2) 58 exit_btn = tk.Button(self.menu_frame, image=icon2, relief=tk.FLAT) 59 60 # control Layout grid 61# ③/////// title_la load_btn exit_btn のアイコンボタンが表示されない 62 title_la.grid(row=0, column=0, columnspan=3, padx=10, pady=(0, 10), sticky=tk.W) 63 info_la.grid(row=1, column=0, padx=20, pady=5, sticky=tk.W) 64 folder_cmb.grid(row=2, column=0, padx=20, pady=5, sticky=tk.W) 65 label_fl.grid(row=3, column=0, padx=20, pady=5, sticky=tk.W) 66 Order_rb1.grid(row=4, column=0, padx=5, pady=0, sticky=tk.W) 67 Order_rb2.grid(row=4, column=1, padx=5, pady=0, sticky=tk.W) 68 # load_bbtn.grid(row=5, column=0, padx=20, pady=(30,5), sticky=tk.W) 69 # exit_bbtn.grid(row=6, column=0, padx=20, pady=0, sticky=tk.W) 70 load_btn.grid(row=5, column=0, padx=(20, 0), pady=30, sticky=tk.W) 71 # exit_btn.grid(row=5, column=0, padx=0, pady=(15,0)) 72 exit_btn.grid(row=5, column=0, padx=0, pady=0) 73 74 # top_button 75 icon3 = Image.open('./inifile/top.png') 76 icon3 = icon3.resize(size=(55, 57)) 77 icon3 = ImageTk.PhotoImage(icon3) 78 top_btn = tk.Button(self.main_frame, image=icon3, relief=tk.FLAT) 79 # top_btn.pack(padx=10, pady=10, anchor=tk.SW, side=tk.BOTTOM) 80# ②/////// 位置が左下に配置されない 81 top_btn.grid(row=0, column=0, padx=10, pady=10, sticky=tk.SW) 82 83 self.menu_frame.grid(row=0, column=0, sticky=tk.NSEW) 84 self.main_frame.grid(row=0, column=1, sticky=tk.NSEW) 85 86 self.win.grid_propagate(tk.NO) 87 self.win.grid_rowconfigure(0, weight=1) 88 self.win.grid_columnconfigure(0, minsize=200) 89 self.win.grid_columnconfigure(1, weight=1) 90 91 92 self.win_w = 800 93 self.win_h = 480 94 # 取り敢えずyoutubeから https://youtu.be/JTUb5Bxkvck 流用 95 self.video = cv2.VideoCapture("./video/2018年おうし座流星群 大火球出現.mp4") 96 97 self.img_w = self.video.get(cv2.CAP_PROP_FRAME_WIDTH) # 動画幅 98 self.img_h = self.video.get(cv2.CAP_PROP_FRAME_HEIGHT) # 動画高 99 self.interval = 10 # Interval in ms to get the latest frame 100 101 # Create canvas for image 102 self.canvas = tk.Canvas(self.main_frame, width=self.img_w, height=self.img_h) 103 self.canvas.place(x=0, y=0) 104 self.canvas.grid(row=0, column=0) 105# ①////// ↓ エラー発生  MainWindow(win) // TypeError: __init__() should return None, not 'types.SimpleNamespace' 106 return SimpleNamespace(**locals()) 107 108 # Update image on canvas 109 self.update_image() 110 111 def update_image(self): 112 # Get the latest frame and convert image format 113 self.image = cv2.cvtColor(self.video.read()[1], cv2.COLOR_BGR2RGB) # to RGB 114 self.image = Image.fromarray(self.image) # to PIL format 115 self.image = self.image.resize((int(self.img_w * (self.win_h / self.img_h)), int(self.win_h))) 116 self.image = ImageTk.PhotoImage(self.image) # to ImageTk format 117 118 # roop ok 119 ret, frame = self.video.read() 120 # print(ret) 121 if ret: 122 # Update image 123 self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image) 124 self.canvas.create_image(self.win_w / 2 - (self.img_w * (self.win_h / self.img_h) / 2), 0, image=self.image, 125 anchor=tk.NW) 126 # 指定した時間経過後 self.update_image を実行 127 self.win.after(self.interval, self.update_image) 128 129 else: 130 self.video.set(cv2.CAP_PROP_POS_FRAMES, 0) 131 self.update_image() 132 133 134 def main(): 135 # root = tk.Tk() 136 # root.title("Digital Photo") 137 root.geometry("1000x480") 138 view = create_view(root) 139 140 def show_animation(maxsize=200): 141 # video.release() 動画を閉じる 142 143 def animation(value): 144 value = min(value, maxsize) 145 root.grid_columnconfigure(0, minsize=value) 146 if value < maxsize: 147 root.after(20, animation, value + 10) 148 149 view.top_btn.pack_forget() 150 view.menu_frame.grid(row=0, column=0, sticky=tk.NSEW) 151 152 root.after_idle(animation, 10) 153 154 def hide_animation(value=200): 155 def animation(value): 156 value = max(0, value - 10) 157 root.grid_columnconfigure(0, minsize=value) 158 if value > 0: 159 root.after(20, animation, value) 160 else: 161 view.root.grid_propagate(False) 162 view.menu_frame.grid_forget() 163 view.top_btn.pack(padx=10, pady=10, anchor=tk.SW, side=tk.BOTTOM) 164 165 root.after_idle(animation, value) 166 167 def toggle_menu(e): 168 is_shown = root.grid_columnconfigure(0)["minsize"] 169 if is_shown: 170 hide_animation() 171 else: 172 show_animation() 173 174 root.bind_all("<F4>", toggle_menu) 175 view.exit_btn.config(command=root.quit) 176 view.load_btn.config(command=hide_animation) 177 view.top_btn.config(command=show_animation) 178 179 180if __name__ == "__main__": 181 win = tk.Tk() 182 win.title("Digital Photo") 183 MainWindow(win) 184 main() 185 win.mainloop()

--環境--
python3.8
tkinter8.6
pycharm2021.1

teamikl👍を押しています

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

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

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

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

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

guest

回答2

0

イメージ説明

投稿2021/06/05 12:59

shin0859

総合スコア15

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

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

0

ベストアンサー

title_la load_btn exit_btn のアイコンボタンが表示されない

ローカル変数なので、関数を抜けた時に破棄されます。

PhotoImage オブジェクトをインスタンス変数 (self.icon1 等) にすると、
MainWindow のインスタンスが生存中は残り続けるので、問題を解消できます。


①////// ↓ エラー発生  MainWindow(win) // TypeError: init() should return None, not 'types.SimpleNamespace'

__init__ 内の return で値を返してはいけません。
前の時のコードが変な位置に来てますが、ここでは不要です。

コードの全貌を把握してませんが、ここのエラーを修正しただけでは、
やりたいことの実現は出来ないと思います。


②/////// 位置が左下に配置されない

問題点
Button の親が main_frame なので、メニューではなくキャンバスと同じフレームに配置される

解決策

  • Button の親を main_frame -> menu_frame
  • top_btn.grid(row=6, column=0, row に menu_frame の一番下の値を設定
  • canvas.place(x=0, y=0) は不要

クラスを使わない方が、分かり易いのでしょうか?
クラスもグローバル変数もちょっと理解できていません

クラス単位で開発を勧める事自体は、良いと思います。
但し、何処で切り分けるか、設計は重要です。
単にクラスを使って書いただけでは、恩恵は余りありません。

今回の場合であれば、質問に関する部分はGUIのみなので
動画や画像処理のコードは不要なはずですが、
現況の設計では、不要な部分だけを切り離すのは、困難なので、
まずは、Frame 単位で部品の切り分けをしましょう。
(例えば、MenuFrame クラスと MainFrame クラスの様にして、
MainWindow クラス内で配置する。
メニューの非表示は、MainWindow 側で実装しておけば、
質問として掲載するコードは MenuFrame の部分のみでよくなります)

大雑把な指針としては、フレーム(Frame) 単位でクラスにまとめておくと、
他のプログラムからも使いたい、その部分だけテストしたい、
等といった場合に便利です。
ウィンドウ(Toplevel) 単位では、再利用は難しくなります。

投稿2021/06/03 21:01

teamikl

総合スコア8760

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

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

shin0859

2021/06/04 10:10

teamikl様 度々アドバイス有難うございます いろいろなご指摘頂き、試行錯誤状態です。 少しは先が見えてきたようですので、 もうしばらく先にご報告したいと思います。
shin0859

2021/06/05 12:40

その後 teamikl様のアドバイスと、ネット情報の試行錯誤で、希望のコードが得られました。 teamikl様 有難うございました。 下記にその全コードをアップいたします。 まだこのプログラムは途中経過なので、またその時はアドバイスを賜りたくお願いいたします。 ```python # coding: utf-8 import tkinter as tk from tkinter import ttk from tkinter import * from PIL import Image, ImageTk import cv2 class Application(tk.Frame): def __init__(self, master): super().__init__(master) self.pack() self.master.title("Digital Photo") self.menu_frame = tk.Frame(self, width=200) self.menu_frame.grid(row=0, column=0, sticky=tk.NSEW) self.main_frame = tk.Frame(self, width=800, bg="black") self.main_frame.grid(row=0, column=1, sticky=tk.NSEW) self.MenuFrame() self.MainCanvas() def MainCanvas(self): self.win_w = 800 self.win_h = 480 # 取り敢えずyoutubeから https://youtu.be/JTUb5Bxkvck 流用 self.video = cv2.VideoCapture("./video/2018年おうし座流星群 大火球出現.mp4") self.img_w = self.video.get(cv2.CAP_PROP_FRAME_WIDTH) # 動画幅 self.img_h = self.video.get(cv2.CAP_PROP_FRAME_HEIGHT) # 動画高 self.canvas1 = tk.Canvas(self.main_frame, width=self.win_w-10, height=self.win_h-10, bg="red") self.canvas1.grid(row=0, column=0, sticky=tk.NSEW) ### top_button icon3 = Image.open('./inifile/top.png') icon3 = icon3.resize(size=(55, 57)) self.icon3 = ImageTk.PhotoImage(icon3) self.top_btn = tk.Button(self.main_frame, image=self.icon3, relief=tk.FLAT) # self.top_btn.grid(row=0, column=0, padx=10, pady=10, sticky=tk.SW) # Update image on canvas self.interval = 10 # Interval in ms to get the latest frame self.update_image() def update_image(self): # Get the latest frame and convert image format self.image = cv2.cvtColor(self.video.read()[1], cv2.COLOR_BGR2RGB) # to RGB self.image = Image.fromarray(self.image) # to PIL format self.image = self.image.resize((int(self.img_w * (self.win_h / self.img_h)), int(self.win_h))) self.image = ImageTk.PhotoImage(self.image) # to ImageTk format # roop ok ret, frame = self.video.read() # print(ret) if ret: # Update image self.canvas1.create_image(0, 0, anchor=tk.NW, image=self.image) self.canvas1.create_image(self.win_w / 2 - (self.img_w * (self.win_h / self.img_h) / 2), 0, image=self.image, anchor=tk.NW) # 指定した時間経過後 self.update_image を実行 self.master.after(self.interval, self.update_image) else: self.video.set(cv2.CAP_PROP_POS_FRAMES, 0) self.update_image() def MenuFrame(self): ### title_Label icon0 = Image.open('./inifile/titleLogo.png') icon0 = icon0.resize(size=(208, 34)) self.icon0 = ImageTk.PhotoImage(icon0) self.title_la = ttk.Label(self.menu_frame, image=self.icon0) ### info_Label info_la = ttk.Label(self.menu_frame, text="menu select", width=10, font=("メイリオ", "9")) ### select Folder_Combobox List = ['all select', 'folder1', 'folder2', 'folder3'] str = tk.StringVar() folder_cmb = ttk.Combobox(self.menu_frame, values=List, width=10, font=("Meiryo UI", 12), textvariable=str, state='readonly') folder_cmb.set(List[0]) folder_cmb.bind('<<ComboboxSelected>>', lambda e: print('str=%s' % str.get())) # folder_cmb.bind('<<ComboboxSelected>>', selectFile_changed) ### LabelFrame label_fl = ttk.Labelframe(self.menu_frame, text='Order Check', padding=3, style='My.TLabelframe') ### Order_Radiobutton Order_rb1 = tk.Radiobutton(label_fl, value=0, text="shuffle", font=("Meiryo UI", "12")) Order_rb1.select() ### Order_Radiobutton Order_rb2 = tk.Radiobutton(label_fl, value=1, text="normal", font=("Meiryo UI", "12")) Order_rb2.deselect() ### load_button icon1 = Image.open('./inifile/start.png') icon1 = icon1.resize(size=(60, 57)) self.icon1 = ImageTk.PhotoImage(icon1) # load_btn = tk.Button(menu_frame, # image=icon1, relief=tk.FLAT, command=load_btn_click) self.load_btn = tk.Button(self.menu_frame, image=self.icon1, relief=tk.FLAT) ### exit_button icon2 = Image.open('./inifile/exit.png') icon2 = icon2.resize(size=(44, 57)) self.icon2 = ImageTk.PhotoImage(icon2) # exit_btn = tk.Button(menu_frame, # image=icon2, relief=tk.FLAT, command=exit_btn_click) self.exit_btn = tk.Button(self.menu_frame, image=self.icon2, relief=tk.FLAT) # ### top_button # icon3 = Image.open('./inifile/top.png') # icon3 = icon3.resize(size=(55, 57)) # self.icon3 = ImageTk.PhotoImage(icon3) # self.top_btn = tk.Button(self.menu_frame, image=self.icon3, relief=tk.FLAT) ### control Layout grid self.title_la.grid(row=0, column=0, columnspan=3, padx=10, pady=(0, 10), sticky=tk.W) info_la.grid(row=1, column=0, padx=20, pady=5, sticky=tk.W) folder_cmb.grid(row=2, column=0, padx=20, pady=5, sticky=tk.W) label_fl.grid(row=3, column=0, padx=20, pady=5, sticky=tk.W) Order_rb1.grid(row=4, column=0, padx=5, pady=0, sticky=tk.W) Order_rb2.grid(row=4, column=1, padx=5, pady=0, sticky=tk.W) self.load_btn.grid(row=5, column=0, padx=(20, 0), pady=30, sticky=tk.W) self.exit_btn.grid(row=5, column=0, padx=0, pady=0) def main(): root = tk.Tk() app = Application(master=root) def show_animation(maxsize=200): def animation(value): value = min(value, maxsize) root.grid_columnconfigure(0, minsize=value) if value < maxsize: root.after(20, animation, value+20) app.menu_frame.grid(row=0, column=0, sticky=tk.NSEW) root.after_idle(animation, 10) # print("show_animation") app.top_btn.grid_forget() def hide_animation(value=200): def animation(value): value = max(0, value-20) root.grid_columnconfigure(0, minsize=value) if value > 0: root.after(20, animation, value) else: app.grid_propagate(False) app.menu_frame.grid_forget() app.top_btn.grid(row=0, column=0, padx=10, pady=10, sticky=tk.SW) root.after_idle(animation, value) # print("hide_animation") def toggle_menu(e): is_shown = root.grid_columnconfigure(0)["minsize"] if not is_shown: show_animation() else: hide_animation() root.bind_all("<F4>", toggle_menu) app.exit_btn.config(command=root.quit) app.load_btn.config(command=hide_animation) app.top_btn.config(command=show_animation) app.mainloop() if __name__ == "__main__": main() ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問