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

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

ただいまの
回答率

88.06%

python wxCheckListBoxの使い方

解決済

回答 2

投稿

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

score 2

前提・実現したいこと

初心者です。python3で、wxFormBuilderを使いチェックリスト付きのバックアップソフトを作ろうと思っています。
2度目の投稿ですが、wx.CheckListBoxの仕組みがよく分かりません。

チェックリストの全選択、全選択解除、また、前回終了時に選択していたチェックの復元(他ファイルに保存を考えています)を実現したいのです。
以前の質問時に、wx.CheckListBoxを紹介してもらいましが、

wxCheckListBox::Check
void Check(int item, bool check = TRUE)

がうまく使えませんでした。

以下がsorceです。

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

###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc

###########################################################################
## Class MyFrame1
###########################################################################

class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 203,167 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )

        bSizer1 = wx.BoxSizer( wx.VERTICAL )

        self.m_staticText1 = wx.StaticText( self, wx.ID_ANY, u"バックアップするよ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText1.Wrap( -1 )

        bSizer1.Add( self.m_staticText1, 0, wx.ALL, 5 )

        m_checkList1Choices = [u"file1", u"file2", u"file3"]
        self.m_checkList1 = wx.CheckListBox( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_checkList1Choices, 0 )
        bSizer1.Add( self.m_checkList1, 0, wx.ALL, 5 )

        self.m_button1 = wx.Button( self, wx.ID_ANY, u"実行", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer1.Add( self.m_button1, 0, wx.ALL, 5 )

        self.all_button3 = wx.Button( self, wx.ID_ANY, u"全選択", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer8.Add( self.all_button3, 0, wx.ALL, 5 )

        self.no_button5 = wx.Button( self, wx.ID_ANY, u"全解除", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer8.Add( self.no_button5, 0, wx.ALL, 5 )

        self.SetSizer( bSizer1 )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.m_button1.Bind( wx.EVT_BUTTON, self.m_button1OnButtonClick )
        self.all_button3.Bind( wx.EVT_BUTTON, self.all_button3OnButtonClick )
        self.no_button5.Bind( wx.EVT_BUTTON, self.no_button5OnButtonClick )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def m_button1OnButtonClick( self, event ):
        event.Skip()

    def all_button3OnButtonClick( self, event ):
        **__ここにコード__**
        event.Skip()
    def all_button5OnButtonClick( self, event ):
        **__ここにコード__**
        event.Skip()

よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

void Check(int item, bool check = TRUE)がうまく使えませんでした。

item には、要素の添字(ゼロ開始)を指定します。

# Check() の使い方。第2引数は True: 選択 / False: 解除

for item in range(self.m_checkList1.Count): # 全要素を対象に...
    self.m_checkList1.Check(item, True)

# 別解: 全選択 / 全解除
self.m_checkList1.SetCheckedItems(range(self.m_checkList1.Count))
self.m_checkList1.SetCheckedItems([]) # 空リストを指定で全解除

選択中の項目/表示名を得るには、
GetCheckedItems(), GetCheckedStrings() が使えます。

Items の値は、要素の内容が変わると変更される点には注意してください。


追記: 表示名を記録する場合の復元方法

checkedList = [] # 選択されたラベルのリスト (ファイルに記録する内容)
def button_save(event):
    global checkedList
    checkedList = self.m_checkList1.GetCheckedStrings()

def button_load(event):
    # FindString で項目が何番目かを探索
    # 選択された項目のリスト→ 選択されたitemリスト に変換。
    items = map(self.m_checkList1.FindString, labels)
    items = [x for x in items if x != wx.NOT_FOUND] # 項目が見つからなかった場合を省く
    self.m_checkList1.SetCheckedItems(items)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2021/05/04 21:52

    素早い回答、ありがとうございます。
    全選択、解除はこれでいいんですね。簡単で素晴らしいです。
    (結局void…は分かりませんが…)

    もう一つお聞きしたいのですが、選択中の項目を得る方法は分かりましたが、
    最初にいくつかの項目にチェックを入れる方法が分かりません。

    TFlist = [True,False,True] #1と3にチェックが入った状態にしたい
    for item in range(self.m_checkList1.Count): # 全要素を対象に...
    self.m_checkList1.Check(item, TFlist[item])

    などと書いてみましたが、エラーになります。
    すいませんが、お教えください。

    キャンセル

  • 2021/05/05 01:01

    void は wxWidgets (C++) の型の記述ですね。
    戻り値がないという意味なので、気にしなくても大丈夫です。
    wxPython のドキュメントには書かれてないはずです。

    1と 3 にチェックを入れたい場合は、
    その添字 0開始なので -1した値の[0, 2] をSetCheckedItemsに渡します。

    for文で一つづつ設定する場合は、enumerate() 関数を使った繰り返しで

    TFlist = [True, False, True]
    for item, checked in enumerate(TFlist):
      self.m_checkList1.Check(item, checked)

    ※コメント中の為、↑インデントは全角スペースを使ってます。

    enumerate() を使う事で、TFileの要素の値(checked=True or False)と、
    必要なitemの値(0開始のインデックス)を得られます。

    繰り返し時の変数の内容
    item=0, checked=True
    item=1, checked=False
    item=2, checked=True

    ----
    エラーはどのようなエラーですか?

    推測できる範囲では、
    TFlist[item] としてるので、Count が4以上であれば
    リストの範囲外で、IndexError になると思います。

    キャンセル

  • 2021/05/05 10:51

    エラー内容は
    TypeError: CheckListBox.Check(): argument 1 has unexpected type 'str'
    でした。

    調べたら、TFlist = [ ]の内容をテキストファイルから引用していたため、文字列として認識していたのが原因でした…。
    str を bool に変換してできました!
    ありがとうございました!助かりました!

    キャンセル

0

前回のチェックしたリストを、'checklist.txt'に保存してあります。
True,False,False,… とリストの要素数分書いてあります。

old_checklist = [実行ファイルのパス] + "\\" + 'checklist.txt'
with open(old_checklist , "r") as tf:
    lines = tf.read().split(',')

tflist = list(lines)

def str2bool(s):
     return s.lower() in ['true']   ※'True'と大文字だとなぜかFalseになりますが…

TFchecklist = [ str2bool(t) for t in tflist ]

for item, checked in enumerate(TFchecklist):
    self.m_checkList1.Check(item, checked)

汚いコードかもしれませんが、これでチェックリストにチェックがつきました。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2021/05/05 15:02

    チェック状態のリストを保存する場合、
    選択肢の途中追加に対応できませんが大丈夫ですか?

    例えば、項目に Apple, Grape, Orange とあって、
    Apple, Orange を選択 True, False, True のデータを保存。
    2番目に Banana を追加した場合、項目がずれて
    Apple, Grape を選択になってしまいます。

    選択肢が固定で後から絶対変更がない項目であれば大丈夫ですが、
    仕様変更に対応できないので、
    対応したい場合は、表示名をファイルに保存して、
    itemの値(何番目の要素かを調べる) 逆引きが必要になるかもしれません。

    キャンセル

  • 2021/05/05 16:43

    なるほど。ありがとうございます。
    今のところは、選択肢が増えることはなさそうなのですが、
    仕様変更はありえることですので、逆引きも考えてみます。

    何度もお答えいただき、ありがとうございます。

    キャンセル

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

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

関連した質問

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