Tkinter button 'not defined' when ran - python-2.7

I am following a quick guide online to start using Tk in Python (2.7) and so far, I have this code:
from Tkinter import *
root = Tk()
root.title("Note Taker")
root.mainloop()
button1 = Button(root, text="button1", command = Button1)
button2 = Button(root, text="button2", command = Button2)
button3 = Button(root, text="button3", command = Button3)
text = Entry(root)
listbox = Listbox(root)
text.pack()
button1.pack()
button2.pack()
button3.pack()
listbox.pack()
def Button1():
listbox.insert(END, "button1 pressed")
def Button2():
listbox.insert(END, "button2 pressed")
def Button3():
text_contents = text.get()
listbox.insert(END, text_contents)
text.delete(0,END)
However when I run this, the GUI is loaded, however none of the buttons are shown, instead I am given this 'NameError':
button1 = Button(root, text="button1", command = Button1)
NameError: name 'Button1' is not defined
I'm sure its purely my error however what could be changed to make this run correctly?

Move
def Button1():
listbox.insert(END, "button1 pressed")
before
button1 = Button(root, text="button1", command=Button1)
since command = Button1 references Button1.
And of course, do the same for Button2 and Button3.
Also move
root.mainloop()
to the bottom of the script, so the flow of control does not get caught in the event loop before the Tkinter widgets are defined.
from Tkinter import *
root = Tk()
root.title("Note Taker")
def Button1():
listbox.insert(END, "button1 pressed")
def Button2():
listbox.insert(END, "button2 pressed")
def Button3():
text_contents = text.get()
listbox.insert(END, text_contents)
text.delete(0, END)
button1 = Button(root, text="button1", command=Button1)
button2 = Button(root, text="button2", command=Button2)
button3 = Button(root, text="button3", command=Button3)
text = Entry(root)
listbox = Listbox(root)
text.pack()
button1.pack()
button2.pack()
button3.pack()
listbox.pack()
root.mainloop()

Related

Unable to navigate to the next frame in the window using TKinter

