wxpython notebook - creating new pages - python

I'm new here and I'm newbie in coding (since April, this year) so please be gentle ;-)
This is my simplified code. Each time I'm creating new page in the notebook by clicking "ClickMe" button. My question is: Is there any option to not use if/elif statement? There will be 10 pages or more, so a want to avoid typing each time similar code. Are there any way to use dynamically creating variable (self.page...)?
import wx
class PageOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
wx.StaticText(self, -1, pos = (10,10), label = "Test")
class PageTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
wx.StaticText(self, -1, pos = (10,10), label = "Test 2")
self.text = wx.TextCtrl(self,-1, pos = (100,10))
def OnLoad(self, text):
self.text.AppendText(str(text))
class MainFrame(wx.Frame):
def __init__(self, parent, id, title, pos, size):
wx.Frame.__init__(self, parent, id, title, pos, size)
panel = wx.Panel(self)
self.nb = wx.Notebook(panel)
self.page1 = PageOne(self.nb)
self.nb.AddPage(self.page1, "PAGE 1")
self.button = wx.Button(self.page1, -1, pos = (100,10), label = "ClickMe")
self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
sizer = wx.BoxSizer()
sizer.Add(self.nb, 1, wx.EXPAND)
panel.SetSizer(sizer)
def OnClick(self, event):
page_number = self.nb.GetPageCount()
if page_number == 1:
self.page2 = PageTwo(self.nb)
self.nb.AddPage(self.page2, "PAGE 2")
self.page2.OnLoad("PAGE 2")
elif page_number == 2:
self.page3 = PageTwo(self.nb)
self.nb.AddPage(self.page3, "PAGE 3")
self.page3.OnLoad("PAGE 3")
elif page_number == 3:
self.page4 = PageTwo(self.nb)
self.nb.AddPage(self.page4, "PAGE 4")
self.page4.OnLoad("PAGE 4")
class App(wx.App):
def OnInit(self):
self.frame = MainFrame(None, -1, "Notebook", (250,50), (500,500))
self.frame.Show()
return True
app = App(False)
app.MainLoop()
I found here many useful informations and I hope that someone will help me with this issue or show me the right way (if I'm making some stupid mistake/assumption).

I would put all the pages in a list instead of having them as separate attributes.
def __init__(self, parent, id, title, pos, size):
#...
self.pages = [PageOne(self.nb)]
#...
def OnClick(self, event):
page = self.nb.GetPageCount() + 1
# Or: page = len(self.pages) + 1
self.pages.append(PageTwo(self.nb))
self.nb.AddPage(self.pages[page], "PAGE %d" % page)
self.pages[page].OnLoad("PAGE %d" % page)

Related

Wxpython Phoenix - Multiple OnDropFiles boxes with TABS

I have a python 3 (wxpython phoenix) app which has two TABs, each TAB has a OnDropFiles box, but I just can't get it working. I have a simple stripped down example below, which should print the file URL on each drop, but not working, if someone could show a working example please, or point me in the right direcion, I would be very gratefull.
I'm using Python 3.10.5 and wxpython 4.2.
import wx
class ScrolledWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(510, 330), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER |
wx.MAXIMIZE_BOX))
run_params = {}
self.tabbed = wx.Notebook(self, -1, style=(wx.NB_TOP))
self.filePrep = PrepFile(self.tabbed, self, run_params)
self.fileCheck = CheckFile(self.tabbed, self, run_params)
self.tabbed.AddPage(self.filePrep, "File Prep")
self.tabbed.AddPage(self.fileCheck, "File Check")
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.switchSize)
self.Centre()
self.Show()
def switchSize(self, e):
page = self.tabbed.GetPageText(self.tabbed.GetSelection())
if page == 'File Prep':
self.SetSize((510, 330))
elif page == 'File Check':
self.SetSize((510, 510))
self.fileCheck.setSubmissionDrop(self)
class PrepFile(wx.Panel):
def __init__(self, parent, frame, run_params):
wx.Panel.__init__(self, parent)
self.run_params = run_params
self.parent = parent
self.frame = self
self.selectedFiles = ""
outputtxt3 = '''Drag and Drop files'''
wx.StaticText(self, -1, outputtxt3, pos=(25, 180), style=wx.ALIGN_CENTRE)
self.drop_target = MyFileDropTarget(self)
self.SetDropTarget(self.drop_target)
self.tc_files = wx.TextCtrl(self, wx.ID_ANY, pos=(28, 200), size=(360, 25))
self.tc_files.SetFocus()
self.Show()
def setSubmissionDrop(self, dropFiles):
"""Called by the FileDropTarget when files are dropped"""
print(dropFiles)
self.tc_files.SetValue(','.join(dropFiles))
self.selectedFiles = dropFiles
class CheckFile(wx.Panel):
def __init__(self, parent, frame, run_params):
wx.Panel.__init__(self, parent)
self.run_params = run_params
self.parent = parent
self.frame = self
self.selectedFiles = ""
wx.StaticText(self, -1, '''Drag and Drop files''', pos=(25, 10), style=wx.ALIGN_CENTRE)
self.drop_target = MyFileDropTarget(self)
self.SetDropTarget(self.drop_target)
self.tc_files = wx.TextCtrl(self, wx.ID_ANY, pos=(25, 30), size=(302, 25))
self.tc_files.SetFocus()
self.Show()
def setSubmissionDrop(self, dropFiles):
"""Called by the FileDropTarget when files are dropped"""
print(dropFiles)
self.selectedFiles = dropFiles
class MyFileDropTarget(wx.FileDropTarget):
""""""
def __init__(self, window):
wx.FileDropTarget.__init__(self)
self.window = window
def OnDropFiles(self, x, y, filenames):
print(filenames)
self.window.setSubmissionDrop(filenames)
return True
app = wx.App()
ScrolledWindow(None, -1, 'File Prep ')
app.MainLoop()
We want this to be event driven, so you should define an event, from wx.lib.newevent.
I assume you want the drop zone to be the textctrl not the whole panel, so it's that that needs to be set as the target.
BIND the event.
In the FileDropTarget class we define the event and fire it.
In each drop event callback, we accept the event as a parameter and unpack whatever we packed into the event.
One last thing, in this case, you are getting back a list.
It's simple but every time you decide to use it, it trips you up, I don't know why.
import wx
import wx.lib.newevent
drop_event, EVT_DROP_EVENT = wx.lib.newevent.NewEvent()
class ScrolledWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(510, 330), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER |
wx.MAXIMIZE_BOX))
run_params = {}
self.tabbed = wx.Notebook(self, -1, style=(wx.NB_TOP))
self.filePrep = PrepFile(self.tabbed, self, run_params)
self.fileCheck = CheckFile(self.tabbed, self, run_params)
self.tabbed.AddPage(self.filePrep, "File Prep")
self.tabbed.AddPage(self.fileCheck, "File Check")
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.switchSize)
self.Centre()
self.Show()
def switchSize(self, e):
page = self.tabbed.GetPageText(self.tabbed.GetSelection())
if page == 'File Prep':
self.SetSize((510, 330))
elif page == 'File Check':
self.SetSize((510, 510))
class PrepFile(wx.Panel):
def __init__(self, parent, frame, run_params):
wx.Panel.__init__(self, parent)
self.run_params = run_params
self.parent = parent
self.frame = self
self.selectedFiles = ""
outputtxt3 = '''Drag and Drop files'''
wx.StaticText(self, -1, outputtxt3, pos=(25, 180), style=wx.ALIGN_CENTRE)
self.tc_files = wx.TextCtrl(self, wx.ID_ANY, pos=(28, 200), size=(360, 25))
self.drop_target = MyFileDropTarget(self)
self.tc_files.SetDropTarget(self.drop_target)
self.Bind(EVT_DROP_EVENT, self.setSubmissionDrop)
self.tc_files.SetFocus()
self.Show()
def setSubmissionDrop(self, event):
"""Called by the FileDropTarget when files are dropped"""
files = event.data
print("\nprep event", files)
self.tc_files.SetValue(','.join(files))
self.selectedFiles = files
class CheckFile(wx.Panel):
def __init__(self, parent, frame, run_params):
wx.Panel.__init__(self, parent)
self.run_params = run_params
self.parent = parent
self.frame = self
self.selectedFiles = ""
wx.StaticText(self, -1, '''Drag and Drop files''', pos=(25, 10), style=wx.ALIGN_CENTRE)
self.tc_files = wx.TextCtrl(self, wx.ID_ANY, pos=(25, 30), size=(302, 25))
self.drop_target = MyFileDropTarget(self)
self.tc_files.SetDropTarget(self.drop_target)
self.Bind(EVT_DROP_EVENT, self.setSubmissionDrop)
self.tc_files.SetFocus()
self.Show()
def setSubmissionDrop(self, event):
"""Called by the FileDropTarget when files are dropped"""
files = event.data
print("\ncheck event", files)
self.tc_files.SetValue(','.join(files))
self.selectedFiles = files
class MyFileDropTarget(wx.FileDropTarget):
""""""
def __init__(self, window):
wx.FileDropTarget.__init__(self)
self.obj = window
def OnDropFiles(self, x, y, filenames):
drp_evt = drop_event(data=filenames)
wx.PostEvent(self.obj, drp_evt)
return True
app = wx.App()
ScrolledWindow(None, -1, 'File Prep ')
app.MainLoop()

