Hi, so I'm currently porting one of my applications (it's a media player) from Tkinter to wxPython and I am having some trouble as this is the first wx application I have attempted. I am trying to create something similar to this. However, I can't figure out the wxPython code for it. I got to the point of creating three listboxes and putting them in a sizer and that worked well; but, once I add static text above them, everything poops out. Here's a picture of what my bug looks like. Here's some code, too:

#!/usr/bin/python

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, (550, 350))

        songs1 = ["Take It Easy", "Before I Forget", "Welcome", "Blitzkreig", "One"]
        songs2 = ["The Fray", "Metallica", "AC/DC", "The Eagles", "Godsmack"]
        songs3 = ["Hell Freezes Over", "Believe", "Indestructible", "All Hope is Gone", "Ten Thousand Fists"]
        
        attrpanel = wx.Panel(self, -1)
        self.songAttr = wx.StaticText(attrpanel, -1, "Songs", (170, 25), style=wx.ALIGN_CENTRE)
        self.artistAttr = wx.StaticText(attrpanel, -1, "Artists", (170, 25), style=wx.ALIGN_CENTRE)
        self.albumAttr = wx.StaticText(attrpanel, -1, "Albums", (170, 25), style=wx.ALIGN_CENTRE)
        
        attrSizer = wx.BoxSizer(wx.HORIZONTAL)
        attrSizer.Add(self.songAttr, 1)
        attrSizer.Add(self.artistAttr, 1)
        attrSizer.Add(self.albumAttr, 1)
        attrpanel.SetSizer(attrSizer)
        self.Centre()
        
        lbpanel = wx.Panel(self, -1)
        self.songBox = wx.ListBox(lbpanel, 1, wx.DefaultPosition, (170, 130), songs1, wx.LB_SINGLE)
        self.artistBox = wx.ListBox(lbpanel, 2, wx.DefaultPosition, (170, 130), songs2, wx.LB_SINGLE) #wx.DefaultPosition
        self.albumBox = wx.ListBox(lbpanel, 3, wx.DefaultPosition, (170, 130), songs3, wx.LB_SINGLE)
        
        lbSizer = wx.BoxSizer(wx.HORIZONTAL)
        lbSizer.Add(self.songBox, 1)
        lbSizer.Add(self.artistBox, 1)
        lbSizer.Add(self.albumBox, 1)
        lbpanel.SetSizer(lbSizer)
        self.Centre()
        
        
        self.songBox.SetSelection(0)
        self.artistBox.SetSelection(0)
        self.albumBox.SetSelection(0)
    
        self.Bind(wx.EVT_BUTTON, self.OnClose, id=wx.ID_CLOSE)
        self.Bind(wx.EVT_LISTBOX, self.SongSelect, id=1)
        self.Bind(wx.EVT_LISTBOX, self.ArtistSelect, id=2)
        self.Bind(wx.EVT_LISTBOX, self.AlbumSelect, id=3)

    def OnClose(self, event):
        self.Close()

    def SongSelect(self, event):
        index = event.GetSelection()
        self.artistBox.SetSelection(index)
        self.albumBox.SetSelection(index)
        
    def ArtistSelect(self, event):
        index = event.GetSelection()
        self.songBox.SetSelection(index)
        self.albumBox.SetSelection(index)
        
    def AlbumSelect(self, event):
        index = event.GetSelection()
        self.songBox.SetSelection(index)
        self.artistBox.SetSelection(index)

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'wxCAKE')
        frame.Centre()
        frame.Show(True)
        return True
    
app = MyApp(0)
app.MainLoop()

What the heck am I doing wrong here?
Thanks in advance.

I have a feeling that you could use a listctrl in a better way. If you use the style wx.LC_REPORT i think it is, you can have a look just like you want in just one widget.

Ill just give you an example.

#!/usr/bin/python

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, (550, 350))

        self.List = wx.ListCtrl(self, wx.ID_ANY, style = wx.LC_REPORT)

        self.List.InsertColumn(0,"Title")
        self.List.InsertColumn(1,"Artist")
        self.List.InsertColumn(2,"Album")

        self.List.Append(("We didn't start the fire", "Billy Joel", "Unknown"))
        self.List.Append(("Take it easy",'Eagles','The complete greatest hits'))

        sizer = wx.BoxSizer()

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'wxCAKE')
        frame.Centre()
        frame.Show(True)
        return True
    
app = MyApp(0)
app.MainLoop()

Hope that helps :) its amazing how much the widget changes just because of changing one style isnt it?

HAve a look at the wx api if you want to know more about the wx.ListCtrl and what you can do with it.
http://www.wxpython.org/docs/api/wx.ListCtrl-class.html

Cheers :)

That is absolutely amazing Paul; this is exactly what I needed. I think you are probably one of the most helpful people in this forum. Anyways, that worked exactly how I wanted. But the one thing I would like to change around a little bit would be the color. I tried looking at the API for it and I could not figure out what it expected for the color argument in the "SetItemBackgroundColour" method. Does it want a tuple with the RGB values? The hex value? The traceback simply says it expects a "number." Also, is it possible to make the background of the main window an image? If so, how? The SetItemColumnImage method seemed quite interesting in that aspect.

Thanks again.

Update: After a little bit of research on my own, I now have an image being displayed in a panel but I cannot add anything else. Is it possible for me to put widgets on top of this "background image"?

Code:

#!/usr/bin/python

import wx

class MyPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, style=wx.RAISED_BORDER)
	
        # accepted formats: .jpg .png .bmp or .gif files
        image_file = 'blah.jpg'
        bmp = wx.Bitmap(image_file)
        self.bitmap = wx.StaticBitmap(self, wx.ID_ANY, bmp, (0, 0))
	self.button1 = wx.Button(self.bitmap, id=-1, label='Button1', pos=(10, 10)) #++Gives "Segmentation Fault"
        self.SetSize((bmp.GetWidth(), bmp.GetHeight()))
        parent.Fit()

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, (550, 350))
	MyPanel(self)

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'wxCAKE')
        frame.Centre()
        frame.Show(True)
        return True

app = MyApp(0)
app.MainLoop()

Thanks again.

Well i can help with your first problem.
I had trouble with this for a bit, but looking at the wxPython Demo's code i noticed that instead of just appending it, they first add a "StringItem" and get the return value of that (which is the index of the string item) and then just add values/colours to that.

#!/usr/bin/python

import wx
import sys

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, (550, 350))

        self.List = wx.ListCtrl(self, wx.ID_ANY, style = wx.LC_REPORT)

        self.List.InsertColumn(0,"Title")
        self.List.InsertColumn(1,"Artist")
        self.List.InsertColumn(2,"Album")

        index =  self.List.InsertStringItem(sys.maxint,"We didn't start the fire")
        self.List.SetStringItem(index, 1, "Billy Joel")
        self.List.SetStringItem(index, 2, "Unknown")
        self.List.SetItemBackgroundColour(index,"light blue")
                                            
        index =  self.List.InsertStringItem(sys.maxint,"Take it easy")
        self.List.SetStringItem(index, 1, 'Eagles')
        self.List.SetStringItem(index, 2, 'The complete greatest hits')
        self.List.SetItemBackgroundColour(index,"green")
       

       

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'wxCAKE')
        frame.Centre()
        frame.Show(True)
        return True
    
app = MyApp(0)
app.MainLoop()

This shows how it is done. You should be able to see the vast difference from the last one, even though it looks like a lot more code, with a smart 'for' loop you should be able to get it a bit cleaner

hope that helps :)

Thanks for the feedback both of you. Problem definitely solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.