I am trying to navigate to the next frame on which new buttons or new labels will be displayed. I mean frame1 should disappear when user clicks any button of the four buttons and frame2 should appear.But the below code does not work.
from Tkinter import *
import tkFileDialog
from PIL import ImageTk, Image
root = Tk()
#my_widget = Widget-name (its container window, ** its configuration options)
def callback():
path = tkFileDialog.askopenfilename()
print path
def create_widgets_in_first_frame():
first_window_label1 = Label(root, text="Analysis of Machine Learning Methods using Titanic Disaster Dataset",justify=CENTER,font=("Helvetica", 20,"bold")).place(x=200,y=20)
first_window_label5 = Label(root, text="Choose your Method:",justify=LEFT,font=("Helvetica", 15,"italic")).place(x=20,y=180)
first_window_label2 = Label(root, text="Upload your Titanic datasets .csv extension here:",justify=LEFT,font=("Helvetica", 15,"italic")).place(x=20,y=60)
first_window_label3 = Label(root, text="Training dataset ->",justify=LEFT,font=("Helvetica", 12)).place(x=50,y=100)
training_data_path = StringVar()
first_window_entry1 = Entry(root, textvariable=training_data_path).place(x=350,y=100)
first_window_button1 = Button(root, text="Browse",command=lambda:training_data_path.set(tkFileDialog.askopenfilename())).place(x=550,y=100)
first_window_label4 = Label(root, text="Testing dataset ->",justify=LEFT,font=("Helvetica", 12)).place(x=50,y=140)
testing_data_path = StringVar()
first_window_entry2 = Entry(root, textvariable=testing_data_path).place(x=350,y=140)
first_window_button2 = Button(root, text="Browse",command=lambda:testing_data_path.set(tkFileDialog.askopenfilename())).place(x=550,y=140)
first_window_button3 = Button(root, text="Decision Tree",font=("Helvetica", 15))
first_window_button3.place(x=50,y=220)
first_window_button3.bind('<Button-1>', call_second_frame_on_top)
first_window_button4 = Button(root, text="Random Forests",font=("Helvetica", 15))
first_window_button4.place(x=350,y=220)
first_window_button4.bind('<Button-1>', call_second_frame_on_top)
first_window_button5 = Button(root, text="Logistic Regression",font=("Helvetica", 15))
first_window_button5.place(x=650,y=220)
first_window_button5.bind('<Button-1>', call_second_frame_on_top)
first_window_button6 = Button(root, text="Analysis",font=("Helvetica", 15))
first_window_button6.place(x=1000,y=220)
first_window_button6.bind('<Button-1>', call_second_frame_on_top)
def create_widgets_in_second_frame():
second_window_label6 = Label(root, text="Decision Trees",justify=CENTER,font=("Helvetica", 20,"bold")).place(x=200,y=20)
print "graph is below"
def call_second_frame_on_top(event):
first_frame.grid_forget()
second_frame.grid(column=0, row=0, padx=20, pady=5)
window_width = 1300
window_heigth = 700
first_frame=Frame(root, width=window_width, height=window_heigth)
first_frame['borderwidth'] = 2
first_frame['relief'] = 'sunken'
first_frame.grid(column=0, row=0, padx=20, pady=5)
second_frame=Frame(root, width=window_width, height=window_heigth)
second_frame['borderwidth'] = 2
second_frame['relief'] = 'sunken'
second_frame.grid(column=0, row=0, padx=20, pady=5)
create_widgets_in_second_frame()
create_widgets_in_first_frame()
second_frame.grid_forget()
#root.minsize(width=1300, height=700)
#root.configure(background='lavender')
root.mainloop()
The problem is that you put all the widgets into root which is the whole window, so when you forget the frame, you forget nothing, as nothing is in the frame.
Just change the root to first_frame
Here is a working code:
from Tkinter import *
import tkFileDialog
from PIL import ImageTk, Image
root = Tk()
#my_widget = Widget-name (its container window, ** its configuration options)
def callback():
path = tkFileDialog.askopenfilename()
print path
def create_widgets_in_first_frame():
first_window_label1 = Label(first_frame, text="Analysis of Machine Learning Methods using Titanic Disaster Dataset",justify=CENTER,font=("Helvetica", 20,"bold")).place(x=200,y=20)
first_window_label5 = Label(first_frame, text="Choose your Method:",justify=LEFT,font=("Helvetica", 15,"italic")).place(x=20,y=180)
first_window_label2 = Label(first_frame, text="Upload your Titanic datasets .csv extension here:",justify=LEFT,font=("Helvetica", 15,"italic")).place(x=20,y=60)
first_window_label3 = Label(first_frame, text="Training dataset ->",justify=LEFT,font=("Helvetica", 12)).place(x=50,y=100)
training_data_path = StringVar()
first_window_entry1 = Entry(first_frame, textvariable=training_data_path).place(x=350,y=100)
first_window_button1 = Button(first_frame, text="Browse",command=lambda:training_data_path.set(tkFileDialog.askopenfilename())).place(x=550,y=100)
first_window_label4 = Label(first_frame, text="Testing dataset ->",justify=LEFT,font=("Helvetica", 12)).place(x=50,y=140)
testing_data_path = StringVar()
first_window_entry2 = Entry(first_frame, textvariable=testing_data_path).place(x=350,y=140)
first_window_button2 = Button(first_frame, text="Browse",command=lambda:testing_data_path.set(tkFileDialog.askopenfilename())).place(x=550,y=140)
first_window_button3 = Button(first_frame, text="Decision Tree",font=("Helvetica", 15))
first_window_button3.place(x=50,y=220)
first_window_button3.bind('<Button-1>', call_second_frame_on_top)
first_window_button4 = Button(first_frame, text="Random Forests",font=("Helvetica", 15))
first_window_button4.place(x=350,y=220)
first_window_button4.bind('<Button-1>', call_second_frame_on_top)
first_window_button5 = Button(first_frame, text="Logistic Regression",font=("Helvetica", 15))
first_window_button5.place(x=650,y=220)
first_window_button5.bind('<Button-1>', call_second_frame_on_top)
first_window_button6 = Button(first_frame, text="Analysis",font=("Helvetica", 15))
first_window_button6.place(x=1000,y=220)
first_window_button6.bind('<Button-1>', call_second_frame_on_top)
def create_widgets_in_second_frame():
second_window_label6 = Label(root, text="Decision Trees",justify=CENTER,font=("Helvetica", 20,"bold")).place(x=200,y=20)
print "graph is below"
def call_second_frame_on_top(event):
first_frame.grid_forget()
second_frame.grid(column=0, row=0, padx=20, pady=5)
window_width = 1300
window_heigth = 700
first_frame=Frame(root, width=window_width, height=window_heigth)
first_frame['borderwidth'] = 2
first_frame['relief'] = 'sunken'
first_frame.grid(column=0, row=0, padx=20, pady=5)
second_frame=Frame(root, width=window_width, height=window_heigth)
second_frame['borderwidth'] = 2
second_frame['relief'] = 'sunken'
second_frame.grid(column=0, row=0, padx=20, pady=5)
create_widgets_in_second_frame()
create_widgets_in_first_frame()
second_frame.grid_forget()
#root.minsize(width=1300, height=700)
#root.configure(background='lavender')
root.mainloop()
Note, that the label you get when you click any buttons is still in the main root so you will have to put that into the second_frame, or wherever you wish.