Start a hidden panel with wxpython

I want to start an app with several panels hidden from the user and show them per request when interacting with the menu.
So far the `budget_panel' that I want to be initially hidden is always on display.
My code is as follows (likely it can be dramatically improved as it is my first time using wxwidgets and OOP in Python).
#!/usr/bin/python3
import sqlite3
import wx
class DB():
def __init__(self):
self.db = sqlite3.connect(':memory:')
self.cursor = self.db.cursor()
self.cursor.execute('CREATE TABLE invoices (id INT PRIMARY KEY, client TEXT)')
self.cursor.execute('INSERT INTO invoices (client) VALUES ("Empresa A")')
self.db.commit()
def myget(self, id):
return self.cursor.execute('SELECT * FROM {}'.format(id)).fetchall()
class BudgetPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.SetSizer(sizer)
self.choices = ["Empresa A", "Empresa B"]
self.choice = wx.Choice(parent, id=wx.ID_ANY, choices = self.choices)
sizer.Add(self.choice)
class EmptyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent = parent)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
text = wx.StaticText(self, -1, 'Text', style = wx.ALIGN_CENTER | wx.TE_READONLY)
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Empresa",
size=(800,600))
self.db = DB()
self.menu()
self.empty_panel = EmptyPanel(self)
self.budget_panel = BudgetPanel(self)
self.panels = {1000 : self.empty_panel, 2001 : self.budget_panel}
for key in self.panels.keys():
if key == 1000:
self.panels[key].Show()
else:
self.panels[key].Hide()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.empty_panel, 1, wx.EXPAND)
self.sizer.Add(self.budget_panel, 1, wx.EXPAND)
self.SetSizer(self.sizer)
def menu(self):
menubar = wx.MenuBar()
main_menu = wx.Menu()
budget_menu = main_menu.Append(2001, 'Presupuestos')
self.Bind(wx.EVT_MENU, self.change_panel, budget_menu)
menubar.Append(main_menu, '&GestiĆ³n')
self.SetMenuBar(menubar)
def change_panel(self, event):
for key in self.panels.keys():
if event.GetId() == key:
self.panels[key].Show()
else:
self.panels[key].Hide()
self.Layout()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
'''

On button click open wxpython TextEntryDialog and get multiple input from user

I want to open a TextEntryDialog, when user clicks the button. So if i have a button in the parent frame which i am going to bind this way:
self.Bind(wx.EVT_BUTTON, self.OnAddNew, self.add_new_btn)
Now i have to open a TextEntryDialog when user clicks the button add_new. I want to make textentrydialog somewthing like this
Python, Using wxPython to get multiple input from user
How can i do that? Do i need to just paste that code in ` def OnAddNew(self, event):
Here is the pastebin link to my code: https://pastebin.com/UEYscgFa
I have created class inside a function, so is it possible to do in that way?
NO!
GetData is a class in its own right.
That code already provides you with the method.
The MyFrame is all fluff, to create a standalone working example.
def OnButton(self,event):
dlg = GetData(parent = self.panel)
dlg.ShowModal()
if dlg.result_name:
self.log.AppendText("Name: "+dlg.result_name+"\n")
self.log.AppendText("Surname: "+dlg.result_surname+"\n")
self.log.AppendText("Nickname: "+dlg.result_nickname+"\n")
else:
self.log.AppendText("No Input found\n")
dlg.Destroy()
Edit: I don't understand where the instructions in my comments eluded you but for my sins, here is your code cleaned up and edited as in the comments.
import sqlite3
import wx
import os
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title, size=(1000,800))
self.inter_list = list()
self.plot_list = list()
self.InitUI()
self.Layout()
self.Centre()
self.Show()
def InitUI(self):
self.p = wx.Panel(self)
bs = wx.BoxSizer(wx.VERTICAL)
gs = wx.GridSizer(10, 18, 5, 5)
bs.Add(gs, 1, wx.EXPAND)
self.search_btn=wx.Button(self.p,-1,"Search!")
self.search_btn.Bind(wx.EVT_BUTTON, self.OnSearch, self.search_btn)
bs.Add(self.search_btn,0,wx.ALIGN_CENTER)
self.p.SetSizer(bs)
def OnSearch(self, event):
dlg = GetData(parent = self.p)
dlg.ShowModal()
if dlg.result_name:
print "Name: "+dlg.result_name+"\n"
print "Surname: "+dlg.result_surname+"\n"
print "Nickname: "+dlg.result_nickname+"\n"
else:
print "No Input found\n"
dlg.Destroy()
class GetData(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Name Input", size= (650,220))
self.p = wx.Panel(self,wx.ID_ANY)
self.lblname = wx.StaticText(self.p, label="Name", pos=(20,20))
self.name = wx.TextCtrl(self.p, value="", pos=(110,20), size=(500,-1))
self.lblsur = wx.StaticText(self.p, label="Surname", pos=(20,60))
self.surname = wx.TextCtrl(self.p, value="", pos=(110,60), size=(500,-1))
self.lblnick = wx.StaticText(self.p, label="Nickname", pos=(20,100))
self.nickname = wx.TextCtrl(self.p, value="", pos=(110,100), size=(500,-1))
self.saveButton =wx.Button(self.p, label="Save", pos=(110,160))
self.closeButton =wx.Button(self.p, label="Cancel", pos=(210,160))
self.saveButton.Bind(wx.EVT_BUTTON, self.SaveConnString)
self.closeButton.Bind(wx.EVT_BUTTON, self.OnQuit)
self.Bind(wx.EVT_CLOSE, self.OnQuit)
self.Show()
def OnQuit(self, event):
self.result_name = None
self.Destroy()
def SaveConnString(self, event):
self.result_name = self.name.GetValue()
self.result_surname = self.surname.GetValue()
self.result_nickname = self.nickname.GetValue()
self.Destroy()
app = wx.App()
Example(None, title = 'Raman Spectroscopy Database')
app.MainLoop()

How do I retrieve the ID of a bitmap button in wxpython?

self.btid = 0
self.btarray = []
self.btarray.append("x")#so that the buttons are appended according to their ids
self.bmt = wx.BitmapButton(panel, btid, pic, pos=(50,50))
self.btarray.append(self.bmt)
self.btid += 1
I create multiple buttons using the same code. How do I retrieve an individual buttons' ID later on?
Thanks in advance,
Swayam
GetId is the method to get the Id of an object.
So you can write:
id_of_button_n = button_n.GetId()
However in your case, this is not neccessary because you already stored the ids as the keys of the dictionary self.btarray !
Here's a quick and dirty script that will show you how to get button ids and labels. I'm using normal wx.Button objects since there's no good way to include images for bitmap buttons on Stack:
import random
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
i = random.choice(range(5, 10))
for index, item in enumerate(range(i)):
num = index + 1
btn = wx.Button(self, label="Button %s" % num)
btn.Bind(wx.EVT_BUTTON, self.onClick)
mainSizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(mainSizer)
#----------------------------------------------------------------------
def onClick(self, event):
""""""
btn = event.GetEventObject()
print "%s id => %s" % (btn.GetLabel(), btn.GetId())
########################################################################
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Random Buttons", size=(1024, 768))
panel = MyPanel(self)
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
app.MainLoop()

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.
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()
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.

Categories