So I have been teaching myself Object Oriented Programming for Tkinter projects as I clearly see that they are much more organized for large amounts of coding. However I must admit that I've been coasting by simply copying various bits of coding from online, not fully understanding what its purpose is.
This has lead me to the point that my code does not work at all and I have no idea why not. The first issue is an issue with simply changing an aspect of other widgets.
I have this sample code:
import Tkinter as tk
LARGE_FONT = ("Verdana", 12)
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0 , weight = 1)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
button = tk.Button(self, text = "Change Label", command = self.change)
button.pack(pady = 10, padx = 10)
def change(self):
label["text"] = "It has changed"
app = SeaofBTCapp()
app.mainloop()
Which SHOULD be a simple enough code that, with a button press, change the label from "Start Page" to "It has changed". But whenever I run it, it says that the global variable "label" is not defined. Additionally, if I then change it to self.label, it states that StartPage instance has no attribute 'label'. I don't know what I'm doing wrong.
Additionally, in a similar vein, I'm working on a project that has a SideBar class and a Main class tied to one MainApplication class. The Main class takes a value and displays it on a Frame in the Main class. Following this, a button in the SideBar increases that value by 1. But the Main display doesn't update and I have no idea how to tie the Main updating with the button in the SideBar.
import Tkinter as tk
something = [0, 6]
class Main():
def __init__(self, root):
mainboard = tk.Frame(root, height = 100, width = 100)
self.maincanvas = tk.Canvas(mainboard, bd = 1, bg = "white")
mainboard.grid(row = 0, column = 0)
self.maincanvas.grid(row = 0, column = 0)
self.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1]))
class SideBar():
def __init__(self, root):
sidebarframe = tk.Frame(root, height = 100, width = 100)
button = tk.Button(sidebarframe, width = 20, text = "Change Value", command = self.add)
sidebarframe.grid(row = 0, column = 1)
button.grid(row = 0, column = 0)
def add(self):
something[1] += 1
print something[1]
class MainApplication():
def __init__(self, parent):
self.parent = parent
self.sidebar = SideBar(self.parent)
self.main = Main(self.parent)
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root)
root.mainloop()
All help would be appreciated, but please try and not use a lot of technical terms, as I am still learning.
In the first scenario replace:
label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
With:
self.label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
self.label.pack(pady = 10, padx = 10)
And also in the function change put it like this:
self.label["text"] = "It has changed"
And in your second problem i changed the code a little bit so it works:
import Tkinter as tk
something = [0, 6]
class Main():
def __init__(self, root):
mainboard = tk.Frame(root, height = 100, width = 100)
self.maincanvas = tk.Canvas(mainboard, bd = 1, bg = "white")
mainboard.grid(row = 0, column = 0)
self.maincanvas.grid(row = 0, column = 0)
self.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1]))
class SideBar():
def __init__(self, root, main):
self.main = main # Putting the main object to self.main
sidebarframe = tk.Frame(root, height = 100, width = 100)
button = tk.Button(sidebarframe, width = 20, text = "Change Value", command = self.add)
sidebarframe.grid(row = 0, column = 1)
button.grid(row = 0, column = 0)
def add(self):
something[1] += 1
self.main.maincanvas.delete("all") # Removing everything from canvas
self.main.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1])) # Inserting the new value
print something[1]
class MainApplication():
def __init__(self, parent):
self.parent = parent
self.main = Main(self.parent) # The main needs to run first
self.sidebar = SideBar(self.parent, self.main) # So that SideBar can use its canvas
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root)
root.mainloop()
Related
I have a Python Tkinter GUI class as following:
import Tkinter as tk
class AppClient(tk.Frame):
def __init__(self, master):
error_class = ErrorClass()
self.val_error_code = error_class.error_message
tk.Frame.__init__(self, master)
self.pack()
##Frame for error message display
error_frame = tk.Frame(self, highlightbackground="violet", highlightcolor="violet", highlightthickness=1, width=600, height = 60, bd= 0)
error_frame.pack(padx = 10, pady = 5, anchor = 'w')
## error code: Label and Entry
tk.Label(error_frame, text = 'Error message').grid(row = 0, column = 0, sticky = 'w')
self.error_code = tk.Entry(error_frame, background = 'white', width = 27)
self.error_code.grid(row = 0, column = 1, sticky = 'w', padx = 5, pady = 5)
def update_error_messsage(self):
self.error_code.delete(0, 'end')
self.error_code.insert(0, self.val_error_code)
if __name__ == '__main__':
root = tk.Tk()
app_client = AppClient(root)
app_client.mainloop()
I want to update the entry field error_code dynamically by using the function update_error_message. The problem is, error message is continuously updated from another class ErrorClass() and I am receiving the error message to my AppClient class by variable error_message.
How can I update the error_code entry filed whenever the value of the variable error_message got updated in another class (ErrorClass())
The simple solution is that you need a reference to your instance of AppClient inside of ErrorClass, and then allow the instance of ErrorClass to pass the new value to the app
For example:
class AppClient(tk.Frame):
def __init__(self, master):
error_class = ErrorClass(self)
...
def update_error_messsage(self, error_code):
self.error_code.delete(0, 'end')
self.error_code.insert(0, error_code)
class ErrorClass():
def __init__(self, app):
self.app = app
def update_error(self):
...
error_code = 42
self.app.update_error_message(error_code)
I am trying to start a graph (which is it's getting data from serial port) on a button's click. I had tried the following code but was not successful. I am new to python. Please help me in guiding were I am wrong.
I am using Python 2.7 with Tkinter
Thanks in advance
import serial
import Tkinter as tk
import ttk
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import figureCanvasTkAgg
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import tkFileDialog
x = []
adc_data = []
f = plt.Figure(figsize = (9,5), dpi = 100)
ax = f.add_subplot(111)
def select(self):
self.BaudRate = self.Baud.get()
self.COMPort = self.COM.get()
self.ser = serial.Serial(port = self.COMPort, baudrate = self.BaudRate,bytesize = serial.EIGHTBITS, stopbits = serial.STOPBITS_ONE, parity = serial.PARITY_NONE)
self.ser.close()
self.ser.open()
self.ser.flushInput();
self.ser.flushOutput();
def quit_(self):
self.ser.close()
def animate_(i):
self.ser.write(str(chr(250)))
data = self.ser.read(1)
data1 = self.ser.read(1)
LSB = ord(data)
MSB = ord(data1)
x.append(LSB)
adc_data.append(MSB) #adding data to list
plt.pause(.00001)
ax.clear()
ax.plot(x,adc_data)
def animate_button(self):
ani = animation.FuncAnimation(f, animate_,interval=1000)
class ADC_Ref_Data(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_geometry(self, '900x600+200+150')
tk.Tk.wm_title(self, "ADC Reference")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
frame.grid(row=0, column=0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
self.button = ttk.Button(self, text="Stop", state = 'disable',
command=lambda: quit_(self))
self.button.place(relx = 0.97, rely = 0.95, height = 30 , width = 80, anchor = 'se')
button2 = ttk.Button(self, text="Select",
command = lambda:select(self))
button2.place(relx = 0.97, rely = 0.016, height = 30 , width = 80, anchor = 'ne')
button4 = ttk.Button(self, text="Start",
command=lambda: animate_button(self))
button4.place(relx = 0.03, rely = 0.95, height = 30 , width = 80 , anchor = 'sw')
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.get_tk_widget().place(relx = 0.5, rely = 0.48, relwidth = 1, relheight = 0.8, anchor = 'center' )
app = ADC_Ref_Data()
app.mainloop()
I got success in getting my plot to start on button click.
To get my code working I just need to add a simple line in it which is as follow:
def animate_button(self):
ani = animation.FuncAnimation(f, animate_,frames = 10, interval=1000)
f.canvas.show()
I know this is an old question, but for future travelers: There are a couple functions that are not documented that you can use to control the animation. See this answer for an example of start, stop and pause.
I have a wxgrid inside a resizable scrollable panel. I dynamically add/hide/show rows in wxgrid. When I try to add/show more rows in wxgrid, it does not fit to the available space in panel but instead occupies a small area it had been occupying previously with a scrollbar for wxgrid.
Like this:
But after I resize the panel or frame, then it fits perfectly. Like this:
How can I make it to fit properly without needing to resize the panel?
I have tried all combinations of wx.EXPAND, wx.GROW, wx.ALL while adding grid to sizer and also tried gridobj.Layout() Nothing works. Any Ideas?
Iam using wx 3.0 with python 2.7 on windows 7
Edit:
Here's my code
controls.py
import wx
import wx.grid
import wx.combo
class SimpleGrid(wx.grid.Grid):
def __init__(self, parent):
wx.grid.Grid.__init__(self, parent, -1)
self.CreateGrid(10, 5)
for i in range(10):
self.SetRowLabelValue(i,str(i))
class ListCtrlComboPopup(wx.ListCtrl, wx.combo.ComboPopup):
def __init__(self,parent):
self.gfobj = parent
self.PostCreate(wx.PreListCtrl())
self.parent = parent
wx.combo.ComboPopup.__init__(self)
def AddItem(self, txt):
self.InsertStringItem(self.GetItemCount(), txt)
self.Select(0)
def GetSelectedItems(self):
del self.gfobj.selection[:]
current = -1
while True:
next = self.GetNextSelected(current)
if next == -1:
return
self.gfobj.selection.append(next)
current = next
def onItemSelected(self, event):
item = event.GetItem()
self.GetSelectedItems()
self.parent.draw_plot()
def onItemDeSelected(self, event):
self.GetSelectedItems()
self.parent.draw_plot()
def Init(self):
""" This is called immediately after construction finishes. You can
use self.GetCombo if needed to get to the ComboCtrl instance. """
self.value = -1
self.curitem = -1
def Create(self, parent):
""" Create the popup child control. Return True for success. """
wx.ListCtrl.Create(self, parent,
style=wx.LC_LIST|wx.SIMPLE_BORDER)
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.onItemDeSelected)
return True
def GetControl(self):
""" Return the widget that is to be used for the popup. """
return self
def SetStringValue(self, val):
""" Called just prior to displaying the popup, you can use it to
'select' the current item. """
idx = self.FindItem(-1, val)
if idx != wx.NOT_FOUND:
self.Select(idx)
def GetStringValue(self):
""" Return a string representation of the current item. """
a = self.GetItemText(self.value)
if self.value >= 0:
return a
return ""
def OnPopup(self):
""" Called immediately after the popup is shown. """
self.state = []
for i in range(self.GetItemCount()):
item = self.GetItem(itemId=i)
self.state.append(item.GetState())
#print self.state
wx.combo.ComboPopup.OnPopup(self)
def OnDismiss(self):
" Called when popup is dismissed. """
wx.combo.ComboPopup.OnDismiss(self)
main.py
import wx
import wx.lib.scrolledpanel
from controls import SimpleGrid
from controls import ListCtrlComboPopup
class GraphFrame(wx.Frame):
title = 'Demo: Data Trending Tool'
def __init__(self):
self.selection = []
self.displaySize = wx.DisplaySize()
wx.Frame.__init__(self, None, -1, self.title,
style = wx.DEFAULT_FRAME_STYLE,
size = (self.displaySize[0]/2, self.displaySize[1]/2))
self.containingpanel = wx.Panel(self, -1)
self.toppanel = wx.Panel(self, -1)
self.splittedwin = wx.SplitterWindow(self.containingpanel, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER)
self.splittedwin.SetMinimumPaneSize(20)
self.gridpanel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
self.panel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
#### GRID
self.grid = SimpleGrid(self.gridpanel)
self.gridpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
self.gridpanelsizer.Add(self.grid, wx.GROW)
self.gridpanel.SetSizer(self.gridpanelsizer)
self.gridpanelsizer.Fit(self)
#### COMBOBOX
self.cc = wx.combo.ComboCtrl(self.toppanel, style=wx.CB_READONLY, size=(200,-1), )
self.cc.SetPopupMaxHeight(140)
popup = ListCtrlComboPopup(self)
self.cc.SetPopupControl(popup)
self.cc.SetText("--select--")
# Add some items to the listctrl
for i in range(10):
popup.AddItem(str(i))
#### SIZER FOR COMBOBOX
self.cbpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
self.cbpanelsizer.Add(self.cc, border = 5,flag = wx.LEFT)
self.toppanel.SetSizer(self.cbpanelsizer)
self.splittedwin.SplitHorizontally(self.gridpanel,self.panel,100)
##### SIZER FOR CONTAININGPANEL
self.cpsizer = wx.BoxSizer(wx.VERTICAL)
self.cpsizer.Add(self.splittedwin, 1, wx.EXPAND, 0)
self.containingpanel.SetSizer(self.cpsizer)
self.cpsizer.Fit(self.containingpanel)
mainsizer = wx.BoxSizer(wx.VERTICAL)
mainsizer.Add(self.toppanel, 0, wx.EXPAND)
mainsizer.Add(self.containingpanel, 1, wx.EXPAND)
self.SetSizerAndFit(mainsizer)
self.panel.SetAutoLayout(1)
self.panel.SetupScrolling()
self.gridpanel.SetAutoLayout(1)
self.gridpanel.SetupScrolling()
self.draw_plot()
def draw_plot(self):
for i in range(10):
if i in self.selection:
self.grid.ShowRow(i)
else:
self.grid.HideRow(i)
self.Layout()
#self.gridpanel.Layout()
if __name__ == "__main__":
app = wx.PySimpleApp()
app.frame = GraphFrame()
app.frame.Show()
app.MainLoop()
To simulate:
1. run main.py It displays a splitted window with a grid with single row in one panel.
Use the drop down to select more than one item (hold ctrl and select)
The wxgrid is cramped to one row space with a wxgrid scrollbar
Resize the panel using the splitter or resize the window. Now all the selected rows appear as required.
Finally found out!!!
With the help of This Answer, found that the problem was trying to redraw the gridpanel using gridpanel.Layout(). Instead redrawing the gridpanelsizer using gridpanelsizer.Layout() worked out!!
Updated main.py:
import wx
import wx.lib.scrolledpanel
from controls import SimpleGrid
from controls import ListCtrlComboPopup
class GraphFrame(wx.Frame):
title = 'Demo: Data Trending Tool'
def __init__(self):
self.selection = []
self.displaySize = wx.DisplaySize()
wx.Frame.__init__(self, None, -1, self.title,
style = wx.DEFAULT_FRAME_STYLE,
size = (self.displaySize[0]/2, self.displaySize[1]/2))
self.containingpanel = wx.Panel(self, -1)
self.toppanel = wx.Panel(self, -1)
self.splittedwin = wx.SplitterWindow(self.containingpanel, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER)
self.splittedwin.SetMinimumPaneSize(20)
self.gridpanel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
self.panel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
#### GRID
self.grid = SimpleGrid(self.gridpanel)
self.gridpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
self.gridpanelsizer.Add(self.grid, wx.GROW)
self.gridpanel.SetSizer(self.gridpanelsizer)
self.gridpanelsizer.Fit(self)
#### COMBOBOX
self.cc = wx.combo.ComboCtrl(self.toppanel, style=wx.CB_READONLY, size=(200,-1), )
self.cc.SetPopupMaxHeight(140)
popup = ListCtrlComboPopup(self)
self.cc.SetPopupControl(popup)
self.cc.SetText("--select--")
# Add some items to the listctrl
for i in range(10):
popup.AddItem(str(i))
#### SIZER FOR COMBOBOX
self.cbpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
self.cbpanelsizer.Add(self.cc, border = 5,flag = wx.LEFT)
self.toppanel.SetSizer(self.cbpanelsizer)
self.splittedwin.SplitHorizontally(self.gridpanel,self.panel,100)
##### SIZER FOR CONTAININGPANEL
self.cpsizer = wx.BoxSizer(wx.VERTICAL)
self.cpsizer.Add(self.splittedwin, 1, wx.EXPAND, 0)
self.containingpanel.SetSizer(self.cpsizer)
self.cpsizer.Fit(self.containingpanel)
mainsizer = wx.BoxSizer(wx.VERTICAL)
mainsizer.Add(self.toppanel, 0, wx.EXPAND)
mainsizer.Add(self.containingpanel, 1, wx.EXPAND)
self.SetSizerAndFit(mainsizer)
self.panel.SetAutoLayout(1)
self.panel.SetupScrolling()
self.gridpanel.SetAutoLayout(1)
self.gridpanel.SetupScrolling()
self.draw_plot()
def draw_plot(self):
for i in range(10):
if i in self.selection:
self.grid.ShowRow(i)
else:
self.grid.HideRow(i)
#self.Layout()
self.gridpanelsizer.Layout()
if __name__ == "__main__":
app = wx.PySimpleApp()
app.frame = GraphFrame()
app.frame.Show()
app.MainLoop()
A great tool to debug this is the WIT (http://wiki.wxpython.org/Widget%20Inspection%20Tool)
With your corrected code I can get it to grow by forcing the sash position, not ideal, but it shows that the 'problem' is with the splitter.
import wx
import wx.lib.scrolledpanel
from controls import SimpleGrid
from controls import ListCtrlComboPopup
class GraphFrame(wx.Frame):
title = 'Demo: Data Trending Tool'
def __init__(self):
self.selection = []
self.displaySize = wx.DisplaySize()
wx.Frame.__init__(self, None, -1, self.title,
style = wx.DEFAULT_FRAME_STYLE,
size = (self.displaySize[0]/2, self.displaySize[1]/2))
self.containingpanel = wx.Panel(self, -1)
self.toppanel = wx.Panel(self, -1)
self.splittedwin = wx.SplitterWindow(self.containingpanel, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER)
self.splittedwin.SetMinimumPaneSize(20)
self.gridpanel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
self.panel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
#### GRID
self.grid = SimpleGrid(self.gridpanel)
self.gridpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
self.gridpanelsizer.Add(self.grid, wx.GROW)
self.gridpanel.SetSizer(self.gridpanelsizer)
self.gridpanelsizer.Fit(self)
#### COMBOBOX
self.cc = wx.combo.ComboCtrl(self.toppanel, style=wx.CB_READONLY, size=(200,-1), )
self.cc.SetPopupMaxHeight(140)
popup = ListCtrlComboPopup(self)
self.cc.SetPopupControl(popup)
self.cc.SetText("--select--")
# Add some items to the listctrl
for i in range(10):
popup.AddItem(str(i))
#### SIZER FOR COMBOBOX
self.cbpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
self.cbpanelsizer.Add(self.cc, border = 5,flag = wx.LEFT)
self.toppanel.SetSizer(self.cbpanelsizer)
self.splittedwin.SplitHorizontally(self.gridpanel, self.panel, 50)
##### SIZER FOR CONTAININGPANEL
self.cpsizer = wx.BoxSizer(wx.VERTICAL)
self.cpsizer.Add(self.splittedwin, 1, wx.EXPAND, 0)
self.containingpanel.SetSizer(self.cpsizer)
mainsizer = wx.BoxSizer(wx.VERTICAL)
mainsizer.Add(self.toppanel, 0, wx.EXPAND)
mainsizer.Add(self.containingpanel, 1, wx.EXPAND)
self.SetSizer(mainsizer)
self.panel.SetupScrolling()
self.gridpanel.SetupScrolling()
self.draw_plot()
def draw_plot(self):
for i in range(10):
if i in self.selection:
self.grid.ShowRow(i)
else:
self.grid.HideRow(i)
s = self.grid.GetBestSize()
print(s)
self.splittedwin.SetSashPosition(s[1])
if __name__ == "__main__":
from wx.lib.mixins.inspection import InspectableApp
app = InspectableApp()
app.frame = GraphFrame()
app.frame.Show()
app.MainLoop()
I am coding with Python 2.7, and I am trying to change the background bitmap image based on a user's radio button selection from a drop down menu in a different window. In the code attached, the Bitmap0 image is the default. By selecting "Photo" menu, then the "Change Photo" menu item, causes a radio box to appear. I want to be able to select Bitmap1 and have the bitmap image change to the Bitmap1 image.
I have unsuccessfully tried pubsub, and I was never confident with how the pubsub module fit into Python. Isn't this possible through accessing the right variables in the right way?
My simplified code is as follows:
import wx
IPaa0 = 0
bgphoto = "bitmap" + str(IPaa0) + ".bmp"
print bgphoto
_ID_Item0 = wx.NewId()
_ID_Item1 = wx.NewId()
_ID_Item2 = wx.NewId()
_ID_Item3 = wx.NewId()
_ID_Item4 = wx.NewId()
_ID_Item5 = wx.NewId()
class cPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
def TogFot(self, fotnum):
print "TogFot Entered"
class aFotoDir(wx.App):
def OnInit(self):
iMainFrame = cMainFrame("Top Frame", (0, 0), (1200, 900))
iMainFrame.Show()
self.SetTopWindow(iMainFrame)
return True
class cMainFrame(wx.Frame):
def __init__(self, title, pos, size):
wx.Frame.__init__(self, None, -1, title, pos, size)
iPanel = cPanel(self)
MenuBar = wx.MenuBar()
mFile = wx.Menu()
MenuBar.Append(mFile, "File")
mFoto = wx.Menu()
MenuBar.Append(mFoto, "Photo")
self.SetMenuBar(MenuBar)
MenuItem0 = wx.Menu()
mFile.Append(_ID_Item0, "Open")
MenuItem1 = wx.Menu()
mFile.Append(_ID_Item1, "Save")
MenuItem2 = wx.Menu()
mFile.Append(_ID_Item2, "Save As")
MenuItem3 = wx.Menu()
mFile.Append(_ID_Item3, "Close")
MenuItem4 = wx.Menu()
mFile.Append(_ID_Item4, "Exit")
MenuItem5 = wx.Menu()
mFoto.Append(_ID_Item5, "Change Photo")
self.Bind(wx.EVT_MENU, self.ClickChFoto, id = _ID_Item5)
img0 = wx.Image(bgphoto, wx.BITMAP_TYPE_ANY)
img1 = wx.StaticBitmap(iPanel, -1, wx.BitmapFromImage(img0))
def ClickChFoto(self, event):
iSecondFrame = cSecondFrame("Input", (50, 0), (400, 300))
iSecondFrame.Show()
return True
class cSecondFrame(cMainFrame):
def __init__(self, title, pos, size):
wx.Frame.__init__(self, None, -1, title, pos, size)
iSecondPanel = wx.Panel(self, -1)
iBut0 = wx.Button(iSecondPanel, -1, "OK", pos = ( 75, 200))
iBut1 = wx.Button(iSecondPanel, -1, "CANCEL", pos = (225, 200))
Plist = ["Bitmap0", "Bitmap1"]
self.iWid0 = wx.RadioBox(iSecondPanel, -1, "Photo Selection", (50, 50),
(200, 100), Plist, 1, wx.RA_SPECIFY_COLS)
self.Bind(wx.EVT_BUTTON, self.ClickOK, iBut0)
self.Bind(wx.EVT_BUTTON, self.ClickCANCEL, iBut1)
def ClickOK(self, event):
print "OK Clicked"
global IPaa0
IPaa0 = self.iWid0.GetSelection()
print IPaa0
global bgphoto
bgphoto = "bitmap" + str(IPaa0) + ".bmp"
print bgphoto
self.Close(True)
def ClickCANCEL(self, event):
print "CANCEL Clicked"
self.Close(True)
#-------------------------------------------------------------------------------
if __name__ == "__main__":
app = aFotoDir(False)
app.MainLoop()
The image files are just two files with the titles "Bitmap0" and "Bitmap1". I didn't know the protocol for uploading images, and they were each over 6 MB in size, so I didn't upload.
I would appreciate any guidance and instruction.
You need to pass a reference of cFrame to cSecondFrame as a parameter to the __init__ of cSecondFrame. Then from within its def ClickOK load the new bitmap as before and set it in img1 and call the Layout() function of cFrame.
Here is my code along with the error message.
from Tkinter import *
class Window01 (Frame):
def __init__(self, master):
Frame.__init__(self)
self.reveal()
self.create_widget()
self.grid()
def create_widget(self):
self.lbl = Label (self, text = "This is a Widget App.")
self.lbl.grid(row =1, column =0, columnspan =2, sticky = W)
self.entbx = Entry(self)
self.entbx.grid(row = 1, column = 1, sticky = W)
self.bttn = Button (self, text = "Widget Button", command = self.reveal)
self.bttn.grid(row = 2, column = 0, sticky = W)
self.txt = Text (self, width =35, height = 5, wrap = WORD)
self.txt.grid(row = 3, column = 0, columnspan =2, sticky = W)
def reveal (self):
contents = self.entbx.get()
if contents =="magic":
message = "Access Granted"
else:
message = "Denied"
self.txt.delete(0.0, END)
elf.txt.insert(0.0, message)
root = Tk()
root.title ("Widget_Button")
root.geometry ("300x150")
app = Window01 (root)
root.mainloop()
File "C:\PyDev\Py_Widgets101\src\Py_Widget03.py", line 10, in init
self.reveal()
File "C:\PyDev\Py_Widgets101\src\Py_Widget03.py", line 30, in reveal
contents = self.entbx.get()
AttributeError: Window01 instance has no attribute 'entbx'
self.entbx is created by create_widget(). You are calling reveal() -- which requires self.entbx -- before you've called create_widget():
self.reveal()
self.create_widget()