Search code examples
comboboxevent-handlingwxpython

How to update a combo box with a list of items


I am trying to update the list of items in one combobox2 depending on the item selected in another - combobox1.

For example, if the user selects a file.mp3 in combobox1 then combobox2 will display a list of audio extension (.aac, .wav, .wma). However, if the user selects a file.flv from combobox1, combobox2 will display a list of video extensions (.mpg, mp4, .avi, .mov).

I initially thought I could accomplish this with if statements. The initial selection works, but there after, if you continue to choose different files, the combobox2 is not updated. I tried using an Event, but it didn't work.

Below if a very stripped-down version of the code so that you can get the gist:

import wx
import os
import sys
import time
from wx.lib.delayedresult import startWorker

class udCombo(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'd-Converter', size=(500, 310))
        panel = wx.Panel(self, wx.ID_ANY)#Creates a panel over the widget
        toolbar = self.CreateToolBar()
        toolbar.Realize()

        font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        font2 = wx.Font(7, wx.DECORATIVE, wx.NORMAL, wx.NORMAL)

        directory = wx.StaticText(panel, -1, 'Path to media files: c:\\ffmpeg\\bin', (300, 13))
        directory.SetFont(font2)

        convertfile = wx.StaticText(panel, -1, 'File:', (270, 53))
        convertfile.SetFont(font)

        convertfile2 = wx.StaticText(panel, -1, 'Format:', (245, 83))

        #Select Media
        os.chdir("c:\\ffmpeg\\bin")
        wrkdir = os.getcwd()
        filelist = os.listdir(wrkdir)
        self.formats1 = []

        for filename in filelist:
            (head, filename) = os.path.split(filename)
            if filename.endswith(".avi") or filename.endswith(".mp4") or filename.endswith(".flv") or filename.endswith(".mov") or filename.endswith(".mpeg4") or filename.endswith(".mpeg") or filename.endswith(".mpg2") or filename.endswith(".wav") or filename.endswith(".mp3"):
                self.formats1.append(filename)
        self.format_combo1=wx.ComboBox(panel, size=(140, -1),value='Select Media', choices=self.formats1, style=wx.CB_DROPDOWN, pos=(300,50))

        self.Bind(wx.EVT_COMBOBOX, self.fileFormats, self.format_combo1)

        self.format_combo2=wx.ComboBox(panel, size=(100, -1),pos=(300,81))
        self.Bind(wx.EVT_COMBOBOX, self.fileFormats, self.format_combo2)

    def fileFormats(self, e):
    myFormats = {'audio': ('.wav', '.wma', '.mp3'), 'video': ('.mpg', '.mp4', '.mpeg')}
    bad_file = ['Media not supported']
    myFile = self.format_combo1.GetValue()
    f_exten = [x for x in myFormats['audio'] or myFormats['video'] if myFile.endswith(x)]


    if f_exten[0] in myFormats['audio']:
        self.format_combo2.SetItems(myFormats['audio'])

    elif f_exten[0] in myFormats['video']:
        self.format_combo2.SetItems(myFormats['video'])
    else:
        self.format_combo2.SetItems(bad_file)


if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = udCombo()
    frame.SetSizeHints(500,310,500,310)
    frame.Show()
    app.MainLoop()

Traceback error:

Traceback (most recent call last):
File "C:\Users\GVRSQA004\Desktop\udCombo.py", line 86, in fileFormats
if f_exten[0] in myFormats['audio']:
IndexError: list index out of range

Solution

  • Use a dictionary to hold the two lists. Then when the user clicks something in the first widget, you can call the second combobox's SetItems(myDict[selection]) method or something along those lines. The error message is because you're trying to do something with a CommandEvent that it doesn't support. They don't have an "rfind" attribute, for example.

    EDIT: The new code the OP posted doesn't work because it's only running the list comprehension against the first half of the OR statement. It never runs against the "video" portion, so it returns an empty list if the user chooses anything with a video format extension. It WILL work if you select an audio selection.

    Personally, I would recommend creating a video extension list and an audio list. That would be easier to understand in the future should you need to fix it later.