anon
anon

Reputation:

Destroy() wxpython simple error?

i am having an interesting problem,

This program is a simple image viewer and it can contain different images in a listbox. The listbox contains the names of the images. You can load an image to an item in the listbox. You can click any item on the listbox to see its image. For some reason Destroy() is not functioning properly. Please run the following code if you are unable to understand me,

IMAGE_NAME=[]
IMAGE_DATA=[]
IMAGE_LISTSEL=[]
import sys
import wx
def deletepic(self,parent):
    try:
        bitmap1.Destroy()
        bmp1.Destroy()
    except:
        print sys.exc_info()
def sendnewpic(self,parent):
    global scroll_img
    deletepic(self,parent)  
    print IMAGE_DATA[IMAGE_LISTSEL[0]]
    if IMAGE_DATA[IMAGE_LISTSEL[0]]!='':
        try:
            print IMAGE_DATA[IMAGE_LISTSEL[0]]
            bmp1 = wx.Image(IMAGE_DATA[IMAGE_LISTSEL[0]], wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            bitmap1 = wx.StaticBitmap(scroll_img, -1, bmp1, (0, 0))
        except:
            pass
def areachange(self,pg):
    print pg
    try:
        if IMAGE_DATA[IMAGE_LISTSEL[0]]=='':
            deletepic(self,parent)
    except:
        pass
    if pg=="Images":
        self.images_area.Show()
    else:
        self.images_area.Hide()
class imageMax(wx.Panel):
    pass

class imageTab(imageMax):
    def imagesel(self,parent):
        IMAGE_LISTSEL[:] = []
        IMAGE_LISTSEL.append(self.listBox.GetSelection())
        sendnewpic(self,parent)
    def newAddImage(self,parent):
        IMAGE_NAME.append('hi');
        IMAGE_DATA.append('');
        self.listBox.Set(IMAGE_NAME)
        self.listBox.SetSelection(len(IMAGE_NAME)-1)
        self.imagesel(self) #making it a selected image, globally

    def reName(self,parent):
        sel = self.listBox.GetSelection()
        text = self.listBox.GetString(sel)
        renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
        if renamed != '':
            IMAGE_NAME.pop(sel)
            IMAGE_NAME.insert(sel,renamed)
            self.listBox.Set(IMAGE_NAME)
            self.listBox.SetSelection(sel)
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.listBox = wx.ListBox(self, size=(200, -1), choices=IMAGE_NAME, style=wx.LB_SINGLE)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
        self.sizerMain = wx.BoxSizer()
        self.listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.reName)
        self.listBox.Bind(wx.EVT_LISTBOX, self.imagesel)
        btn = wx.Button(self, label="Create New",size=(200, 40))
        btnTwo = wx.Button(self, label="Test 2",size=(200, 40))
        btn.Bind(wx.EVT_BUTTON, self.newAddImage)
        self.sizer.Add(self.listBox, proportion=1, flag=wx.TOP | wx.EXPAND | wx.LEFT, border=5)
        btnSizer.Add(btn, 0, wx.ALL, 5)
        btnSizer.Add(btnTwo, 0, wx.ALL, 5)
        self.sizer.Add(btnSizer)
        self.sizerMain.Add(self.sizer, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=0)
        self.SetSizer(self.sizerMain)

class MyNotebook(wx.Notebook):
    def __init__(self, *args, **kwargs):
        wx.Notebook.__init__(self, *args, **kwargs)

