Getting an error on button events in wxPython - python

I'm facing the following problem - Whenever I try to make an event listener to any of my buttons I get the following error:
self.button_compute.Bind(wx.EVT_BUTTON, self.on_click)
AttributeError: 'BMICalculator' object has no attribute 'button_compute'
I tried the suggested solution in this thread: AttributeError: 'module' object has no attribute 'PyScrolledWindow' in wxPython ,but it didn't work for me.
The program is for calculating the BMI and here's the code:
import wx
class BMICalculator(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "BMI calculator", (600, 800))
panel = wx.Panel(self)
self.Centre()
#Creating the buttons and text fields
static_text_height = wx.StaticText(panel, -1, "Height", (170, 10))
height = wx.SpinCtrl(panel, -1, pos=(164, 40), size=(60, -1))
static_text_weight = wx.StaticText(panel, -1, "Weight", (170, 100))
weight = wx.SpinCtrl(panel, -1, pos=(164, 130), size=(60, -1))
button_compute = wx.Button(panel, label="Compute", pos=(110, 180), size=(60, -1))
button_cancel = wx.Button(panel, label="Cancel", pos=(210, 180), size=(60, -1))
result_text = wx.StaticText(panel, -1, "Enter your height and weight and press compute", (68, 220))
#Adding the events for the buttons (Where I get the error)
self.button_compute.Bind(wx.EVT_BUTTON, self.on_click)
self.button_cancel.Bind(wx.EVT_CLOSE, self.click_close)
def compute_BMI(height, weight):
#BMI = x KG / (y M * y M)
height_m = height/100
BMI = weight/(height_m * height_m)
return BMI
def click_close(self, event):
self.Close(True)
def on_click(self, event):
result_text.SetValue(compute_BMI(height.GetValue(), weight.GetValue()))
def main():
app = wx.App()
frame = BMICalculator(None, -1)
frame.Show()
app.MainLoop()
enter code here
if __name__ == '__main__':
main()
Any help will be appreciated!

When you create button_compute you leave it as a local variable to the function. When you try to bind the event, you then try to read from an instance attribute that you haven't created yet. You actually do this in many cases, but your script is erring out on the first one. Add self.xxx to your assignments to make instance attributes rather than local variables to the function.
import wx
class BMICalculator(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "BMI calculator", (600, 800))
self.panel = wx.Panel(self)
self.Centre()
#Creating the buttons and text fields
self.static_text_height = wx.StaticText(self.panel, -1, "Height", (170, 10))
self.height = wx.SpinCtrl(self.panel, -1, pos=(164, 40), size=(60, -1))
self.static_text_weight = wx.StaticText(self.panel, -1, "Weight", (170, 100))
self.weight = wx.SpinCtrl(self.panel, -1, pos=(164, 130), size=(60, -1))
self.button_compute = wx.Button(self.panel, label="Compute", pos=(110, 180), size=(60, -1))
self.button_cancel = wx.Button(self.panel, label="Cancel", pos=(210, 180), size=(60, -1))
self.result_text = wx.StaticText(self.panel, -1, "Enter your height and weight and press compute", (68, 220))
#Adding the events for the buttons (Where I get the error)
self.button_compute.Bind(wx.EVT_BUTTON, self.on_click)
self.button_cancel.Bind(wx.EVT_CLOSE, self.click_close)
def compute_BMI(height, weight):
#BMI = x KG / (y M * y M)
height_m = height/100
BMI = weight/(height_m * height_m)
return BMI
def click_close(self, event):
self.Close(True)
def on_click(self, event):
self.result_text.SetValue(self.compute_BMI(self.height.GetValue(), self.weight.GetValue()))
def main():
app = wx.App()
frame = BMICalculator(None, -1)
frame.Show()
app.MainLoop()
#enter code here
if __name__ == '__main__':
main()

Related

GUI Window Does Not Resize as indicated

