プログラミング初学者です
1,これは誰でも初学者の時期があるので問題は無いのですが、質問するときのヒントのページを見て、質問の初心者にはならないでくださいな。
2,質問文のソースコードは1行ではなく、もう少し全体のコードを投稿してくださいな。
■本題
self.f_buttonとVolumeWindowの型が分からなかったので、
VolumeWindowを1個しか開かない簡単なサンプルコードを添付しておきます。
メインウィンドウの制御は、自分で行ってくださいな。
Python
1# -*- coding: UTF-8 -*
2from tkinter import ttk
3from tkinter import *
4import functools
5
6
7class VolumeWindow(Toplevel):
8 def __init__(self, root):
9 super().__init__()
10 # ウィンドウを閉じたときのイベントを登録
11 self.protocol('WM_DELETE_WINDOW', functools.partial(self.on_window_exit, param=2))
12 self.volumes = Scale(self, {'label': 'volume', 'from_': 0, 'to': 100,
13 'length': 200, 'command': self.__on_changed_scale_value})
14 self.volumes.pack()
15 # 初期状態は非表示
16 self.set_visible(False)
17
18 def __on_changed_scale_value(self, event):
19 # Scale(スライダ)を移動時にイベント発生
20 pass
21
22 def on_window_exit(self, param):
23 # VolumeWindowウィンドウを閉じた時に呼ばれる処理
24 if param == 2:
25 self.set_visible(False)
26
27 def set_visible(self, visible):
28 # ウィンドウの表示を切り替える
29 # visible:True 表示,False 非表示
30 if visible:
31 self.deiconify()
32 else:
33 self.withdraw()
34
35
36class App(object):
37 def __init__(self):
38 self.root = Tk()
39 self.root.title('Q109871')
40 # ウィンドウを閉じたときのイベントを登録
41 self.root.protocol('WM_DELETE_WINDOW', functools.partial(self.on_window_exit, param=1))
42 # ボリュームウィンドウを作成して、self.volume_windowに変数を保持
43 self.volume_window = VolumeWindow(self.root)
44 # ボタンクリック時はVolumeWindow#set_visibleをTrueで呼び出す。
45 self.volume_button = Button(self.root, text='Volume',
46 command=functools.partial(self.volume_window.set_visible, visible=True))
47 self.volume_button.pack()
48
49 def on_window_exit(self, param):
50 # sys.exitを呼び出し。
51 if param == 1:
52 sys.exit(0)
53
54 def run(self):
55 self.root.mainloop()
56
57
58def main():
59 app = App()
60 app.run()
61
62
63if __name__ == '__main__':
64 main()
65
コメント欄の質問を受けて追加
まず、Python言語自体が簡単なテストアプリならいいのですが、
本格的な画面(GUI)アプリケーション作成には向いていない言語だと個人的に思っています。
すぐに思いつく理由としては
・情報がtkinterのチュートリアルレベルで終わっている事が多い。
・他のGUIアプリを開発した事がある前提の情報が多い。
・日本語の情報が少なめ。
・体感 GUIアプリ開発者のユーザーが少なめ
どういうユーザーを対象にしてアプリケーションを作成しているのかが分かりませんが。
例えば、OSがWindowsならVisual Studio Communityを使ったアプリになるのでは。
あとはそのアプリに質問者様がどれだけの時間(作業工数)を掛けれるかでしょうか。
個人的には最低限、画面レイアウトをコードではなく、XMLやJSONで定義できるGUIツールキットを使ったほうが、
画面の定義に掛かる時間を短く出来ます。
なければ、昔、別の質問で回答した感じの事をプログラムで作成して、
JSONファイルなどから読む形にするといいですよ。
とりとめのない回答になってしまいましたが、参考になればー。
質問文の編集ありがとうございました。以下のサンプルコードで希望する動作になりますかー?
サンプルコード1)元ソースをあまり変更しないタイプ
Python
1# -*- coding: UTF-8 -*
2import tkinter as Tk
3
4
5# ↓追加 ここから
6def set_window_visible(window, visible):
7 if visible:
8 window.deiconify()
9 else:
10 window.withdraw()
11# ↑追加 ここまで
12
13
14class VolumeWindow:
15
16 def __init__(self, master):
17 # masterはFrame型
18 self.master = master
19 self.top = Tk.Toplevel(self.master)
20 self.f = Tk.Frame(self.top)
21 self.f.pack()
22 self.volume = Tk.IntVar()
23 self.volume.set(50)
24 self.volume_bar = Tk.Scale(self.f, orient='h',variable=self.volume)
25 self.volume_bar.pack()
26 set_window_visible(self.top, False)
27 #VolumeWindowウィンドウを閉じる時のイベントを追加
28 self.top.protocol('WM_DELETE_WINDOW', self.on_window_exit)
29
30 def on_window_exit(self):
31 # VolumeWindowウィンドウを閉じた時に呼ばれる処理
32 # Frame型の変数volume_buttonを設定
33 self.master.volume_button.configure(state=Tk.NORMAL)
34 # ボリュームウィンドウを非表示に
35 set_window_visible(self.top, False)
36
37
38class Frame(Tk.Frame):
39 def __init__(self, master=None):
40 Tk.Frame.__init__(self, master)
41 self.f = Tk.Frame(self)
42 self.f.pack()
43 # 引数をFrameに変更
44 self.volume = VolumeWindow(self)
45 self.f_button = Tk.Frame(self.f)
46 self.f_button.pack()
47 self.volume_button = Tk.Button(self.f_button, text='Volume', command=self.control_volume, state=Tk.NORMAL)
48 self.volume_button.pack(padx=5, pady=5, side=Tk.LEFT)
49
50 def control_volume(self):
51 # make_windowはしない。ボリュームウィンドウを表示するだけ。
52 #self.volume.make_window()
53 set_window_visible(self.volume.top, True)
54 self.volume_button.configure(state=Tk.DISABLED)
55
56
57if __name__ == '__main__':
58 f = Frame()
59 f.pack()
60 f.mainloop()
61
サンプルコード2)個人的な変更版
1,VolumeWindowをTk.Toplevelに変更して変数を削除
2,メイン画面のボタンが増えた時用にFrame#widgets_set_state関数を追加
Python
1# -*- coding: UTF-8 -*
2import tkinter as Tk
3
4
5# ↓追加
6def set_window_visible(window, visible):
7 if visible:
8 window.deiconify()
9 else:
10 window.withdraw()
11#
12
13#Tk.Toplevelを継承するように変更
14class VolumeWindow(Tk.Toplevel):
15 def __init__(self, master):
16 super().__init__(master)
17 self.f = Tk.Frame(self)
18 self.f.pack()
19 self.volume = Tk.IntVar()
20 self.volume.set(50)
21 self.volume_bar = Tk.Scale(self.f, orient='h',variable=self.volume)
22 self.volume_bar.pack()
23 set_window_visible(self, False)
24 #VolumeWindowウィンドウを閉じる時のイベントを追加
25 self.protocol('WM_DELETE_WINDOW', self.on_window_exit)
26
27 def on_window_exit(self):
28 # VolumeWindowウィンドウを閉じた時に呼ばれる処理
29 # 親ウィンドウのボタンを活性化
30 self.master.widgets_set_state(True)
31 # ボリュームウィンドウを非表示に
32 set_window_visible(self, False)
33
34
35class Frame(Tk.Frame):
36 def __init__(self, master=None):
37 Tk.Frame.__init__(self, master)
38 self.f = Tk.Frame(self)
39 self.f.pack()
40 # 引数をFrameに変更
41 self.volume = VolumeWindow(self)
42 self.f_button = Tk.Frame(self.f)
43 self.f_button.pack()
44 self.volume_button = Tk.Button(self.f_button, text='Volume', command=self.control_volume, state=Tk.NORMAL)
45 self.volume_button.pack(padx=5, pady=5, side=Tk.LEFT)
46
47 def control_volume(self):
48 # make_windowはしない。ボリュームウィンドウを表示するだけ。
49 #self.volume.make_window()
50 set_window_visible(self.volume, True)
51 self.widgets_set_state(False)
52
53 def widgets_set_state(self, state):
54 if state:
55 self.volume_button.configure(state=Tk.NORMAL)
56 else:
57 self.volume_button.configure(state=Tk.DISABLED)
58
59
60if __name__ == '__main__':
61 f = Frame()
62 f.pack()
63 f.mainloop()
64
65
個人的な意見としてはボリュームウィンドウを表示しても、別にメインウィンドウの操作を制限する必要はないのでは・・と思いますが。。