How to delete Entry text when disabling and re-enabling widget

Is there any way that i can delete the user input in an entry widget when it's state is disabled and re-enabled? The user input stays as is, I would like to it without having to add a button event.
from Tkinter import *
class Interface():
def __init__(self, window):
frame = Frame(window)
frame.pack()
self.hopLabel = Label(frame, text="Number:", anchor=E)
self.hopLabel.grid(row=0, column=0, sticky=EW)
options = range(0,6)
options.append("Other")
self.variable = StringVar(frame)
self.variable.set(options[0])
self.options = OptionMenu(frame, self.variable, *options, command=self.this)
self.options.grid(row=0, column=2, sticky=EW)
self.button = Button(frame,text = "Print Value",width=20,command = self.printit(self.variable.get()))
self.button.grid(row=1)
self.otherEntry = Entry(frame, state=DISABLED)
self.otherEntry.grid(row=0, column=1, sticky=EW)
def this(self, value):
if value == "Other":
self.otherEntry.config(state=NORMAL)
else:
self.otherEntry.config(state=DISABLED)
def printit(self,value):
print value
if __name__ == "__main__":
root = Tk()
app = Interface(root)
root.mainloop()
In order to save space, i didn't add the function that prints the value of the "Other" option. My question again is: Is there anyway to delete the value in the entry box when the state of the widget goes from DISABLED to NORMAL without having to press a button?
To delete the text in an entry widget when the state is disabled, you simply need to set the state to normal first and then call the delete method:
def this(self, value):
if value == "Other":
self.otherEntry.config(state=NORMAL)
self.otherEntry.delete(0, "end")
...

Tkinter grid manager cutting off buttons