I set the size in my panel, but it does not take action when I run the program. It just pops up small and I have to manually resize.
I have tried setting/initializing a frame, but when I do that it blocks any input. So I can no longer use my program. I have also tried numerous times to set it within the panel settings.
class CipherTexter(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, size=(5000, 5000))
#wx.Frame.__init__(self, parent, size=(5000, 5000))
self.cipherText = wx.StaticText(self, label="Cipher Texter ", pos=(20, 30))
…
app = wx.App(False)
frame = wx.Frame(None, wx.ID_ANY, "The SS Cipher")
panel = CipherTexter(frame)
frame.Show()
app.MainLoop()
When I first open the application, I get this. I would like to be able to see the whole thing instead of having to manually resize it.
Try putting the "panel" within the "frame".
Here is a mock up of what is, I suppose, your required starting point.
import wx
class CipherTexter(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(1000, 600))
self.panel = wx.Panel(self)
cipherText = wx.StaticText(self.panel, label="Cipher Texter ", pos=(20, 30))
encryptorText = wx.StaticText(self.panel, label="Encryptor ", pos=(20, 70))
decryptorText = wx.StaticText(self.panel, label="Decryptor ", pos=(20, 100))
self.cipher = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE, size=(400,400), pos=(400, 30))
self.encryptor = wx.TextCtrl(self.panel, -1, size=(100,30), pos=(200, 70))
self.decryptor = wx.TextCtrl(self.panel, -1, size=(100,30), pos=(200, 100))
self.encrypt = wx.Button(self.panel, -1, "Encrypt", pos=(20, 140))
self.decrypt = wx.Button(self.panel, -1, "Decrypt", pos=(20, 180))
self.panel.SetBackgroundColour('white')
self.encrypt.Bind(wx.EVT_BUTTON, self.encryptNow)
self.decrypt.Bind(wx.EVT_BUTTON, self.decryptNow)
self.Show()
def encryptNow(self, event):
print("Encrypting")
cipher = self.cipher.GetValue()
encryptor = self.encryptor.GetValue()
print(cipher)
print("with ", encryptor)
def decryptNow(self, event):
print("De-Encrypting")
cipher = self.cipher.GetValue()
decryptor = self.decryptor.GetValue()
print(cipher)
print("with ", decryptor)
app = wx.App(False)
frame = CipherTexter(None, "The SS Cipher")
app.MainLoop()

TextCtrl doesn't work properly with CheckBox