class MyPanel(imageTab):

    def OnClickTop(self, event):
        scroll_img.Scroll(600, 400)

    def OnClickBottom(self, event):
        scroll_img.Scroll(1, 1)

    def OnPageChanged(self, event):
        new = event.GetSelection()
        areachange(self,self.notebook.GetPageText(new))
        event.Skip()

    def OnPageChanging(self, event):
        event.Skip()
    def onOpenFile(self,parent):
        """ Open a file"""
        filename = wx.FileSelector()
        if (filename!=''):
            global bitmap1,bmp1,scroll_img
            if IMAGE_DATA[IMAGE_LISTSEL[0]]!='':
                deletepic(self,parent)
            bmp1 = wx.Image(filename, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            bitmap1 = wx.StaticBitmap(scroll_img, -1, bmp1, (0, 0))
            scroll_img.SetScrollbars(1, 1, bmp1.GetWidth(), bmp1.GetHeight())
            IMAGE_DATA[IMAGE_LISTSEL[0]]=filename
            print IMAGE_DATA

    def __init__(self, *args, **kwargs):
        global bitmap1,bmp1,scroll_img
        wx.Panel.__init__(self, *args, **kwargs)
        self.notebook = MyNotebook(self, size=(225, -1))
#        self.button = wx.Button(self, label="Something else here? Maybe!")
        tab_images = imageTab(self.notebook)
        # add the pages to the notebook with the label to show on the tab
        self.notebook.AddPage(tab_images, "Pics",select=True)

        scroll_img = wx.ScrolledWindow(self, -1)
        scroll_img.SetScrollbars(1, 1, 600, 400)
        #self.button = wx.Button(scroll_img, -1, "Scroll Me", pos=(50, 20))
        #self.Bind(wx.EVT_BUTTON,  self.OnClickTop, self.button)
        #self.button2 = wx.Button(scroll_img, -1, "Scroll Back", pos=(500, 350))
        #self.Bind(wx.EVT_BUTTON, self.OnClickBottom, self.button2)

        self.images_area=wx.StaticBox(self, -1, '')
        self.sizerBox = wx.StaticBoxSizer(self.images_area,wx.HORIZONTAL)
        #self.load_file=wx.Button(self, label='Load File')
        #self.sizerBox.Add(self.load_file,0,wx.ALL,5)
        self.sizerBox2 = wx.BoxSizer()
        self.sizerBox.Add(scroll_img, 1, wx.EXPAND|wx.ALL, 10)
        self.sizerBox2.Add(self.sizerBox, 1, wx.EXPAND|wx.ALL, 10)
        self.sizer = wx.BoxSizer()
        self.sizer.Add(self.notebook, proportion=0, flag=wx.EXPAND)
#        self.sizer.Add(self.button, proportion=0)
        btnSizer = wx.BoxSizer() #change to horizontal for side by side
        btnTwo = wx.Button(self, label="Load File",size=(200, 40))
        btnTwo.Bind(wx.EVT_BUTTON,self.onOpenFile)

        bmp1 = None
        bitmap1 = None

        btnSizer.Add(btnTwo, 0, wx.TOP, 15)
        self.sizerBox2.Add(btnSizer)
        #self.sizerBox.Add(self.bitmap1)
        self.sizer.Add(self.sizerBox2, proportion=1, flag=wx.EXPAND)

        self.SetSizer(self.sizer)
        self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
        areachange(self,self.notebook.GetPageText(0))

class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.panel = MyPanel(self)

        self.Show()

app = wx.App(False)
win = MainWindow(None, size=(600, 400))
app.MainLoop()

Try this to see what the error is, 1.you press create new (any amount of times) 2.press, load file 3. click any item on the listbox (except for the one that you are in) 4. Then go back to the orginal item that you were in, 5. Then click any item, other than the one you are currently in

There will be some sort of problem, the image does not destroy itself and returns an error like the following: (, PyDeadObjectError('The C++ part of the StaticBitmap object has been deleted, attribute access no longer allowed.',), ) I am still able to load images but the previous images do not delete.

It is hard to word this problem, if anyone can help me with this situation, it would be greatly appreciated. If you need further explanation please comment. I thank you greatly for viewing.

Upvotes: 2

Views: 751

Answers (2)

joaquin
joaquin

Reputation: 85603

Here you have your code fixed to clear your current image when loading another one. This is done basically using self.parent.bitmap.Destroy().

I modified some few things without changing the structure of your code, in order for you to recognize changes. I eliminated globals calls. Look how I also eliminated the global IMAGE_LISTSEL variable and converted it in a class attribute. That is what Robin and Fenikso were telling you. Try to do the same with IMAGE_NAME and IMAGE_DATA.

Although the code is working, it is still far from being acceptable wxpython code. You can get many examples of correctly written wxpython code in the web. If you can afford it I recommend to you wxPython in Action from Noel Rappin and Robin Dunn.

IMAGE_NAME = []
IMAGE_DATA = []

import sys
import wx

def deletepic(self):
    try:
        self.parent.bitmap.Destroy()
    except:
        print sys.exc_info()

def sendnewpic(self):
    if self.parent.bitmap: deletepic(self)  
    if IMAGE_DATA[self.image_listsel] != '':
        try:
            print IMAGE_DATA[self.image_listsel]
            bmp = wx.Image(IMAGE_DATA[self.image_listsel], wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            self.parent.scroll_img.SetScrollbars(1, 1, bmp.GetWidth(), bmp.GetHeight())
            self.parent.bitmap = wx.StaticBitmap(self.parent.scroll_img, -1, bmp, (0, 0))
            self.parent.Refresh()
        except:
            pass

def areachange(self, pg):
    print pg
    try:
        if IMAGE_DATA[self.image_listsel] == '':
            deletepic(self)
    except:
        pass

    if pg == "Images":
        self.images_area.Show()
    else:
        self.images_area.Hide()


class imageTab(wx.Panel):

    def __init__(self, parent, grandparent):
        wx.Panel.__init__(self, parent)
        self.parent = grandparent
        self.image_listsel = 0
        self.listBox = wx.ListBox(self, size=(200, -1), choices=IMAGE_NAME, style=wx.LB_SINGLE)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
        self.sizerMain = wx.BoxSizer()
        self.listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.reName)
        self.listBox.Bind(wx.EVT_LISTBOX, self.imagesel)
        btn = wx.Button(self, label="Create New",size=(200, 40))
        btnTwo = wx.Button(self, label="Test 2",size=(200, 40))
        btn.Bind(wx.EVT_BUTTON, self.newAddImage)
        self.sizer.Add(self.listBox, proportion=1, flag=wx.TOP | wx.EXPAND | wx.LEFT, border=5)
        btnSizer.Add(btn, 0, wx.ALL, 5)
        btnSizer.Add(btnTwo, 0, wx.ALL, 5)
        self.sizer.Add(btnSizer)
        self.sizerMain.Add(self.sizer, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=0)
        self.SetSizer(self.sizerMain)

    def imagesel(self, evt):
        self.image_listsel = self.listBox.GetSelection()
        sendnewpic(self)

    def newAddImage(self, evt):
        IMAGE_NAME.append('hi')
        IMAGE_DATA.append('')
        self.listBox.Set(IMAGE_NAME)
        self.listBox.SetSelection(len(IMAGE_NAME)-1)
        self.imagesel(None) #making it a selected image, globally

    def reName(self,parent):
        sel = self.listBox.GetSelection()
        text = self.listBox.GetString(sel)
        renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
        if renamed != '':
            IMAGE_NAME.pop(sel)
            IMAGE_NAME.insert(sel,renamed)
            self.listBox.Set(IMAGE_NAME)
            self.listBox.SetSelection(sel)


class MyPanel(wx.Panel):

    def __init__(self, *args, **kwargs):

        wx.Panel.__init__(self, *args, **kwargs)
        self.notebook = wx.Notebook(self, size=(225, -1))
# 
        self.tab_images = imageTab(self.notebook, self)
        # add the pages to the notebook with the label to show on the tab
        self.notebook.AddPage(self.tab_images, "Pics", select=True)

        self.scroll_img = wx.ScrolledWindow(self, -1)
        self.scroll_img.SetScrollbars(1, 1, 600, 400)

        self.images_area = wx.StaticBox(self, -1, '')
        self.sizerBox = wx.StaticBoxSizer(self.images_area, wx.HORIZONTAL)

        self.sizerBox2 = wx.BoxSizer()
        self.sizerBox.Add(self.scroll_img, 1, wx.EXPAND|wx.ALL, 10)
        self.sizerBox2.Add(self.sizerBox, 1, wx.EXPAND|wx.ALL, 10)
        self.sizer = wx.BoxSizer()
        self.sizer.Add(self.notebook, proportion=0, flag=wx.EXPAND)
#
        btnSizer = wx.BoxSizer() #change to horizontal for side by side
        btnTwo = wx.Button(self, label="Load File", size=(200, 40))
        btnTwo.Bind(wx.EVT_BUTTON, self.onOpenFile)

        self.bmp = None
        self.bitmap = None

        btnSizer.Add(btnTwo, 0, wx.TOP, 15)
        self.sizerBox2.Add(btnSizer)
        #
        self.sizer.Add(self.sizerBox2, proportion=1, flag=wx.EXPAND)

        self.SetSizer(self.sizer)
        self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
        areachange(self, self.notebook.GetPageText(0))

    def OnClickTop(self, event):
        self.scroll_img.Scroll(600, 400)

    def OnClickBottom(self, event):
        self.scroll_img.Scroll(1, 1)

    def OnPageChanged(self, event):
        new = event.GetSelection()
        areachange(self, self.notebook.GetPageText(new))
        event.Skip()

    def OnPageChanging(self, event):
        event.Skip()

    def onOpenFile(self, evt):
        """ Open a file"""
        filename = wx.FileSelector()
        if filename != '':
            IMAGE_DATA[ self.tab_images.image_listsel] = filename
            self.tab_images.imagesel(None)
            print IMAGE_DATA


class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.panel = MyPanel(self)
        self.Show()


app = wx.App(False)
win = MainWindow(None, size=(600, 400))
app.MainLoop()

Upvotes: 3

RobinDunn
RobinDunn

Reputation: 6306

Sometimes you are using bmp1 and bitmap1 as local variables and sometimes as globals. Since you are making multiple instances of them without saving the prior references anywhere then you are losing your references to the already existing objects. When you Destroy() them then you are only destroying the most recently created instances.

Try adding them to some sort of collection (like a list) instead and then you can access any of the items from the list when you need them later. Also try to avoid using global variables. Store your variables in the object instances that they belong to.

Upvotes: 0

Related Questions