So I have to write a BMI calculator. I cannot get it to work tho.
Before I added the class and the methods it was working fine but in order to make the Compute button working I had to use a class. And once I did it broke.
Can you tell me what I am doing wrong?
import wx
class BMI(wx.Frame):
def InitUI(self):
window = wx.Frame(self, title="wx.SpinCtrl", size=(400, 300))
panel = wx.Panel(window)
label = wx.StaticText(panel, label="Body Mass Index", pos=(20, 10))
self.weight = wx.StaticText(panel, label="weight:", pos=(20, 70))
self.height = wx.StaticText(panel, label="height:", pos=(20, 140))
weightset = wx.SpinCtrl(panel, value='0', pos=(100, 70))
heightset = wx.SpinCtrl(panel, value='0', pos=(100, 140))
result = wx.StaticText(panel, label="BMI:", pos=(300, 110))
result2 = wx.StaticText(panel, label=" ", pos=(335, 110))
computeButton = wx.Button(panel, label='Compute', pos=(40, 200))
closeButton = wx.Button(panel, label='Close', pos=(250, 200))
computeButton.Bind(wx.EVT_BUTTON, self.ComBMI)
closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
def ComBMI(self, e):
teglo = self.weight.GetValue()
vis = self.height.GetValue()
bmi = teglo * (pow(vis, 2))
self.result2.SetLabel(str(bmi))
def OnClose(self, e):
self.Close(True)
def main():
app = wx.App()
ex = BMI(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
Uhh, question is why is any of this even working...
Issues (probably incomplete):
No proper initializsation of class BMI (see a tutorial how to use a wx.Frame class properly)
Use of SpinCtrl will either not allow entering height in meter or limit people to 100 cm in heigth (and 100 kg in weight, by the way). Use as TextCtrl instead and parse the value with float (or modify the range/resolution of the SpinCtrl)
You do a self.weigth.GetValue() on a object attribute, but user input goes to self.weightset
Wrong BMI formula (look it up on wiki), linked to that wrong units
You need to resolve the __init__ of your class.
Use the spinctrl values not the text objects.
Define the weight to be a float or explain the value to be input is in Centimetres.
The formula is weight(Kgs) / (height (M) * height) unless you want to set off a plethora of un-necessary crash diets ;)
You may want to add the ability to choose between Metric and Imperial values
import wx
import wx.lib.agw.floatspin as FS
class BMI(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title='BMI Calculatot')
panel = wx.Panel(self)
label = wx.StaticText(panel, label="Body Mass Index", pos=(20, 10))
weightT = wx.StaticText(panel, label="weight (Kgs):", pos=(20, 70))
heightT = wx.StaticText(panel, label="height (M):", pos=(20, 140))
self.weight = wx.SpinCtrl(panel, value='0', min=0, max=500, pos=(100, 70))
#self.height = wx.SpinCtrl(panel, value='0', min=100, max=250, pos=(100, 140))
self.height = FS.FloatSpin(panel, -1, min_val=1.00, max_val=2.50, increment=0.01, pos=(100, 140))
self.height.SetFormat("%f")
self.height.SetDigits(2)
resultT = wx.StaticText(panel, label="BMI:", pos=(300, 110))
self.result = wx.StaticText(panel, label=" ", pos=(335, 110))
computeButton = wx.Button(panel, label='Compute', pos=(40, 200))
closeButton = wx.Button(panel, label='Close', pos=(250, 200))
computeButton.Bind(wx.EVT_BUTTON, self.ComBMI)
closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
def ComBMI(self, e):
teglo = self.weight.GetValue()
vis = self.height.GetValue()
bmi = teglo / (pow(vis, 2))
self.result.SetLabel(str(round(bmi,3)))
def OnClose(self, e):
self.Close(True)
if __name__ == '__main__':
app = wx.App()
ex = BMI()
ex.Show()
app.MainLoop()
Related
I have the following class hierarchy:
wx.Frame derived class; within that frame I have a splitter window, and a wx.Panel based class linked to that splitter window. In the panel I have a button. I am binding an event handler to the button to do some actions. The problem is that most of the actions are supposed to be done within the frame class. So, somehow I have to call a method from the frame class in the button even handler. How can I do that? Relevant part of the code is below.
Cheers
class EPSPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
lbl_SGCR = wx.StaticText(self, label="SGCR", pos=(20, 20))
self.ent_SGCR = wx.TextCtrl(self, value="", pos=(100,20), size=(200,-1))
lbl_SWCR = wx.StaticText(self, label="SWCR", pos=(20, 60))
self.ent_SWCR = wx.TextCtrl(self, value="", pos=(100,60), size=(200,-1))
lbl_SWU = wx.StaticText(self, label="SWU", pos=(20, 100))
self.ent_SWU = wx.TextCtrl(self, value="", pos=(100,100), size=(200,-1))
lbl_SGU = wx.StaticText(self, label="SGU", pos=(20, 140))
self.ent_SGU = wx.TextCtrl(self, value="", pos=(100,140), size=(200,-1))
lbl_SWL = wx.StaticText(self, label="SWL", pos=(20, 180))
self.ent_SWL = wx.TextCtrl(self, value="", pos=(100,180), size=(200,-1))
lbl_SGL = wx.StaticText(self, label="SGL", pos=(20, 220))
self.ent_SGL = wx.TextCtrl(self, value="", pos=(100,220), size=(200,-1))
calc_button = wx.Button(self, label="Calculate", pos=(110,260))
calc_button.Bind(wx.EVT_BUTTON, self.on_btn)
def on_btn(self, event):
self.set_SGCR = float(self.ent_SGCR.GetValue())
self.set_SWCR = float(self.ent_SWCR.GetValue())
self.set_SGU = float(self.ent_SGU.GetValue())
self.set_SWU = float(self.ent_SWU.GetValue())
# these four values in this method I need to pass to the KrFrame class
# instance to process in one of its methods. I also need somehow
# let the frame class know that that button was pressed. How can I do it?
class KrFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,
title='Gas Relative Permeability Editor', size=(900, 800))
self.sp = wx.SplitterWindow(self)
self.rightSplitter = wx.SplitterWindow(self.sp) #Another splitter to split right panel into two vertical ones
self.leftSplitter = wx.SplitterWindow(self.sp)
self.panel01 = KrPanel(self.leftSplitter)
self.panel02 = PlotPanel(self.rightSplitter)
self.panel03 = EPSPanel(self.rightSplitter) #Third panel for scaled end point entry
self.panel04 = KrPanel(self.leftSplitter)
self.rightSplitter.SplitHorizontally(self.panel02, self.panel03, 400) #Splitting right panel into two horizontally
self.leftSplitter.SplitHorizontally(self.panel01, self.panel04, 400)
self.sp.SplitVertically(self.leftSplitter, self.rightSplitter, 450)
self.create_menu()
self.Show()
if __name__ == '__main__':
app = wx.App(False)
frame = KrFrame()
app.MainLoop()
del app
Thanks Rolf. The issue is with sharing the code is that it already flourished over a number of modules and sharing all of them will result in several metres of scrolling. I found a workaround as below. My understanding is that events are propagated among all parent classes from the child widget. Hence if the button is clicked, wxFrame gets the event too. So, I am doing the bind to an instance of the button class under the constructor of my WxFrame. In the binding I am defining event handling logic. This seems to work:
class KrFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,
title='Gas Relative Permeability Editor', size=(900, 800))
self.sp = wx.SplitterWindow(self)
self.rightSplitter = wx.SplitterWindow(self.sp) #Another splitter to split right panel into two vertical ones
self.leftSplitter = wx.SplitterWindow(self.sp)
self.panel01 = KrPanel(self.leftSplitter)
self.panel02 = PlotPanel(self.rightSplitter)
self.panel03 = EPSPanel(self.rightSplitter) #Third panel for scaled end point entry
This is where I am binding an handler to the button click event
self.panel03.calc_button.Bind(wx.EVT_BUTTON, self.on_btn)
self.panel04 = KrPanel(self.leftSplitter)
self.rightSplitter.SplitHorizontally(self.panel02, self.panel03, 400) #Splitting right panel into two horizontally
self.leftSplitter.SplitHorizontally(self.panel01, self.panel04, 400)
self.sp.SplitVertically(self.leftSplitter, self.rightSplitter, 450)
self.create_menu()
self.Show()
def on_btn(self, event):
self.set_SGCR = float(self.panel03.ent_SGCR.GetValue())
self.set_SWCR = float(self.panel03.ent_SWCR.GetValue())
self.set_SGU = float(self.panel03.ent_SGU.GetValue())
self.set_SWU = float(self.panel03.ent_SWU.GetValue())
print(self.set_SGCR, self.set_SWCR, self.set_SGU, self.set_SWU)
You can call a function defined within the frame, although to do something useful with the data, is made more difficult because you have defined a splitter window, within a splitter window, within a frame.
For future reference, it's best if you can provide a running version of sample code. Many people who could answer the question, do not want to have to re-hash the code to make it run.
This should give you food for thought.
import wx
class EPSPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
#track the real parent for updating purposes
#
self.parent = parent.GrandParent
#
lbl_SGCR = wx.StaticText(self, label="SGCR", pos=(20, 20))
self.ent_SGCR = wx.TextCtrl(self, value="", pos=(100,20), size=(200,-1))
lbl_SWCR = wx.StaticText(self, label="SWCR", pos=(20, 60))
self.ent_SWCR = wx.TextCtrl(self, value="", pos=(100,60), size=(200,-1))
lbl_SWU = wx.StaticText(self, label="SWU", pos=(20, 100))
self.ent_SWU = wx.TextCtrl(self, value="", pos=(100,100), size=(200,-1))
lbl_SGU = wx.StaticText(self, label="SGU", pos=(20, 140))
self.ent_SGU = wx.TextCtrl(self, value="", pos=(100,140), size=(200,-1))
lbl_SWL = wx.StaticText(self, label="SWL", pos=(20, 180))
self.ent_SWL = wx.TextCtrl(self, value="", pos=(100,180), size=(200,-1))
lbl_SGL = wx.StaticText(self, label="SGL", pos=(20, 220))
self.ent_SGL = wx.TextCtrl(self, value="", pos=(100,220), size=(200,-1))
calc_button = wx.Button(self, label="Calculate", pos=(110,260))
calc_button.Bind(wx.EVT_BUTTON, self.on_btn)
def on_btn(self, event):
self.set_SGCR = float(self.ent_SGCR.GetValue())
self.set_SWCR = float(self.ent_SWCR.GetValue())
self.set_SGU = float(self.ent_SGU.GetValue())
self.set_SWU = float(self.ent_SWU.GetValue())
# these four values in this method I need to pass to the KrFrame class
# instance to process in one of its methods. I also need somehow
# let the frame class know that that button was pressed. How can I do it?
KrFrame.mycalculation(self.parent,self.set_SGCR,self.set_SWCR,self.set_SGU,self.set_SWU)
class KrFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,
title='Gas Relative Permeability Editor', size=(900, 800))
self.sp = wx.SplitterWindow(self)
self.rightSplitter = wx.SplitterWindow(self.sp) #Another splitter to split right panel into two vertical ones
self.leftSplitter = wx.SplitterWindow(self.sp)
self.panel01 = wx.Panel(self.leftSplitter)
self.Total = wx.TextCtrl(self.panel01)
self.panel02 = wx.Panel(self.rightSplitter)
self.panel03 = EPSPanel(self.rightSplitter) #Third panel for scaled end point entry
self.panel04 = wx.Panel(self.leftSplitter)
self.rightSplitter.SplitHorizontally(self.panel02, self.panel03, 400) #Splitting right panel into two horizontally
self.leftSplitter.SplitHorizontally(self.panel01, self.panel04, 400)
self.sp.SplitVertically(self.leftSplitter, self.rightSplitter, 450)
# self.create_menu()
self.Total.SetValue("00000.00")
self.Show()
def mycalculation(parent,SGCR=0,SWCR=0,SGU=0,SWU=0):
print ("Total of values:",SGCR,SWCR,SGU,SWU,"=",SGCR+SWCR+SGU+SWU)
parent.Total.SetValue(str(SGCR+SWCR+SGU+SWU))
if __name__ == '__main__':
app = wx.App(False)
frame = KrFrame()
app.MainLoop()
I'm using Python and wxPython to create an UI that lets the user select a XML file in the first combobox and all the components (i.e. buttons) in the XML appears as choices of another combobox below. It's clearly reading correctly as it prints out the right thing in the console as I go through all the XMLs, but I just can't seem to link it back to the combobox I'm looking for.
Here's the code:
import wx
import os
import xml.dom.minidom
from xml.dom.minidom import parse
# get all xmls
path = "C:\Users\William\Desktop\RES\Param"
files = os.listdir(path)
class Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.xmlList = files
self.xmlPickerTitle = wx.StaticText(self, label="XML Picker", pos=(20, 30))
self.xmlPicker = wx.ComboBox(self, pos=(100, 30), size=(500, -1), choices=self.xmlList, style=wx.CB_DROPDOWN)
self.elementsTitle = wx.StaticText(self, label="Elements Found", pos=(20, 100))
# labels
self.buttonsPickerTitle = wx.StaticText(self, pos=(20,120), label="Buttons")
self.buttonList = []
self.buttonsPicker = wx.ComboBox(self, pos=(100, 120), size=(250, -1), choices=buttonList, style=wx.CB_DROPDOWN)
self.Bind(wx.EVT_COMBOBOX, self.XMLSelect,)
def XMLSelect(self, event):
xmlPicked = self.xmlList[event.GetSelection()]
DOMTree = xml.dom.minidom.parse(xmlPicked)
collection = DOMTree.documentElement
buttons = DOMTree.getElementsByTagName("Button")
for button in buttons:
if button.hasAttribute("name"):
buttonList.append(button.getAttribute("name"))
print button.getAttribute("name")
app = wx.App(False)
frame = wx.Frame(None, title = "Auto", size = (800, 600))
panel = Panel(frame)
frame.Show()
app.MainLoop()
Any ideas?
Thanks in advance!
I had an issue with the file name not containing the path so I have had to join them to pass into xmlPicked but that might be a difference between linux and Windows.
The key point is to Clear() and Append() to the ComboBox
Also, Bind to a specific ComboBox because you have 2.
Finally, set the selection for the ComboBox so that it is obvious that you have data available.
import wx
import os
import xml.dom.minidom
from xml.dom.minidom import parse
# get all xmls
path = "/home/whatever"
files = os.listdir(path)
class Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.xmlList = files
self.xmlPickerTitle = wx.StaticText(self, label="XML Picker", pos=(20, 30))
self.xmlPicker = wx.ComboBox(self, pos=(100, 30), size=(500, -1), choices=self.xmlList, style=wx.CB_DROPDOWN)
self.elementsTitle = wx.StaticText(self, label="Elements Found", pos=(20, 100))
# labels
self.buttonsPickerTitle = wx.StaticText(self, pos=(20,120), label="Buttons")
self.buttonList = []
self.buttonsPicker = wx.ComboBox(self, pos=(100, 120), size=(250, -1), choices=self.buttonList, style=wx.CB_DROPDOWN)
self.xmlPicker.Bind(wx.EVT_COMBOBOX, self.XMLSelect,)
def XMLSelect(self, event):
self.buttonsPicker.Clear()
xmlPicked = self.xmlList[event.GetSelection()]
xmlPicked = os.path.join(path,xmlPicked)
DOMTree = xml.dom.minidom.parse(xmlPicked)
collection = DOMTree.documentElement
buttons = DOMTree.getElementsByTagName("Button")
for button in buttons:
if button.hasAttribute("name"):
button_name = str(button.getAttribute("name"))
self.buttonsPicker.Append(button_name)
print button_name
self.buttonsPicker.SetSelection(0)
app = wx.App(False)
frame = wx.Frame(None, title = "Auto", size = (800, 600))
panel = Panel(frame)
frame.Show()
app.MainLoop()
I am trying to create a web crawler based on specific user input. For example, the User Input I am trying to receive is from a ListBox and a text field. Once I have that information, I would like the user to click a button to start the search with the information collected.
This is where I have been getting problems. The EVT function doesn't recognize the listbox since its been linked to the Button evt. Is there a way to solve the problem? Can EVT information be shared with other EVTs?
Here is what I have so far:
import wx # for gui
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'Title', size=(300,200))
tournLevel = ['$10,000', '$15,000', '$20,000', '$50,000','$75,000','$100,000']
levelBox = wx.ListBox(panel, -1, (40, 50), (90, 90), tournLevel)
levelBox.SetSelection(1) # default selection
checkButton = wx.Button(panel, label= "Check Now", pos = (150, 50), size = (90, 40))
self.Bind(wx.EVT_BUTTON, self.OnClick, checkButton)
def OnClick(self, event):
currLevel = event.GetSelection()
print(currLevel) # to test if GetSelection is working
if __name__ == '__main__':
app = wx.App()
frame = MyFrame(parent=None, id=-1)
frame.Show()
app.MainLoop()
I would be very happy if I could just get the button to recognize the ListBox results.
Thank you for your time!
You can just grab it from the listbox, you don't need it from the event. See below:
import wx # for gui
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'Title', size=(300,200))
tournLevel = ['$10,000', '$15,000', '$20,000', '$50,000','$75,000','$100,000']
self.levelBox = wx.ListBox(panel, -1, (40, 50), (90, 90), tournLevel)
self.levelBox.SetSelection(1) # default selection
self.checkButton = wx.Button(panel, label= "Check Now", pos = (150, 50), size = (90, 40))
self.Bind(wx.EVT_BUTTON, self.OnClick, self.checkButton)
def OnClick(self, event):
currLevel = self.levelBox.GetSelection()
print(currLevel) # to test if GetSelection is working
if __name__ == '__main__':
app = wx.App()
frame = MyFrame(parent=None, id=-1)
frame.Show()
app.MainLoop()
More specifically, if you store levelBox as self.levelBox, it will be accessible inside the OnClick method as a MyFrame attribute. You can then use the GetSelection method for this object (not the event), which will get the current selection.
You can make levelBox into a property of the class by turning it into self.levelBox and accessing it that way as #brettb mentioned. However you can get a bit sneakier and do it using a lambda for your callback to pass the Listbox widget to the event handler:
import wx # for gui
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'Title', size=(300,200))
panel = wx.Panel(self)
tournLevel = ['$10,000', '$15,000', '$20,000', '$50,000','$75,000','$100,000']
levelBox = wx.ListBox(panel, -1, (40, 50), (90, 90), tournLevel)
levelBox.SetSelection(1) # default selection
checkButton = wx.Button(panel, label= "Check Now", pos = (150, 50), size = (90, 40))
evt = lambda caller, widget=levelBox: self.OnClick(caller, widget)
checkButton.Bind(wx.EVT_BUTTON, evt)
def OnClick(self, event, widget):
currLevel = widget.GetSelection()
print(currLevel) # to test if GetSelection is working
print widget.GetString(currLevel)
if __name__ == '__main__':
app = wx.App()
frame = MyFrame(parent=None, id=-1)
frame.Show()
app.MainLoop()
Also note that you didn't have panel defined, so your original code doesn't work. See the following for more information:
http://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks
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()
I don't know why the following code not working, please help me out:
import wx
import wx.lib.scrolledpanel as scrolled
class TaskFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent = None, id = -1, title="ScrolledPanel", size = (500, 600))
MainPanel = wx.Panel(self)
NewPanel = scrolled.ScrolledPanel(parent = MainPanel, pos = (100, 100), size = (300, 200), id = -1, style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER, name="panel" )
self.Button = wx.Button(parent = NewPanel, id = -1, label="Log", pos=(500, 30), size=(50, 20))
NewPanel.SetupScrolling()
class TaskApp(wx.App):
def OnInit(self):
self.frame = TaskFrame()
self.frame.Show()
self.SetTopWindow(self.frame)
return True
def main():
App = TaskApp(redirect = False)
App.MainLoop()
if __name__ == "__main__":
main()
The Log button should be in the NewPanel, and the NewPanel should be able to scroll, but it's not, what's the problem?
Try using a sizer. You have to place an object larger than the ScrolledPanel inside it to activate the scrolling (as far as I know), so this should do what I think you're trying to do:
class TaskFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent = None, id = -1, title="ScrolledPanel", size = (500, 600))
MainPanel = wx.Panel(self)
NewPanel = scrolled.ScrolledPanel(parent = MainPanel, pos = (100, 100), size = (300, 200), id = -1, style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER, name="panel" )
PanelSizer = wx.BoxSizer()
InsidePanel = wx.Panel(NewPanel)
self.Button = wx.Button(parent=InsidePanel, id = -1, label="Log", pos=(500, 30), size=(50, 20))
PanelSizer.Add(InsidePanel, proportion=1)
NewPanel.SetSizer(PanelSizer)
NewPanel.SetupScrolling()