wxPython - modify a frame - python

I have a simply code:
import wx
class Glowne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
pos = 55
tekst = 'HELLO - position'
font = wx.Font(18, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
wx.StaticText(self, -1, tekst, (300, pos)).SetFont(font)
btn = wx.Button(self, -1, "Change pos", (345, 100))
#self.Bind(wx.EVT_BUTTON, Program.zmiana, btn)
class Program(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,'Program')
panel_one = Glowne(self)
self.SetSize((800,600))
self.Centre()
if __name__ == "__main__":
app = wx.App(False)
frame = Program()
frame.Show()
app.MainLoop()
How can I modyfy pos variable after hitting "Change pos" button?
In my real program I have something like:
name
name1
name2
"BUTTTON"
I would like to add wx.TextCtrl method between name2 and button after hitting "BUTTON". I need to modyfy a frame (add place beetwen name2 and button). I do not know how can I achieve that.
EDIT. There is a code I need to modify:
def __init__(self, parent):
global odstep
self.panel = wx.Panel.__init__(self, parent)
odstep = 0
odstep1 = 0
font = wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
for name in config['rewir1']:
nazwa_zliczana = config['rewir1'][name]
odstep += 22
self.name1 = wx.StaticText(self, -1, name, (300, 10 + odstep))
self.name1.SetFont(font)
btn_usuwanie = wx.Button(self, -1, u"Usuń", (475, 10 + odstep))
self.Bind(wx.EVT_BUTTON, lambda evt, i: Program.Usuwanie(evt, i), btn_usuwanie)
wx.StaticText(self, -1, 'PART I', (365, 0), style=wx.ALIGN_CENTER).SetFont(font)
odstep1 = odstep + 50
print odstep
for name in config['rewir2']:
nazwa_zliczana = config['rewir2'][name]
odstep1 += 22
self.name2 = wx.StaticText(self, -1, name, (300, 50 + odstep1))
self.name2.SetFont(font)
btn_usuwanie_2 = wx.Button(self, -1, u"Usuń", (475, 50 + odstep1))
self.Bind(wx.EVT_BUTTON, lambda evt, i: Program.Usuwanie(evt, i), btn_usuwanie_2)
print odstep1
wx.StaticText(self, -1, 'PART II', (365, 80 + odstep), style=wx.ALIGN_CENTER).SetFont(font)
self.btn = wx.Button(self, -1, "Change panel", (345, 500))
self.btn_dodaj_rewir1 = wx.Button(self, -1, "Add name", (345, 42 + odstep))
self.btn_dodaj_rewir2 = wx.Button(self, -1, "Add name", (345, 84 + odstep1))
self.Bind(wx.EVT_BUTTON, self.new_name, self.btn_dodaj_rewir1)

You need to save wx.StaticText instanced. To change property of it later.
Use SetPosition method to change position.
Bind EVT_BUTTON event to event handler (change_pos in the following code).
class Glowne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
tekst = 'HELLO - position'
font = wx.Font(18, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
self.text = wx.StaticText(self, -1, tekst, (300, 55)) # Save for later use
self.text.SetFont(font)
btn = wx.Button(self, -1, "Change pos", (345, 100))
btn.Bind(wx.EVT_BUTTON, self.change_pos)
def change_pos(self, event):
x, y = self.text.Position
self.text.SetPosition((x, y + 10))

Related

How can I resize * wx.CheckListBox* automatically in wxPython?

If the text of label for checkboxes is more than width of a wx.CheckListBox one must change its size.
The short answer is to not set the size of the CheckListBox. This will automatically set the size to the largest item. If you do set the size parameter and the text does not fit, set the style=wx.LB_HSCROLL and a horizontal slider will be created, if needed.
Below a demonstration with both versions of self.clb
import wx
class ClbView(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, None, -1, 'CheckListBox', size=(250, 200))
def createWidgets(self, list):
self.panel = wx.Panel(self, -1)
# self.clb = wx.CheckListBox(self.panel, -1, size=(100,150),choices=list,style=wx.LB_HSCROLL)
self.clb = wx.CheckListBox(self.panel, -1, choices = list)
self.btn_exit = wx.Button(self.panel, wx.ID_ANY, 'Exit')
def sizeWidgets(self):
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.clb, 0, wx.ALL|wx.CENTER, 5)
self.vbox.Add(self.btn_exit, 0, wx.CENTER)
self.panel.SetSizer(self.vbox)
self.Centre()
class ClbControl:
def __init__(self):
self.list = ['Quite a long piece of text', 'Short text', 'X']
self.createView()
def createView(self):
self.view = ClbView(None)
self.view.createWidgets(self.list)
self.view.sizeWidgets()
self.view.Show()
self.view.btn_exit.Bind(wx.EVT_BUTTON, self.onExit)
self.view.clb.Bind(wx.EVT_CHECKLISTBOX, self.onCLB )
def onCLB(self, evt):
x = int(evt.GetSelection())
print "Box ",x," Accessed"
def onExit(self, evt):
self.view.Close()
if __name__ == '__main__':
app = wx.App()
controller = ClbControl()
app.MainLoop()

Using wxPython's wx.TextCtrl blocks out rest of form

I am using wxPython to build forms. I am new to wxpython. My first form opens correctly and when you press the Travel Advisory button the second form opens. This is where the users will enter information. When I use this line of code to be able to enter text:
self.logger = wx.TextCtrl(self, pos=(100, 145), size=(140,-1))
it will obliterate everything else on the form. Comment the line out and the form is good. I am having trouble figuring this out and cannot seem to find a good answer on the web. Here is my code so far. Any help would be great.
import wx
# varialbes
title = 'Advisory Form'
closuretypeList = ['is closed ', 'is open', 'closed for season ', 'open for season ']
stateList = ['Alabama','Alaska']
analystList = []
dotPhoneList = []
dotWebList = []
class formMS(wx.Frame):
#formMS is main switchboard
def __init__(self, parent, title):
# create form
super(formMS, self).__init__(parent,title=title,size=(225, 350))
panel = wx.Panel(self, -1)
font1 = wx.Font(11, wx.SWISS, wx.NORMAL, wx.BOLD, True)
#add static labels
text1 = wx.StaticText(panel, -1, "FORMS", (55, 15))
text1.SetFont(font1)
text2 = wx.StaticText(panel, -1, "REPORTS", (55, 110))
text2.SetFont(font1)
#Form buttons
self.buttonTAForm = wx.Button(panel,id=wx.ID_OPEN, label="Travel Advisory", pos = (55, 40))
self.buttonTAForm.Bind(wx.EVT_BUTTON, self.OnClick, self.buttonTAForm)
self.buttonDOTForm = wx.Button(panel,id=wx.ID_ANY, label="DOT Contacts", pos = (55, 75))
#Report Buttons
self.buttonTARep = wx.Button(panel,id=wx.ID_ANY, label="TA Report", pos = (55, 140))
self.buttonDOTContactRep = wx.Button(panel,id=wx.ID_ANY, label="DOT Contacts", pos = (55, 175))
#cancel button
self.buttonCancel = wx.Button(panel,id=wx.ID_CANCEL, label="Close",pos = (55,225))
self.buttonCancel.Bind(wx.EVT_BUTTON, self.OnCloseMe)
self.buttonCancel.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.Centre()
self.Show()
def OnClick(self, event):
secondWindow = formTAN(self)
secondWindow.Show()
def OnCloseMe(self, event):
self.Close(True)
def OnCloseWindow(self, event):
self.Close(True)
class formTAN(wx.Frame):
#formTAN is Travel Advisory Notice Form
def __init__(self, parent):
# create form
super(formTAN, self).__init__(parent,size=(550, 650))
panel = wx.Panel(self, -1)
font1 = wx.Font(11, wx.SWISS, wx.NORMAL, wx.BOLD, True)
font2 = wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False)
self.logger = wx.TextCtrl(self, pos=(100, 145), size=(140,-1))
#Label Panel
self.lblname = wx.StaticText(panel, -1, "TRAVEL ADVISORY FORM", (170, 15))
self.lblname.SetFont(font1)
#Clears form to create a new record
self.buttonNew = wx.Button(panel,id=wx.ID_ANY, label="New Record", pos = (55, 40))
#Exits Form
self.buttonCancel = wx.Button(panel,id=wx.ID_CANCEL, label="All Clear/Exit",pos = (380,40))
self.buttonCancel.Bind(wx.EVT_BUTTON, self.OnCloseMe)
#Selects type of closure
self.lblname = wx.StaticText(panel, -1, "Closure Type", (10, 85))
self.lblname.SetFont(font2)
self.choClosureType = wx.Choice(panel,-1, (100, 85),choices=closuretypeList)
# self.choClosureType.Bind(wx.EVT_CHOICE, self.OnSelect)
#Drop down list of states/provinces
self.lblname = wx.StaticText(panel, -1, "State", (10, 115))
self.lblname.SetFont(font2)
self.choStateType = wx.Choice(panel,-1, (100, 115),choices=stateList)
# self.choClosureType.Bind(wx.EVT_CHOICE, self.OnSelect)
#Enter strip map number
self.lblname = wx.StaticText(panel, -1, "Strip #:", (250, 115))
self.lblname.SetFont(font2)
# self.editname = wx.TextCtrl(self, value="", pos=(100, 145), size=(140, -1))
# self.Bind(wx.EVT_TEXT, self.EvtText, self.editname)
# self.Bind(wx.EVT_CHAR, self.EvtChar, self.editname)
#Enter route name
self.lblname = wx.StaticText(panel, -1, "Road Name:", (10, 145))
self.lblname.SetFont(font2)
#Enter area in question
self.lblname = wx.StaticText(panel, -1, "To / From:", (250, 145))
self.lblname.SetFont(font2)
#Extra Details
self.lblname = wx.StaticText(panel, -1, "Description:", (10, 175))
self.lblname.SetFont(font2)
# self.logger = wx.TextCtrl(self, pos=(100, 170), size=(400, 150), style=wx.TE_MULTILINE | wx.TE_READONLY)
#Dot Phone number
self.lblname = wx.StaticText(panel, -1, "DOT Phone:", (10, 275))
self.lblname.SetFont(font2)
self.choDotPhoneType = wx.Choice(panel,-1, (100, 275),choices=dotPhoneList)
#DOT websites
self.lblname = wx.StaticText(panel, -1, "DOT Website:", (250, 275))
self.lblname.SetFont(font2)
self.choDotWebType = wx.Choice(panel,-1, (350, 275),choices=dotWebList)
#Analyst list
self.lblname = wx.StaticText(panel, -1, "Analyst:", (10, 305))
self.lblname.SetFont(font2)
self.choAnalystType = wx.Choice(panel,-1, (100, 305),choices=analystList)
def OnCloseMe(self, event):
self.Close(True)
self.Centre()
self.Show()
if __name__ == '__main__':
app = wx.App()
formMS(None, title='Travel Advisory')
app.MainLoop()
In the # create form part of your class formTAN
self.logger = wx.TextCtrl(self, pos=(100, 145), size=(140,-1))
is parented to self, it needs parenting to the panel that is a child of self
self.logger = wx.TextCtrl(panel, pos=(100, 145), size=(140,-1))
The #Extra Details part of your class formTAN
self.logger = wx.TextCtrl(self, pos=(100, 170), size=(400, 150),
style=wx.TE_MULTILINE | wx.TE_READONLY)
is also parented to self so also needs parenting to panel, and its height 150 is making it cover other controls,
changing the height to 100 sorts this out.
self.logger = wx.TextCtrl(panel, pos=(100, 170), size=(400, 100),
style=wx.TE_MULTILINE | wx.TE_READONLY)