I wrote a code to receive some input data from user using both CheckBox and TextCtrl. The problem is when I marked the checkbox and textctrl appears, it accept to receive input data, but won't replace with the default one!
import wx
class mainClass(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Interface', size=(500, 250))
self.panel = wx.Panel(self)
self.checkReplaceJob = wx.CheckBox(self.panel, -1, "Replace data", (35, 60), (235, 20))
self.Bind(wx.EVT_CHECKBOX, self.replaceJob, self.checkReplaceJob)
self.RunBut = wx.Button(self.panel, -1, "Run", pos=(150, 150))
self.Bind(wx.EVT_BUTTON, self.RunClick, self.RunBut)
self.RunBut.SetDefault()
self.CloseBut = wx.Button(self.panel, -1, "Close", pos=(250, 150))
self.Bind(wx.EVT_BUTTON, self.CloseClick, self.CloseBut)
def CloseClick(self, event):
self.Close()
def replaceJob(self, event):
if(self.checkReplaceJob.IsChecked()):
self.repJobRetName()
self.btn = wx.Button(self.panel, wx.ID_ANY, "&Help", pos=(345, 82))
self.Bind(wx.EVT_BUTTON, self.HelpJobName, self.btn)
def repJobRetName(self):
self.label = wx.StaticText(self.panel, -1, label = "New name:", pos=(165,87))
self.entry = wx.TextCtrl(self.panel, -1, value = u"Task-1", pos=(230, 84))
repJobName = self.entry.GetValue()
return repJobName
def HelpJobName(self, event):
help = 'Write out new name.'
wx.MessageBox(help, "Help")
def RunClick(self, event):
if(self.checkReplaceJob.IsChecked()):
replaceName = self.repJobRetName()
wx.MessageBox('The new name is: ' + replaceName, "Info")
#############=======================
if __name__ == "__main__":
app = wx.App(False)
mainClass().Show()
app.MainLoop()
Let me make sure I understand correctly. You want the text control to have a default value when it is created, but you want that value to disappear when you actually select the control. Is that correct? If so, then you just need to add a binding to wx.EVT_SET_FOCUS and do a little work when the widget gets focus. Here's an example:
import wx
class mainClass(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Interface', size=(500, 250))
self.panel = wx.Panel(self)
self.checkReplaceJob = wx.CheckBox(self.panel, -1, "Replace data", (35, 60), (235, 20))
self.Bind(wx.EVT_CHECKBOX, self.replaceJob, self.checkReplaceJob)
self.RunBut = wx.Button(self.panel, -1, "Run", pos=(150, 150))
self.Bind(wx.EVT_BUTTON, self.RunClick, self.RunBut)
self.RunBut.SetDefault()
self.CloseBut = wx.Button(self.panel, -1, "Close", pos=(250, 150))
self.Bind(wx.EVT_BUTTON, self.CloseClick, self.CloseBut)
def CloseClick(self, event):
self.Close()
def replaceJob(self, event):
if(self.checkReplaceJob.IsChecked()):
self.repJobRetName()
self.btn = wx.Button(self.panel, wx.ID_ANY, "&Help", pos=(345, 82))
self.Bind(wx.EVT_BUTTON, self.HelpJobName, self.btn)
def repJobRetName(self):
self.label = wx.StaticText(self.panel, -1, label = "New name:", pos=(165,87))
self.entry = wx.TextCtrl(self.panel, -1, value = u"Task-1", pos=(230, 84))
self.entry.Bind(wx.EVT_SET_FOCUS, self.onFocus)
repJobName = self.entry.GetValue()
return repJobName
def onFocus(self, event):
current_value = self.entry.GetValue()
if current_value == "Task-1":
self.entry.SetValue("")
def HelpJobName(self, event):
help = 'Write out new name.'
wx.MessageBox(help, "Help")
def RunClick(self, event):
if(self.checkReplaceJob.IsChecked()):
replaceName = self.repJobRetName()
wx.MessageBox('The new name is: ' + replaceName, "Info")
#############=======================
if __name__ == "__main__":
app = wx.App(False)
mainClass().Show()
app.MainLoop()

wxpython frame update with a button click

In progress of making an wxpython assignment for school, I stumbled on something I can't seem to figure out by myself.
The main idea of the assignment is to make a self-generating quiz. Now I made a frame were the questions should be in the future.
I need this frame to update itself with the button for the next question (middle one), so the next question is showing when clicking the button.
Before actually doing that I tried testing it with a random number generator. But the update button doesn't seem to update to a new frame with a new number (looking the same, only the number changing). I know I'm missing something, but I don't know where to start.
Here is my code:
import wx
import random
class welkom(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "Aminozuurtoets V.1.0", size=(900,600))
self.mainFrame = mainFrame
top_panel = wx.Panel(self)
w_tekst = wx.StaticText(top_panel, -1, "Welkom bij de aminozuurtoets",(325,50), (100, -1), wx.ALIGN_CENTER)
w_font = wx.Font(20, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
w_tekst.SetFont(w_font)
st_nr = wx.StaticText(top_panel, -1, 'Studentnummer' ,(100,150))
inp_st_nr = wx.TextCtrl(top_panel, -1, '', (300,150), size=(140,-1))
st_vr= wx.StaticText(top_panel, -1, 'Student voornaam' ,(100,200))
inp_st_vr = wx.TextCtrl(top_panel, -1, '', (300,200), size=(140,-1))
st_ach = wx.StaticText(top_panel, -1, 'Student achternaam' ,(100,250))
inp_st_ach = wx.TextCtrl(top_panel, -1, '', (300,250), size=(140,-1))
aan_vr = wx.StaticText(top_panel, -1, 'Aantal vragen' ,(100,300))
inp_aan_vr = wx.TextCtrl(top_panel, -1, '20', (300,300), size=(140,-1))
close_button = wx.Button(top_panel, label = "Stoppen", pos=(600, 400), size=(150, 200))
self.Bind(wx.EVT_BUTTON, self.closebutton, close_button)
go_button = wx.Button(top_panel, label = "Doorgaan", pos=(100, 400), size=(150, 200))
self.Bind(wx.EVT_BUTTON, self.buttonClick, go_button)
def closebutton(self, event):
self.Close(True)
def buttonClick(self, event):
self.Hide()
self.mainFrame(None, id = -1).Show()
class mainFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "Aminozuurtoets V.1.0", size=(900,600))
top_panel = wx.Panel(self)
self.vraag = 1
m_tekst = wx.StaticText(top_panel, -1, "Vraag " + str(self.vraag),(400,50), (100, -1), wx.ALIGN_CENTER)
m_font = wx.Font(20, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
m_tekst.SetFont(m_font)
cijfer = random.randint(1,100)
test2 = wx.StaticText(top_panel, -1, str(cijfer), (325,300))
res_but = wx.Button(top_panel, label = "Resultaten", pos=(650, 400), size=(150, 200))
ga_naar = wx.Button(top_panel, label = "Ga naar vraag", pos=(100, 400), size=(150, 200))
ga_button = wx.Button(top_panel, label = "Volgende vraag", pos=(380, 400), size=(150, 200))
self.Bind(wx.EVT_BUTTON, self.buttonClick1, ga_button)
def buttonClick1(self, event):
self.Update()
def closebutton(self, event):
self.Close(True)
app = wx.App()
frame = welkom(None, id = -1).Show()
app.MainLoop()
Just calling Update doesn't change nothing. I changed mainFrame class. (See comments that starts with ###)
class mainFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "Aminozuurtoets V.1.0", size=(900,600))
top_panel = wx.Panel(self)
self.vraag = 1
m_tekst = wx.StaticText(top_panel, -1, "Vraag " + str(self.vraag),(400,50), (100, -1), wx.ALIGN_CENTER)
m_font = wx.Font(20, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
m_tekst.SetFont(m_font)
cijfer = random.randint(1,100)
### Make an attribute to access from buttonClick1 method.
self.test2 = wx.StaticText(top_panel, -1, str(cijfer), (325,300))
res_but = wx.Button(top_panel, label = "Resultaten", pos=(650, 400), size=(150, 200))
ga_naar = wx.Button(top_panel, label = "Ga naar vraag", pos=(100, 400), size=(150, 200))
ga_button = wx.Button(top_panel, label = "Volgende vraag", pos=(380, 400), size=(150, 200))
self.Bind(wx.EVT_BUTTON, self.buttonClick1, ga_button)
def buttonClick1(self, event):
### Change label of static text.
self.test2.Label = str(random.randint(1,100))
def closebutton(self, event):
self.Close(True)

pop up window creation in wxpython

#!/usr/bin/python
# myconfig.py
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
self.cfg = wx.Config('myconfig')
if self.cfg.Exists('width'):
w, h = self.cfg.ReadInt('width'), self.cfg.ReadInt('height')
else:
(w, h) = (250, 250)
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(w, h))
wx.StaticText(self, -1, 'Width:', (20, 20))
wx.StaticText(self, -1, 'Height:', (20, 70))
self.sc1 = wx.SpinCtrl(self, -1, str(w), (80, 15), (60, -1), min=200, max=500)
self.sc2 = wx.SpinCtrl(self, -1, str(h), (80, 65), (60, -1), min=200, max=500)
wx.Button(self, 1, 'Save', (20, 120))
self.Bind(wx.EVT_BUTTON, self.OnSave, id=1)
self.statusbar = self.CreateStatusBar()
self.Centre()
def OnSave(self, event):
self.cfg.WriteInt("width", self.sc1.GetValue())
self.cfg.WriteInt("height", self.sc2.GetValue())
self.statusbar.SetStatusText('Configuration saved, %s ' % wx.Now())
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'myconfig.py')
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()
how to popup a window if user hits more than max or min value?
You can use the functions wx.MessageDialog, wx.MessageBox or the more improved or wx.lib.agw.genericmessagedialog.GenericMessageDialog.

wxPython display a login box

I'm trying to build a small application in wxPython (absolute beginner) in which I display a login box before showing the content. I created a frame, inside the frame a panel with a flexigrid to put the login form inside but it doesn't show. If I launch the application the login form is invisible. If I resize the application the login box shows. Any idea why? Here's my code so far:
import wx
class AP_App(wx.App):
def OnInit(self):
frame = AP_MainFrame("Test application", (0, 0), (650, 350))
frame.Show()
self.SetTopWindow(frame)
loginPanel = AP_LoginPanel(frame)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
return True
def OnCloseWindow(self, event):
self.Destroy()
class AP_MainFrame(wx.Frame):
def __init__(self, title, pos, size):
wx.Frame.__init__(self, None, -1, title, pos, size)
self.CreateStatusBar()
class AP_LoginPanel(wx.Panel):
def __init__(self, frame):
self.panel = wx.Panel(frame)
self.frame = frame
self.frame.SetStatusText("Authentification required!")
self.showLoginBox()
def showLoginBox(self): #Create the sizer
sizer = wx.FlexGridSizer(rows = 3, cols = 2, hgap = 5, vgap = 15)
# Username
self.txt_Username = wx.TextCtrl(self.panel, 1, size = (150, -1))
lbl_Username = wx.StaticText(self.panel, -1, "Username:")
sizer.Add(lbl_Username,0, wx.LEFT|wx.TOP| wx.RIGHT, 50)
sizer.Add(self.txt_Username,0, wx.TOP| wx.RIGHT, 50)
# Password
self.txt_Password = wx.TextCtrl(self.panel, 1, size=(150, -1), style=wx.TE_PASSWORD)
lbl_Password = wx.StaticText(self.panel, -1, "Password:")
sizer.Add(lbl_Password,0, wx.LEFT|wx.RIGHT, 50)
sizer.Add(self.txt_Password,0, wx.RIGHT, 50)
# Submit button
btn_Process = wx.Button(self.panel, -1, "&Login")
self.panel.Bind(wx.EVT_BUTTON, self.OnSubmit, btn_Process)
sizer.Add(btn_Process,0, wx.LEFT, 50)
self.panel.SetSizer(sizer)
def OnSubmit(self, event):
UserText = self.txt_Username.GetValue()
PasswordText = self.txt_Password.GetValue()
if __name__ == '__main__':
app = AP_App()
app.MainLoop()
I just discovered I'm calling frame.Show() too soon. :)

Categories

Resources