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

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

ただいまの
回答率

88.64%

[Python3] tkinter, チェックボタンで取得したvalue値を参照し関数を実行したい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 748

3265462164

score 24

Python3で、tkinterを使用して、下記のコードを作成しました。

from tkinter import *
from tkinter import ttk

root = Tk()
root.title('測定CH設定')    
root.geometry("500x350+640+40")

frame1 = ttk.Labelframe(root, text='測定帯域選択', padding=5)
frame1.grid(row=0, column=0, columnspan=1, padx=15, pady=10, sticky='w')
frame2 = ttk.Labelframe(root, text='2.4GHz',padding=5)
frame2.grid(row=1,column=0, columnspan=1, padx=15, pady=10, sticky='nw')
frame3 = ttk.Labelframe(root, text='5GHz',padding=5)
frame3.grid(row=1,column=1, columnspan=1, padx=10, pady=10, sticky='w')

selected_frame = IntVar()

def change_selected_frame():
    if selected_frame.get() == 0:
        for child in frame2.winfo_children():
            child.configure(state='enable')
        for child in frame3.winfo_children():
            child.configure(state='disable')

    elif selected_frame.get() == 1:
        for child in frame2.winfo_children():
            child.configure(state='disable')
        for child in frame3.winfo_children():
            child.configure(state='enable')

    else:
        for child in frame2.winfo_children():
            child.configure(state='disable')
        for child in frame3.winfo_children():
            child.configure(state='disable')

rb1 = ttk.Radiobutton(frame1, text='2.4GHz ', variable=selected_frame, value=0, command=change_selected_frame)
rb1.grid(row=1,column=0,pady=5)
rb2 = ttk.Radiobutton(frame1,text='5GHz', variable=selected_frame, value=1, command=change_selected_frame)
rb2.grid(row=1,column=1,pady=5)

class val_2G:
    def __init__(self,name,set_frame,row_no):
        self.bool=BooleanVar()
        self.bool.set(False)
        self.name=name
        self.Cbtn=ttk.Checkbutton(set_frame, text=self.name, variable=self.bool)
        self.Cbtn.grid(row=row_no,column=0, columnspan=1, padx=15, pady=5, sticky='w')

class val_5G:
    def __init__(self,name,set_frame,row_no):
        self.bool=BooleanVar()
        self.bool.set(False)
        self.name=name
        self.Cbtn=ttk.Checkbutton(set_frame, text=self.name, variable=self.bool)
        self.Cbtn.grid(row=row_no,column=0, columnspan=1, padx=15, pady=5, sticky='w')

val_2G1=val_2G('CH1',frame2,6)
val_2G2=val_2G('CH2',frame2,7)
val_2G3=val_2G('CH3',frame2,8)
val_2G_list=[val_2G1, val_2G2, val_2G3]

val_5G36=val_5G('CH36',frame3,6)
val_5G40=val_5G('CH40',frame3,7)
val_5G44=val_5G('CH44',frame3,8)
val_5G_list=[val_5G36, val_5G40, val_5G44]

def check_all_2G_checkboxes():
    for val in val_2G_list:
        val.bool.set(True)

def clear_all_2G_checkboxes():
    for val in val_2G_list:
        val.bool.set(False)

def check_all_5G_checkboxes():
    for val in val_5G_list:
        val.bool.set(True)

def clear_all_5G_checkboxes():
    for val in val_5G_list:
        val.bool.set(False) 

def check_box():
    selected_channel=''

    for val in val_2G_list:
        if val.bool.get():
            if selected_channel=='':
                selected_channel+=val.name
            else:
                selected_channel+=' & '+val.name

    for val in val_5G_list:
        if val.bool.get():
            if selected_channel=='':
                selected_channel+=val.name
            else:
                selected_channel+=' & '+val.name

    print(selected_channel)

def quit(): 
    root.destroy() 

btn1 = ttk.Button(frame2, text='全選択', padding=5, command=check_all_2G_checkboxes)
btn1.grid(row=5,column=0,pady=5)

btn2 = ttk.Button(frame2, text='全解除', padding=5, command=clear_all_2G_checkboxes)
btn2.grid(row=5,column=1,pady=5)

btn3 = ttk.Button(frame3, text='全選択', padding=5, command=check_all_5G_checkboxes)
btn3.grid(row=5,column=0,pady=5)

btn4 = ttk.Button(frame3, text='全解除', padding=5, command=clear_all_5G_checkboxes)
btn4.grid(row=5,column=1,pady=5)

btn5 = ttk.Button(text='測定', padding=5, command=check_box)
btn5.grid(row=5,column=0,pady=5)

btn6 = ttk.Button(text='中止', padding=5, command=quit)
btn6.grid(row=5,column=1,pady=5)

selected_frame.set(-1) 
change_selected_frame() 

root.mainloop()

選択されたラジオボタン、チェックボタンの情報をもとに次のコードを設定したいのですが、
どのように関数を組み込めばいいのか解りません。