I have the following layout:
btnReset = Button(self.upperButtonFrame, text = "Reset", width = 12, command=self.__parent.reset)
btnReset.grid(row=0, column=0, sticky="W", pady=5)
btnRender = Button(self.upperButtonFrame, text = "Render", width = 9, command = self.render)
btnRender.grid(row=0, column=1, pady=5)
self.bScattered = Radiobutton(self.upperButtonFrame, text="Backscattered", variable=self.plotType, value=1).grid(row=1, column=0, sticky="W")
self.depolarized = Radiobutton(self.upperButtonFrame, text="Depolarized", variable=self.plotType, value=2).grid(row=2, column=0, sticky="W")
self.rng = Label(self.upperButtonFrame, text="Step").grid(row=3, column=0, sticky="W")
self.e = Entry(self.upperButtonFrame).grid(row=3,column=1)
self.to = Label(self.upperButtonFrame, text="to").grid(row=3, column=2)
self.e2 = Entry(self.upperButtonFrame).grid(row=3,column=3)
The problem is my third row looks like:
Instead of evenly spacing the 4 widgets I'm trying to place. How can I fix grid manager cutting off the last two and evenly space them on the screen?
EDIT: Here's a minimal example of my problem, running it should reproduce the results shown above
from Tkinter import Label, Toplevel, Frame, Button, IntVar, \
BOTH, BOTTOM, Radiobutton, Entry, TOP, Tk
CHILDWIDTH = 200
CHILDHEIGHT = 325
class ToolsWindow(Toplevel):
def __init__(self, root):
Toplevel.__init__(self, root)
self.__root = root
self.plotType = IntVar()
self.title("Tools")
self.geometry('%dx%d+%d+%d' % (CHILDWIDTH, CHILDHEIGHT,0, 0))
#self.resizable(width=FALSE, height=FALSE)
self.protocol("WM_DELETE_WINDOW", ToolsWindow.ignore)
self.container = Frame(self, background="red")
self.container.pack(side=TOP, fill=BOTH, expand=True )
self.coordinateFrame = Frame(self.container, background="green", width=50, height=50)
self.coordinateFrame.config(highlightthickness=1) # create a small border around the frame
self.coordinateFrame.config(highlightbackground="grey")
self.coordinateFrame.pack(side=BOTTOM, fill=BOTH, expand=False)
#staticmethod
def ignore():
pass
def setupToolBarButtons(self):
self.upperButtonFrame = Frame(self.container, background="blue") # upper button frame holding text buttons
self.upperButtonFrame.pack(side=TOP)
btnReset = Button(self.upperButtonFrame, text = "Reset", width = 12, command=self.render)
btnReset.grid(row=0, column=0, sticky="w")
btnRender = Button(self.upperButtonFrame, text = "Render", width = 9, command = self.render)
btnRender.grid(row=0, column=1, sticky="w")
self.bScattered = Radiobutton(self.upperButtonFrame, text="Backscattered",
variable=self.plotType, value=1).grid(row=1, column=0, sticky="w")
self.depolarized = Radiobutton(self.upperButtonFrame, text="Depolarized",
variable=self.plotType, value=2).grid(row=2, column=0, sticky="w")
self.rng = Label(self.upperButtonFrame, text="Step")
self.rng.grid(row=3, column=0, sticky="w")
self.e = Entry(self.upperButtonFrame, width=8)
self.e.grid(row=3, column=1, sticky="w")
self.to = Label(self.upperButtonFrame, text="to")
self.to.grid(row=3, column=2, sticky="w")
self.e2 = Entry(self.upperButtonFrame, width=8)
self.e2.grid(row=3, column=3, sticky="w")
def render(self):
pass
root = Tk()
tool = ToolsWindow(root)
tool.setupToolBarButtons()
root.mainloop()
The slightly modified program posted below renders properly, so it must be something in the code you did not post that is causing the problem. Are you limiting the size of the root window's, geometry anywhere? I do not know what you mean by "evenly spaced" but you can use the width parameter on most widgets to increase the size.
from Tkinter import *
class TestIt(object):
def __init__(self, top):
self.upperButtonFrame=top
btnReset = Button(self.upperButtonFrame, text = "Reset", width = 12)
btnReset.grid(row=0, column=0, sticky="W", pady=5)
btnRender = Button(self.upperButtonFrame, text = "Render", width = 9)
btnRender.grid(row=0, column=1, pady=5)
self.bScattered = Radiobutton(self.upperButtonFrame, text="Backscattered").grid(row=1, column=0
self.depolarized = Radiobutton(self.upperButtonFrame, text="Depolarized").grid(row=2, column=0,
self.rng = Label(self.upperButtonFrame, text="Step").grid(row=3, column=0, sticky="e")
self.e = Entry(self.upperButtonFrame).grid(row=3,column=1)
self.to = Label(self.upperButtonFrame, text="to").grid(row=3, column=2, sticky="e")
self.e2 = Entry(self.upperButtonFrame).grid(row=3,column=3)
top = Tk()
TI=TestIt(top)
top.mainloop()

wxpython: adding rows to wxgrid dynamically does not fit to panel

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

Tkinter's class.__init__() executes widget functions defined in it

I am writing a GUI for my application using Tkinter. I am using class to describe the whole structure, as described here. For some reason this program runs commands bounded to buttons (even though one of buttons is disabled) on start-up and doesn't react on same buttons afterwards. Please see my code below.
from Tkinter import *
from new_plot_main import PlotClass
class MainWindow:
def __init__(self, master):
Frame(master).grid()
self.main_check = [NoneType, NoneType, NoneType, NoneType]
self.scope_check = [NoneType, NoneType, NoneType, NoneType]
self.main_check[0] = Checkbutton(master, text="Lines")
self.main_check[1] = Checkbutton(master, text="Errors")
self.main_check[2] = Checkbutton(master, text="Upstream Snr")
self.main_check[3] = Checkbutton(master, text="Downstream Snr")
self.scope_check[0] = Checkbutton(master, text="Lines")
self.scope_check[1] = Checkbutton(master, text="Errors")
self.scope_check[2] = Checkbutton(master, text="Upstream Snr")
self.scope_check[3] = Checkbutton(master, text="Downstream Snr")
self.stats_check = Checkbutton(master, text="Enable statistics") # Statistics trigger
self.csi_check = Checkbutton(master, text="Enable CSI") # CSI calculation trigger
self.scope_range = Entry(master, width=15).grid(row=4, column=3) # To specify scope range
self.lines_entry = Entry(master, width=15).grid(row=6, column=1) # Lines to analyze
self.save_to_pdf_button = Button(master,
text="Save to PDF",
state=DISABLED,
width=10)
self.plot_button = Button(master, text="Plot", width=10, command=self.plot_action())
self.set_button = Button(master,
text="Set", state=DISABLED,
width=10, command=self.scope_action()) # Button to apply range from scope_range
#------Setting coordinates via grid--------
Label(master, text="Main", font=("Helvetica", 10, "bold")).grid(row=0, column=0, sticky=SW)
Label(master, text="Scope", font=("Helvetica", 10, "bold")).grid(row=0, column=1, sticky=SW)
Label(master, text="Options", font=("Helvetica", 10, "bold")).grid(row=0, column=3, sticky=SW)
Label(master, text="Lines to plot").grid(row=6, column=0, sticky=E)
Label(master, text="Set scope").grid(row=3, column=3, sticky=S)
self.stats_check.grid(row=1, column=3, sticky=W)
self.stats_check.select()
self.csi_check.grid(row=2, column=3, sticky=W)
self.csi_check.select()
self.save_to_pdf_button.grid(row=6, column=4, sticky=E)
self.plot_button.grid(row=6, column=2, sticky=W)
self.set_button.grid(row=4, column=4, sticky=W)
for i in xrange(0, 4):
self.main_check[i].grid(row=i+1, column=0, sticky=W)
self.scope_check[i].grid(row=i+1, column=1, sticky=W)
self.main_check[i].select()
self.scope_check[i].select()
def plot_action(self):
# plot = PlotClass()
# self.top = Toplevel()
print "Potatoes"
def scope_action(self):
# self.bot = Toplevel()
print "Banana"
def handler():
"""
Exiting GUI and stopping all processes, when system exit button is pressed.
"""
root.quit()
root.destroy()
root = Tk()
root.wm_title("Plot tool [new]")
app = MainWindow(root)
root.protocol("WM_DELETE_WINDOW", handler)
root.mainloop()
This code outputs Potatoes Banana upon execution.
You need to use just the function, not the function result. Instead of:
self.plot_button = Button(master, text="Plot", width=10,
command=self.plot_action())
and
self.set_button = Button(master, text="Set", state=DISABLED,
width=10, command=self.scope_action())
use:
self.plot_button = Button(master, text="Plot", width=10,
command=self.plot_action)
and
self.set_button = Button(master, text="Set", state=DISABLED,
width=10, command=self.scope_action)
That way the commands will be called only when the button is pressed.