How to use Refresh with a wx.ColourDialog in wxpython? - python

i am trying to Refresh() a panel which uses the wx.ColourDialog. Once I refresh the panel once, it is unable to refresh again. Try the following to see the problem in action.
By clicking the button, it will ask you what color you would like to change the rectangle to. Once you press OK, it should change the rectangles color. It will not work it will not change the rectangle.
import wx
xcolor_of_font_dia=(0,0,0)
class MyFrame(wx.Frame):
"""a frame with a panel"""
def __init__(self, parent=None, id=wx.ID_ANY, title=None):
global xcolor_of_font_dia
global dc
wx.Frame.__init__(self, parent, wx.ID_ANY, title)
self.panel = wx.Panel(self, size=(350, 200))
self.panel.Bind(wx.EVT_PAINT, self.on_paint)
self.button2 = wx.Button(self.panel, id=wx.ID_ANY, label='Button2',pos=(8, 38), size=(175, 28))
self.button2.Bind(wx.EVT_BUTTON, self.onColorDlg)
self.Fit()
def onColorDlg(self, event):
global xcolor_of_font_dia
global dc
"""
This is mostly from the wxPython Demo!
"""
dlg = wx.ColourDialog(self)
# Ensure the full colour dialog is displayed,
# not the abbreviated version.
dlg.GetColourData().SetChooseFull(True)
if dlg.ShowModal() == wx.ID_OK:
data = dlg.GetColourData()
print 'You selected: %s\n' % str(data.GetColour().Get())
xcolor_of_font_dia='#%02x%02x%02x' % data.GetColour().Get()
dlg.Destroy()
self.panel.Refresh()
def on_paint(self, event):
global xcolor_of_font_dia
global dc
dc = wx.PaintDC(self.panel)
dc.SetPen(wx.Pen(xcolor_of_font_dia, 1))
rect = wx.Rect(50, 50, 100, 100)
dc.DrawRoundedRectangleRect(rect, 8)
# test it ...
app = wx.PySimpleApp()
frame1 = MyFrame(title='rounded-rectangle & circle')
frame1.Center()
frame1.Show()
app.MainLoop()

I cleaned your code a bit. Basically your globals were producing some problems as you were creating (and deleting) different dc instances after every size event.
You should not use globals if it is not strictly necessary (rarely is).
This works:
import wx
class MyFrame(wx.Frame):
"""a frame with a panel"""
def __init__(self, parent=None, id=wx.ID_ANY, title=None):
wx.Frame.__init__(self, parent, wx.ID_ANY, title)
self.xcolor = (0, 0, 0)
self.panel = wx.Panel(self, size=(350, 200))
self.panel.Bind(wx.EVT_PAINT, self.on_paint)
self.button2 = wx.Button(self.panel, id=wx.ID_ANY, label='Button2',
pos=(8, 38), size=(175, 28))
self.button2.Bind(wx.EVT_BUTTON, self.onColorDlg)
self.Fit()
def onColorDlg(self, event):
"""
This is mostly from the wxPython Demo!
"""
dlg = wx.ColourDialog(None)
dlg.GetColourData().SetChooseFull(True)
if dlg.ShowModal() == wx.ID_OK:
data = dlg.GetColourData()
self.xcolor = data.GetColour().Get()
print 'You selected: %s\n' % str(self.xcolor)
dlg.Destroy()
self.panel.Refresh()
def on_paint(self, event):
dc = wx.PaintDC(self.panel)
dc.SetPen(wx.Pen(self.xcolor, 2))
rect = wx.Rect(50, 50, 100, 100)
dc.DrawRoundedRectangleRect(rect, 8)
# test it ...
app = wx.PySimpleApp()
frame1 = MyFrame(title='rounded-rectangle & circle')
frame1.Center()
frame1.Show()
app.MainLoop()

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

How can I make a wxpython Widget span two cells without pushing other widgets aside?