from selenium import webdriver
driver = webdriver.Firefox()
driver.get('http://router.asus.com')

driver.find_element_by_id('login_username').send_keys('admin')
driver.find_element_by_name('login_passwd').send_keys('password')
driver.find_element_by_class_name('button').click()

driver.maximize_window()
driver.get('http://router.asus.com/Advanced_Wireless_Content.asp')

from selenium.webdriver.support.ui import Select

f2g = driver.find_elements_by_name('wl_unit')
Select(f2g[2]).select_by_value("0") # ← 周波数帯域選択、0か1の値

f2g = driver.find_element_by_name('wl_channel')
f2g_ch = Select(f2g)
f2g_ch.select_by_value("3") # ← チャンネル指定(周波数帯域選択が1の場合[1,2,3] 選択が1の場合[36,40,44])

driver.find_element_by_id('applyButton').click()

from selenium.webdriver.common.alert import Alert
Alert(driver).accept()

コード

初心者のため解り辛いコードで大変申しわけございません。

もしご存知の方がいたらご教授いただけないでしょうか。
よろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

1.
まずは測定するチャンネルの扱いですが、現状の実装では "&" で結合した文字列としておりますが、リストに格納するほうが良いかと思います。

あとは、このリストを引数とした測定用の関数(ここでは仮にmeasure_channels()としております)を呼ぶだけです。

def check_box():
    # チャンネルを格納するためのリストを準備
    selected_channels = []
    # 2.4GHz選択中
    if selected_frame.get() == 0:
        for val in val_2G_list:
            # チェックボックスがチェックされているものをリストに格納
            if val.bool.get():
                selected_channels.append(val.name)
    # 5GHz選択中
    elif selected_frame.get() == 1:
        for val in val_5G_list:
            # チェックボックスがチェックされているものをリストに格納
            if val.bool.get():
                selected_channels.append(val.name)
    # リストが空でなかったら測定をおこなう関数を呼ぶ
    if len(selected_channels) > 0:
        measure_channels(selected_channels)

2.
測定用の関数(measure_channels())は基本的に質問の2つ目のコードをそのまま実装して行くことになるかと思いますが、各チャンネル毎の処理は必要な場合はループを使って実装します
下にダミー(何もしない)の実装例を記述しましたので参考にしてください。

現在の実装にて、チェックボックスの名前は "CH1""CH36" のようになっておりますが、下側の測定用のコードでは数値部 "1""36" のみ使用するようでしたので、startswith() にて "CH" から始まっていることをチェックした上で、先頭2文字を削除するようになってます

# 測定を行う(引数 channels は測定するチャンネルのリスト)
def measure_channels(channels):
    # ここに測定用のコードを実装する

    # 各チャンネル毎に処理
    for channel in channels:
        # "CH" から始まっていないチャンネル名の場合はスキップ
        if not channel.startswith('CH'):
            continue
        # 先頭2文字("CH")を削除
        ch = channel[2:]
        print(f'チャンネル {ch} を測定中')
        # ここに各チャンネル毎の処理を記述する
        # (現状は何もしないで1秒待つだけの実装です)
        time.sleep(1)

    print("測定終了")

3.
tkinter に置いて各イベント関数(ボタンを押した際などに呼ばれる関数など)にて時間を要する処理をおこなってしまうと、他のイベント処理を行うことができなくなり Windowが固まった状態になってしまいます。
もし測定用の関数が時間を要する可能性が場合は、その処理を別Threadにて行う方が良いかと思います。

やり方としては簡単で、2で作成した関数を threading.Thread() で指定して、start()にて実行するだけです

import threading # ←追加
# (略)
def check_box():
    # (略)
    # リストが空でなかったら測定をおこなう関数を呼ぶ
    if len(selected_channels) > 0:
        # measure_channels(selected_channels) この部分を下記のように変更
        # measure_channels() 関数を別スレッドにて実行
        thread = threading.Thread(target=measure_channels, args=(selected_channels,))
        thread.start()

あと補足ですが、測定関数を別Threadした場合、測定関数を実行中に再度「測定」ボタンが押され、測定関数が多重に動作する可能性がありますので、測定中は 「測定」ボタンを無効化するなどの対策を施してください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/25 11:24

    magichanさん、どうも有難うございました!
    リストやループ処理はサイトでしらべたのですが、このケースの場合
    どのように落とし込むのかが全く解りませんでした。
    教えていただいたコードを参考にして、ほぼ私が想定していた通りの動作となっております。
    後は色々さわってみようと思います。
    本当に助かりました。

    有難うございました!

    キャンセル

  • 2019/09/27 10:55

    こんにちは。教えていただいたコードに対して少し質問があったので、
    その部分だけ抜き出し新たに質問させていただきました。

    もしご存知でしたらお手すきの際にご回答お願いいたします。

    よろしくお願いいたします。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る