Python sizers - vertical column in horizontal row?

I'm learning wxPython and I'm having an issue. Here is my code below. It doesn't really work. What I'm trying to do is get a button in the top left section below the text area that says "Enter Task". I want the text input area and "enter task" button to be in a column so that the combined height of the two equals the height of the Start and Exit buttons next to them. Any help? Sizers confuse me.
import wx
import datetime
class UpperPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
#Timer
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.Update, self.timer)
#Enter Task Field
self.edit = wx.TextCtrl(self, -1, size=wx.Size(200, -1))
#Enter Task Button
self.button = wx.Button(self, -1, label="Enter!")
self.midpanel = MiddlePanel(self)
self.button.Bind(wx.EVT_BUTTON, self.midpanel.OnEnterPressed)
#Start/Stop Button
self.start_button=wx.Button(self, label="Start", size=(150,50))
self.Bind(wx.EVT_BUTTON, MiddlePanel.StartButton, self.start_button)
#Exit Button
self.exit_button=wx.Button(self, -1, label="Exit", size=(150,50))
self.Bind(wx.EVT_BUTTON, MainWin.CloseButton, self.exit_button)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.edit, 1, wx.EXPAND)
self.sizer.Add(self.start_button, 0, wx.EXPAND)
self.sizer.Add(self.exit_button, 0, wx.EXPAND)
self.SetSizerAndFit(self.sizer)
#=====================================================================
class MiddlePanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizerAndFit(self.sizer)
#Initialize Variables
self.box_height = 100
self.box_count = 0
self.start_time = ''
def OnEnterPressed(self, event):
#Get entered text
uppanel = UpperPanel(self)
self.box_label = uppanel.edit.GetValue()
if self.box_count < 10:
for x in range(0, 1):
chbx1 = wx.CheckBox(self, -1, self.box_label)
txtbx1 = wx.TextCtrl(self, -1)
self.box_height += 30
uppanel.edit.Clear()
print("CLEARED!")
print self.box_count
print uppanel.edit.GetValue()
#self.Layout()
self.box_count += 1
def StartButton(self,event):
self.start_time = datetime.datetime.now()
btn_label = self.start_button.GetLabel()
if btn_label == "Start":
print "starting timer..."
self.timer.Start(1000)
self.start_button.SetLabel("Stop")
else:
print "timer stopped!"
self.timer.Stop()
self.start_button.SetLabel("Start")
print ('Start button pressed.')
def Update(self, event):
seconds = (self.start_time - datetime.datetime.now() +
datetime.timedelta(days=1)).seconds
self.time_text.SetLabel('Time till next task:\n%d hours %d \
minutes %d seconds'
% (seconds / 3600,
(seconds / 60)
% (seconds / 3600 * 60),
seconds % 60))
#======================================================================
class MainWin(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.middlePanel = MiddlePanel(self)
self.upperPanel = UpperPanel(self)
self.textArea = wx.TextCtrl(self, size=(-1, 300), style=wx.TE_MULTILINE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.upperPanel, 0, wx.EXPAND)
self.sizer.Add(self.middlePanel, 0, wx.EXPAND)
self.sizer.Add(self.textArea, 1, wx.EXPAND)
self.SetSizerAndFit(self.sizer)
#Window Closer
self.Bind(wx.EVT_CLOSE, self.CloseWindow)
#Create Menu Bar
status=self.CreateStatusBar()
menubar=wx.MenuBar()
firstmenu=wx.Menu()
secondmenu=wx.Menu()
firstmenu.Append(wx.NewId(),"Start","Starts the timer.")
firstmenu.Append(wx.NewId(),"Stop","Stops the timer.")
firstmenu.Append(wx.NewId(),"Exit","Exits the program.")
secondmenu.Append(wx.NewId(),"Preferences","Set the timer options.")
secondmenu.Append(wx.NewId(),"Edit task list",
"Add, change, or remove tasks.")
menubar.Append(firstmenu,"File")
menubar.Append(secondmenu,"Edit")
self.SetMenuBar(menubar)
#Static Text
self.st1 = wx.StaticText(self, -1, 'Enter Tasks:')
self.st2 = wx.StaticText(self, -1, 'Created by Spencer Evans')
self.time_text = wx.StaticText(self, -1, '')
def CloseButton(self,event):
#timer.Stop()
self.Close(True)
print ('Closed by Exit button.')
def CloseWindow(self,event):
#timer.Stop()
self.Destroy()
print ('Closed by X\'ing window.')
#========================================================================
#Run program
if __name__ == '__main__':
app = wx.PySimpleApp()
main_win = MainWin()
main_win.Show()
app.MainLoop()
I don't really know where your problem is. In my opinion all of the parts where already there, you just have to put them together. If I understood what you wanted, just replace the text field by a panel containing the text field and a button with a vertical sizer. Nice typing exercise, let me suggest a solution:
--- /tmp/test.py
+++ /tmp/test2.py
## -11,8 +11,19 ##
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.Update, self.timer)
+ # Panel for 'Enter Task' textfield and button
+ enter_task_panel = wx.Panel(self, -1)
+ task_panel_sizer = wx.BoxSizer(wx.VERTICAL)
+ enter_task_panel.SetSizer(task_panel_sizer)
+
#Enter Task Field
- self.edit = wx.TextCtrl(self, -1, size=wx.Size(200, -1))
+ self.edit = wx.TextCtrl(enter_task_panel, -1, size=wx.Size(200, -1))
+ task_panel_sizer.Add(self.edit, 1)
+
+ # 'Enter Task' button
+ enter_task_button = wx.Button(enter_task_panel, -1, "Enter Task")
+ task_panel_sizer.Add(enter_task_button, 1, wx.EXPAND)
+
#Enter Task Button
self.button = wx.Button(self, -1, label="Enter!")
self.midpanel = MiddlePanel(self)
## -25,7 +36,7 ##
self.Bind(wx.EVT_BUTTON, MainWin.CloseButton, self.exit_button)
self.sizer = wx.BoxSizer()
- self.sizer.Add(self.edit, 1, wx.EXPAND)
+ self.sizer.Add(enter_task_panel, 1, wx.EXPAND)
self.sizer.Add(self.start_button, 0, wx.EXPAND)
self.sizer.Add(self.exit_button, 0, wx.EXPAND)
Zetcode has a pretty good tutorial on wxPython, I can only recommend.