I'm trying to make a form that has several input fields. Underneath these fields I want to have a wxpython Ultimate List Control (for all intents and purposes it's the same thing as a List Control). My issue is with sizers. To give some context, my form looks like this
Name [TextCtrl]
Blah [TextCtrl]
ListControl
I want it to look like
Name [TextCtrl]
Blah [TextCtrl]
ListCtrl (this spans to the end of the row)
My problem is when I try to add the List Control. I want the list control to Stretch from The Static Text to the Text Control, but it pushes the TextControl over. Can someone please point me in the right direction? I have attached the relevant code below.
class UserField(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent=parent, title="Info", size=(350, 400),
style=wx.DEFAULT_FRAME_STYLE)
self.init_ui()
self.Center()
self.ShowModal()
def init_ui(self):
panel = wx.Panel(self, wx.ID_ANY)
hbox = wx.BoxSizer(wx.VERTICAL)
flex_grid = wx.FlexGridSizer(5, 2, 5, 10) # row, col, vgap, hgap
info_text = wx.StaticText(parent=panel, label="Enter information")
self.search_button = wx.Button(parent=panel, label="Search")
self.list_control = UltimateListCtrl(panel,
agwStyle=wx.LC_REPORT | wx.BORDER_SUNKEN | ULC_HAS_VARIABLE_ROW_HEIGHT, )
flex_grid.AddMany(
[
info_text, self.search_button
]
)
lbox = wx.BoxSizer(wx.HORIZONTAL)
lbox.Add(self.list_control
hbox.Add(flex_grid, wx.EXPAND|wx.ALL)
hbox.Add(lbox, proportion=1, flag=wx.ALL|wx.EXPAND)
panel.SetSizer(hbox)
Here's a quick demonstration of wx.GridBagSizer. The program opens a simple frame with a single button that spawns a dialog with a GridBagSizer. You can place items in the sizer according to a position (pos) and optionally allow a widget to span multiple rows and/or columns (span).
import wx
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.SetSize((300, 200))
self.Centre()
self.Show(True)
self.InitUI()
def InitUI(self):
panel = wx.Panel(self)
sizer = wx.BoxSizer()
btn = wx.Button(panel, label="Spawn Window")
btn.Bind(wx.EVT_BUTTON, self.spawn_window)
sizer.Add(btn)
panel.SetSizerAndFit(sizer)
def spawn_window(self, evt):
UserField(self)
def OnQuit(self, e):
self.Close()
class UserField(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent=parent, title="Info", size=(350, 400),
style=wx.DEFAULT_FRAME_STYLE)
self.init_ui()
self.Center()
self.ShowModal()
def init_ui(self):
panel = wx.Panel(self)
sizer = wx.GridBagSizer(10, 10)
field1Label = wx.StaticText(panel, label="Field 1")
field2Label = wx.StaticText(panel, label="Field 2")
field1Ctrl = wx.TextCtrl(panel)
field2Ctrl = wx.TextCtrl(panel)
listCtrl = wx.ListCtrl(panel)
sizer.Add(field1Label, pos=(0, 0))
sizer.Add(field2Label, pos=(1, 0))
sizer.Add(field1Ctrl, pos=(0, 1))
sizer.Add(field2Ctrl, pos=(1, 1))
# HERE'S THE IMPORTANT LINE. NOTE THE 'span' ARGUMENT:
sizer.Add(listCtrl, pos=(2, 0), span=(1, 2), flag=wx.EXPAND)
panel.SetSizerAndFit(sizer)
if __name__ == '__main__':
ex = wx.App()
mainFrame = Example(None)
ex.MainLoop()

How to link multiple wx.Dialogs in wxPython

I want to make a game in wxPython (no other modules) and I want to make it so that you can enter some values in popup screens before the game starts, and then the game will be drawn on a canvas which in turn is drawn on a panel, which is bound to the main game.
I made the gamescreen with all fancy stuff (works solo)
I made the input screens
But I cannot link them.
How do I start the game so it will open a dialog box, then on the closure of it open another one, and then open the game ?
I tried the following, but it will not open my canvas:
# makes a game by showing 2 dialogs
# after dialogs have been answered, starts the game by drawing the canvas.
# imports
import wx
import Speelveld3
# globals
SCRWIDTH = 950
SCRHEIGHT = 700
# dialogbox class
class MyDialog1(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
self.username = wx.TextCtrl(self)
self.okButton = wx.Button(self, wx.ID_OK, "OK")
class MyDialog2(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
self.canvasWidth = wx.TextCtrl(self)
self.okButton = wx.Button(self, wx.ID_OK, "OK")
# main class
class Game(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title='My game', size=(SCRWIDTH, SCRHEIGHT))
self.username = ""
self.canvasWidth = 10
# hide the frame for now
self.Hide()
def OnInit(self):
#Make your dialogs
dlg1 = MyDialog1(self)
#if the user pressed "OK" (i.e. NOT "Cancel" or any other button you might add)
if dlg1.ShowModal() == wx.ID_OK:
#get the username from the dialog
self.username = dlg1.username.GetValue()
#clean up the dialog (AFTER you get the username)
dlg1.Destroy()
dlg2 = MyDialog2(self)
#if the user pressed "OK" (i.e. NOT "Cancel" or any other button you might add)
if dlg2.ShowModal() == wx.ID_OK:
#get the username from the dialog
self.canvasWidth = dlg2.canvasWidth.GetValue()
#clean up the dialog (AFTER you get the username)
dlg2.Destroy()
# Now that you have your settings, Make the gameboard
# THIS PART IS STILL BROKEN!
# I can paste the whole board class (structure of it is taken from the tetris tutorial)
# but that seems a bit much tbh...
self.gameBoard = Board.Board(self)
self.gameBoard = SetFocus()
self.gameBoard.start()
self.Centre()
self.Show(True) #show the frame
if __name__ == '__main__':
# how can I start the game here?
app = wx.App()
frame = Game()
board = Speelveld3.Speelveld(frame)
board.start()
frame.Show()
app.MainLoop()
You've double posted, and the lack of any wx.Dialog in your sample code suggests to me that you haven't even looked at a tutorial yet, but I will give you the benefit of the doubt.
First, if you want to return information from a dialog, the easiest way is to define a custom dialog. Define a new class that inherits from wx.Dialog and then set it up just like you would a normal panel or a frame. It seems to me that you will need two of these. They'll look something like this:
class MyDialog1(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
self.username = wx.TextCtrl(self) #this is where users will enter their username
self.okButton = wx.Button(self, wx.ID_OK, "OK") #Note that I'm using wx.ID_OK. This is important
Now, for the logic you want. Pretty much every object in wxPython that you actually see has the functions Show() and Hide() (API here). You don't want to show your frame until AFTER the dialogs are finished, so in your __init__(), call Hide(). I'm also initializing a variable, username, which is where I will store the data from my dialog.
class Game(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(SCRWIDTH, SCRHEIGHT))
self.username = ""
self.Hide() #don't show the frame just yet
#self.Hide() is the exact same as self.Show(False)
Now, for your dialogs. Like Mike Driscoll suggested, you call your dialogs BEFORE making your canvas. wx.Dialogs are launched using ShowModal(). By setting the ID of self.okButton to the constant wx.ID_OK, wxPython recognizes that the dialog should be closed after the button in clicked. You should also be aware of wx.ID_CANCEL.
def OnInit(self):
#Make your dialogs
dlg1 = MyDialog1(self)
if dlg1.ShowModal() == wx.ID_OK:
#if the user pressed "OK" (i.e. NOT "Cancel" or any other button you might add)
self.username = dlg1.username.GetValue() #get the username from the dialog
dlg1.Destroy() #clean up the dialog (AFTER you get the username)
#do this again for your second dialog
#Now that you have your settings, Make the gameboard
self.gameBoard = Board.Board(self)
self.gameBoard = SetFocus()
self.gameBoard.start()
self.Centre()
self.Show(True) #show the frame
In your OnInit you just need to call your dialogs and show them modally BEFORE you create your Board instance. Then it should work correctly.
EDIT (6-28-12): Here's some code:
import wx
########################################################################
class MyDlg(wx.Dialog):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Dialog.__init__(self, None, title="I'm a dialog!")
lbl = wx.StaticText(self, label="Hi from the panel's init!")
btn = wx.Button(self, id=wx.ID_OK, label="Close me")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl, 0, wx.ALL, 5)
sizer.Add(btn, 0, wx.ALL, 5)
self.SetSizer(sizer)
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
# show a custom dialog
dlg = MyDlg()
dlg.ShowModal()
dlg.Destroy()
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnPaint(self, evt):
pdc = wx.PaintDC(self)
try:
dc = wx.GCDC(pdc)
except:
dc = pdc
rect = wx.Rect(0,0, 100, 100)
for RGB, pos in [((178, 34, 34), ( 50, 90)),
(( 35, 142, 35), (110, 150)),
(( 0, 0, 139), (170, 90))
]:
r, g, b = RGB
penclr = wx.Colour(r, g, b, wx.ALPHA_OPAQUE)
brushclr = wx.Colour(r, g, b, 128) # half transparent
dc.SetPen(wx.Pen(penclr))
dc.SetBrush(wx.Brush(brushclr))
rect.SetPosition(pos)
dc.DrawRoundedRectangleRect(rect, 8)
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Example frame")
# show a MessageDialog
style = wx.OK|wx.ICON_INFORMATION
dlg = wx.MessageDialog(parent=None,
message="Hello from the frame's init",
caption="Information", style=style)
dlg.ShowModal()
dlg.Destroy()
# create panel
panel = MyPanel(self)
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
frame.Show()
app.MainLoop()

Python WX - Returning user input from wx Dialog

I'm new to Python and WX. I created a simple test dialog shown below that prompts the user with a combobox. I would like to capture the value from the combox in my main program. How do I call it from my main program?
This is how I was purposing to call it that displays the dialog but does not currently capture the value from the combobox:
import highlight
highlight.create(self).Show(True)
a = highlight.OnComboBox1Combobox(self)
print a
The name of the Dialog file is "highlight". Below is the code:
#Boa:Dialog:Dialog2
import wx
def create(parent):
return Dialog2(parent)
[wxID_DIALOG2, wxID_DIALOG2COMBOBOX1, wxID_DIALOG2STATICTEXT1,
] = [wx.NewId() for _init_ctrls in range(3)]
class Dialog2(wx.Dialog):
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.Dialog.__init__(self, id=wxID_DIALOG2, name='', parent=prnt,
pos=wx.Point(264, 140), size=wx.Size(400, 485),
style=wx.DEFAULT_DIALOG_STYLE, title='Dialog2')
self.SetClientSize(wx.Size(384, 447))
self.comboBox1 = wx.ComboBox(choices=['test1', 'test2'],
id=wxID_DIALOG2COMBOBOX1, name='comboBox1', parent=self,
pos=wx.Point(120, 16), size=wx.Size(130, 21), style=0,
value=u'wining\n')
self.comboBox1.SetToolTipString(u'comboBox1')
self.comboBox1.SetLabel(u'wining\n')
self.comboBox1.Bind(wx.EVT_COMBOBOX, self.OnComboBox1Combobox,
id=wxID_DIALOG2COMBOBOX1)
self.staticText1 = wx.StaticText(id=wxID_DIALOG2STATICTEXT1,
label=u'test', name='staticText1', parent=self, pos=wx.Point(88,
16), size=wx.Size(19, 13), style=0)
def __init__(self, parent):
self._init_ctrls(parent)
##print get_selection
##print get_selection1
def OnComboBox1Combobox(self, event):
get_selection = self.comboBox1.GetValue()
return get_selection
There are lots of dialog examples out there. Here are a couple:
The Dialogs of wxPython (Part 1 of 2)
http://zetcode.com/wxpython/dialogs/
Basically, all you need to do is instantiate your dialog, show it and then before you close it, extract the value. The typical way to do it is something like this:
myDlg = MyDialog()
res = myDlg.ShowModal()
if res == wx.ID_OK:
value = myDlg.myCombobox.GetValue()
myDlg.Destroy()
Update: Here's a more full-fledged example:
import wx
########################################################################
class MyDialog(wx.Dialog):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Dialog.__init__(self, None, title="Dialog")
self.comboBox1 = wx.ComboBox(self,
choices=['test1', 'test2'],
value="")
okBtn = wx.Button(self, wx.ID_OK)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.comboBox1, 0, wx.ALL|wx.CENTER, 5)
sizer.Add(okBtn, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(sizer)
########################################################################
class MainProgram(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Main Program")
panel = wx.Panel(self)
btn = wx.Button(panel, label="Open dialog")
btn.Bind(wx.EVT_BUTTON, self.onDialog)
self.Show()
#----------------------------------------------------------------------
def onDialog(self, event):
""""""
dlg = MyDialog()
res = dlg.ShowModal()
if res == wx.ID_OK:
print dlg.comboBox1.GetValue()
dlg.Destroy()
if __name__ == "__main__":
app = wx.App(False)
frame = MainProgram()
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