Set String of the Current Selected Item with wxListbox

I have a listbox,
How can I change the string of current selected item of the listbox to another string?
I cant really find how to do this on Google.
Just delete selected string and insert a new one, like it is done in this example for a single-choice listbox:
import wx
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, style=wx.DEFAULT_FRAME_STYLE)
self.button = wx.Button(self, -1, "Change")
self.Bind(wx.EVT_BUTTON, self.ButtonPress, self.button)
self.tc = wx.TextCtrl(self, -1)
self.lb = wx.ListBox(self, -1, choices = ('One', 'Two'))
box = wx.BoxSizer(wx.VERTICAL)
box.Add(self.lb, 0, wx.EXPAND, 0)
box.Add(self.tc, 0, wx.EXPAND, 0)
box.Add(self.button, 0, wx.ADJUST_MINSIZE, 0)
self.SetSizer(box)
box.Fit(self)
self.Layout()
def ButtonPress(self, evt):
txt = self.tc.GetValue()
pos = self.lb.GetSelection()
self.lb.Delete(pos)
self.lb.Insert(txt, pos)
if __name__ == "__main__":
app = wx.PySimpleApp(0)
frame = MyFrame(None, -1, "")
frame.Show()
app.MainLoop()
If you need multiple-selection listbox, then you should create it with style=wx.LB_MULTIPLE:
self.lb = wx.ListBox(self, -1, choices = ('One', 'Two'), style=wx.LB_MULTIPLE)
Now you're able to change multiple strings at once:
def ButtonPress(self, evt):
txt = self.tc.GetValue()
for pos in self.lb.GetSelections():
self.lb.Delete(pos)
self.lb.Insert(txt, pos)

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