wxpython - One Frame, Multiple Panels, Modularized Code - python

I'm working on a fairly large GUI project and am thus using wxpython to build it. I have one frame, multiple frames with their own functions and a main file that imports the gui components as well as other, external functions. I've decided to keep the gui/wxpython code different to better modularize the code.
The main question I have is how to execute the functions in the separate panels and how to make them work from my main python file.
Below is a sample of my wxpython code:
import wx
class MainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.SetSizer( bSizer1 )
self.Layout()
self.panelOne = panel_one(self)
self.panelTwo = panel_two(self)
self.panelTwo.Hide()
self.Centre( wx.BOTH )
def __del__( self ):
pass
class panel_one ( wx.Panel ):
def __init__( self, parent ):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )
bSizer5 = wx.BoxSizer( wx.VERTICAL )
self.m_button2 = wx.Button( self, wx.ID_ANY, u"MyButton", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer5.Add( self.m_button2, 0, wx.ALL, 5 )
self.SetSizer( bSizer5 )
self.Layout()
# Connect Events
self.m_button2.Bind( wx.EVT_BUTTON, self.changeIntroPanel )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def changeIntroPanel( self, event ):
event.Skip()
class panel_two ( wx.Panel ):
def __init__( self, parent ):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )
... some code in here ...
def __del__( self ):
pass
So those are my gui components. Then, in my main file, I import it and run the gui:
import gui
class MainApp(gui.MainFrame):
def __init__(self, parent):
gui.MainFrame.__init__(self, parent)
self.panelOne = Panel1(self)
self.panelTwo = Panel2(self)
self.panelTwo.Hide()
class Panel1(gui.panel_one):
def __init__(self, parent):
gui.panel_one.__init__(self, parent)
def changeIntroPanel( self, event ):
if self.panelOne.IsShown():
self.SetTitle("Panel Two Showing")
self.PanelOne.Hide()
self.PanelTwo.Show()
else:
self.SetTitle("Panel One Showing")
self.PanelOne.Show()
self.PanelTwo.Hide()
self.Layout()
class Panel2(gui.panel_two):
def __init__(self, parent):
gui.panel_two.__init__(self, parent)
def main():
app = wx.App()
window = MainApp(None)
window.Show(True)
app.MainLoop()
if __name__ == '__main__':
main()
As you can tell, the idea is that I want to do all my implementation in my main file. How would I go about defining the functionality of my changeIntroPanel function that was first defined in panel_one? For now, the idea is to hide panelOne and show panelTwo.
I have done something similar before, but only with one frame. In that case, it was trivial since all the functions are in the MainFrame class to begin with. In that case, the code I posted would work perfectly.
Any help is appreciated. Thank you.

def OnInit(self, parent): is used for wx.App, you need def _ _init_ _(self, parent) instead.
About __init__ please check: Using inheritance in python
About difference between __init__ and OnInit please check this link
Edit:
gui.py
import wx
class MainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.SetSizer( bSizer1 )
self.Layout()
# self.panelOne = panel_one(self)
# self.panelTwo = panel_two(self)
# self.panelTwo.Hide()
self.Centre( wx.BOTH )
def __del__( self ):
pass
class panel_one ( wx.Panel ):
def __init__( self, parent ):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )
bSizer5 = wx.BoxSizer( wx.VERTICAL )
self.m_button2 = wx.Button( self, wx.ID_ANY, u"panel 1 button", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer5.Add( self.m_button2, 0, wx.ALL, 5 )
self.SetSizer( bSizer5 )
self.Layout()
# Connect Events
self.m_button2.Bind( wx.EVT_BUTTON, self.changeIntroPanel )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def changeIntroPanel( self, event ):
event.Skip()
class panel_two ( wx.Panel ):
def __init__( self, parent ):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 800,600 ), style = wx.TAB_TRAVERSAL )
bSizer5 = wx.BoxSizer( wx.VERTICAL )
self.m_button2 = wx.Button( self, wx.ID_ANY, u"panel 2 button ", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer5.Add( self.m_button2, 0, wx.ALL, 5 )
self.SetSizer( bSizer5 )
self.Layout()
# Connect Events
self.m_button2.Bind( wx.EVT_BUTTON, self.changeIntroPanel )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def changeIntroPanel( self, event ):
event.Skip()
mainapp.py
import wx
import gui
class MainApp(gui.MainFrame):
def __init__(self, parent):
gui.MainFrame.__init__(self, parent)
self.panelOne = Panel1(self)
self.panelTwo = Panel2(self)
self.panelTwo.Hide()
class Panel1(gui.panel_one):
def __init__(self, parent):
gui.panel_one.__init__(self, parent)
self.parent = parent
def changeIntroPanel( self, event ):
if self.IsShown():
self.parent.SetTitle("Panel Two Showing")
self.Hide()
self.parent.panelTwo.Show()
class Panel2(gui.panel_two):
def __init__(self, parent):
gui.panel_two.__init__(self, parent)
self.parent = parent
def changeIntroPanel( self, event ):
if self.IsShown():
self.parent.SetTitle("Panel One Showing")
self.parent.panelOne.Show()
self.Hide()
def main():
app = wx.App()
window = MainApp(None)
window.Show(True)
app.MainLoop()
if __name__ == '__main__':
main()

Related

Start / Stop buttons for reading from serial with wxpython

I created a simple GUI with wxpython to read data from a serial port. Based on several posts I was able to connect to the serial port when I press the Connect button and print the data when i press Start button but I press the Stop button I can´t stop printing data.
Here's is my code (inside are the links to the posts previously refered):
# -*- coding: utf-8 -*-
import wx
import wx.xrc
import serial
import time
import threading
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2 = wx.BoxSizer( wx.VERTICAL )
self.connectBtn = wx.Button( self, wx.ID_ANY, u"Connect", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.connectBtn, 0, wx.ALL, 5 )
self.startBtn = wx.Button( self, wx.ID_ANY, u"Start", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.startBtn, 0, wx.ALL, 5 )
self.stopBtn = wx.Button( self, wx.ID_ANY, u"Stop", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.stopBtn, 0, wx.ALL, 5 )
bSizer1.Add( bSizer2, 0, wx.EXPAND, 5 )
bSizer3 = wx.BoxSizer( wx.VERTICAL )
self.m_textCtrl1 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer3.Add( self.m_textCtrl1, 1, wx.ALL|wx.EXPAND, 5 )
self.ser = None
self.settings = {'PORT':'COM3' , 'BAUDRATE':9600}
self.connected = False
bSizer1.Add( bSizer3, 1, wx.EXPAND, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.connectBtn.Bind( wx.EVT_BUTTON, self.connectBtnOnButtonClick )
self.startBtn.Bind( wx.EVT_BUTTON, self.startBtnOnButtonClick )
self.stopBtn.Bind( wx.EVT_BUTTON, self.stopBtnOnButtonClick )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def connectBtnOnButtonClick( self, event ):
# http://stackoverflow.com/questions/11092417/reconnecting-to-device-with-pyserial
try:
if self.ser == None:
self.ser = serial.Serial(self.settings['PORT'],
self.settings['BAUDRATE'],timeout=10)
# print "Successfully connected to port %r." % self.ser.port
self.connectBtn.SetLabel('Disconnect')
self.connected = True
return True
else:
if self.ser.isOpen():
self.ser.close()
self.connected = False
self.connectBtn.SetLabel('Connect')
# print "Disconnected."
return False
else:
self.ser.open()
self.connected = True
self.connectBtn.SetLabel('Disconnect')
# print "Connected."
return True
except serial.SerialException, e:
return False
def startBtnOnButtonClick( self, event ):
while self.connected:
self.connected = True
while True:
if (self.ser.inWaiting() > 0):
data_str = self.ser.read(self.ser.inWaiting())
print(data_str.strip())
time.sleep(0.1)
def stopBtnOnButtonClick( self, event ):
self.connected = False
# self.connected = False
# http://stackoverflow.com/questions/17553543/pyserial-non-blocking-read-loop
if __name__ == "__main__":
app = wx.App(redirect=False)
frame = MyFrame(None)
#app.SetTopWindow(frame)
frame.Show(True)
app.MainLoop()
Thank you.
Ivo
Essentially, I think that your startBtnOnButtonClick is a "long running process" and you will need to call wx.Yield() before or after your sleep.
This will allow your program is check back with the main loop to see if anything else has occurred i.e. you pressed the stop button.
See: https://wiki.wxpython.org/LongRunningTasks
Change startBtnOnButtonClick to remove the double while loop
def startBtnOnButtonClick( self, event ):
while self.connected:
if (self.ser.inWaiting() > 0):
data_str = self.ser.read(self.ser.inWaiting())
print(data_str.strip())
time.sleep(0.1)
wx.Yield()

python just restarts and does not run the program at all

can anyone help me with this? i created a gui using wxformbuilder which generated python code for. then i created a separate code on how it should be working.
this first code is for the gui only.
# -*- coding: utf-8 -*-
###########################################################################
## Python code generated with wxFormBuilder (version Jun 17 2015)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################
import wx
import wx.xrc
###########################################################################
## Class frmQuestions
###########################################################################
class frmQuestions ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 1055,562 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.lblQbox = wx.StaticText( self, wx.ID_ANY, u"Question:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.lblQbox.Wrap( -1 )
self.lblQbox.SetFont( wx.Font( 18, 73, 93, 90, False, "Brush Script MT" ) )
bSizer1.Add( self.lblQbox, 0, wx.ALL|wx.EXPAND, 5 )
self.txtQ = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.txtQ, 1, wx.ALL|wx.EXPAND, 5 )
self.btnNext = wx.Button( self, wx.ID_ANY, u"Next", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnNext.SetFont( wx.Font( 12, 72, 90, 90, False, "Cooper Black" ) )
bSizer1.Add( self.btnNext, 0, wx.ALL|wx.EXPAND, 5 )
self.btnShowResults = wx.Button( self, wx.ID_ANY, u"Show Results", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnShowResults.SetFont( wx.Font( 12, 72, 90, 90, False, "Cooper Black" ) )
bSizer1.Add( self.btnShowResults, 0, wx.ALL|wx.EXPAND, 5 )
self.btnExit = wx.Button( self, wx.ID_ANY, u"Exit", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnExit.SetFont( wx.Font( 12, 72, 90, 90, False, "Cooper Black" ) )
bSizer1.Add( self.btnExit, 0, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.btnNext.Bind( wx.EVT_BUTTON, self.OnNext )
self.btnShowResults.Bind( wx.EVT_BUTTON, self.OnShowResults )
self.btnExit.Bind( wx.EVT_BUTTON, self.OnExit )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def OnNext( self, event ):
event.Skip()
def OnShowResults( self, event ):
event.Skip()
def OnExit( self, event ):
event.Skip()
###########################################################################
## Class frmResults
###########################################################################
class frmResults ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
self.SetForegroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVECAPTION ) )
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
bSizer2 = wx.BoxSizer( wx.VERTICAL )
self.txtResults = wx.StaticText( self, wx.ID_ANY, u"Results", wx.DefaultPosition, wx.DefaultSize, 0 )
self.txtResults.Wrap( -1 )
self.txtResults.SetFont( wx.Font( 12, 72, 90, 90, False, "Cooper Black" ) )
bSizer2.Add( self.txtResults, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
self.txtA = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.txtA, 1, wx.ALL|wx.EXPAND, 5 )
self.txtB = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.txtB, 1, wx.ALL|wx.EXPAND, 5 )
self.txtC = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.txtC, 1, wx.ALL|wx.EXPAND, 5 )
self.txtD = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.txtD, 1, wx.ALL|wx.EXPAND, 5 )
self.btnGoBack = wx.Button( self, wx.ID_ANY, u"Go Back", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnGoBack.SetFont( wx.Font( 12, 72, 90, 90, False, "Cooper Black" ) )
bSizer2.Add( self.btnGoBack, 0, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( bSizer2 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.btnGoBack.Bind( wx.EVT_BUTTON, self.OnGoBack )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def OnGoBack( self, event ):
event.Skip()
then here is the code to be run on rpi:
from noname import *
from wx import *
Q1 = 'Q1'
Q2 = 'Q2'
Q3 = 'Q3'
Q4 = 'Q4'
Q5 = 'Q5'
Q6 = 'Q6'
Q7 = 'Q7'
Q8 = 'Q8'
Q9 = 'Q9'
Q10 = 'Q10'
Q11 = 'Q11'
Q12 = 'Q12'
Q13 = 'Q13'
Q14 = 'Q14'
Q15 = 'Q15'
Q16 = 'Q16'
Q17 = 'Q17'
Q18 = 'Q18'
Q19 = 'Q19'
Q20 = 'Q20'
class Questions(frmQuestions):
x = 0
def __init__(self, parent):
frmQuestions.__init__(self,parent)
self.txtQ.SetLabel('')
def OnNext(self, event):
self.x = self.x + 1
if (self.x==1):
self.txtQ.SetLabel(Q1)
elif (self.x==2):
self.txtQ.SetLabel(Q2)
elif (self.x==3):
self.txtQ.SetLabel(Q3)
elif (self.x==4):
self.txtQ.SetLabel(Q4)
elif (self.x==5):
self.txtQ.SetLabel(Q5)
elif (self.x==6):
self.txtQ.SetLabel(Q6)
elif (self.x==7):
self.txtQ.SetLabel(Q7)
elif (self.x==8):
self.txtQ.SetLabel(Q8)
elif (self.x==9):
self.txtQ.SetLabel(Q9)
elif (self.x==10):
self.txtQ.SetLabel(Q10)
elif (self.x==11):
self.txtQ.SetLabel(Q11)
elif (self.x==12):
self.txtQ.SetLabel(Q12)
elif (self.x==13):
self.txtQ.SetLabel(Q13)
elif (self.x==14):
self.txtQ.SetLabel(Q14)
elif (self.x==15):
self.txtQ.SetLabel(Q15)
elif (self.x==16):
self.txtQ.SetLabel(Q16)
elif (self.x==17):
self.txtQ.SetLabel(Q17)
elif (self.x==18):
self.txtQ.SetLabel(Q18)
elif (self.x==19):
self.txtQ.SetLabel(Q19)
elif (self.x==20):
self.txtQ.SetLabel(Q20)
else:
pass
print self.x
def OnShowResults(self, event):
results.Show()
def OnExit(self, event):
self.Destroy()
class Results(frmResults):
def __init__(self, parent):
frmResults.__init__(self,parent)
def OnGoBack(self, event):
self.txtA.SetLabel('')
self.txtB.SetLabel('')
self.txtC.SetLabel('')
self.txtD.SetLabel('')
self.Hide()
app = wx.App(False)
results = Results(None)
questions = Questions(None)
questions.Show()
app.MainLoop()
everytime i run it on rpi. python shell just always display -------------------------------restart------------------------- and the gui doesnt appear at all. i just wanna know what is the problem with the code.
and also i created the code on windows and i copied both python files on rpi. on windows it works properly. i sincerely thank you for your hep im just a student and a newbie so i can't really point out what is wrong with my code. thanks :)))
Are you running this via ./myscript.py? If so, you need to add the interpreter to the top. The first line should be:
#!/usr/bin/env python
or something similar so that it knows which interpreter to use.
I know this is not the question, but I'm more concerned about your actual program, to be honest. For example, instead of writing multiple consecutive QN = "QN", you can create them all as a dict and update the global variables. For example:
tmp = ["Q{}".format(i+1) for i in range(20)]
globals().update(dict(zip(tmp, tmp)))
That's significantly easier. Or, better yet, you can map numbers to your desired strings in the form of a dict so the entire thing can be rewritten as:
#!/usr/bin/env python
from noname import *
from wx import *
tmp = ["Q{}".format(i+1) for i in range(20)] # Create a list of "Q1"..."Q20"
vars = dict(enumerate(tmp, 1)) # { 1 : "Q1", 2 : "Q2", ... 20 : "Q20" }
class Questions(frmQuestions):
def __init__(self, parent):
self.x = 0 # Made this an instance variable
frmQuestions.__init__(self,parent)
self.txtQ.SetLabel('')
def OnNext(self, event):
self.x = self.x + 1
if self.x in vars:
self.txtQ.SetLabel(vars[self.x]) # significantly simplified
print(self.x)
def OnShowResults(self, event):
results.show()
def OnExit(self, event):
self.Destroy()
class Results(frmResults):
def __init__(self, parent):
frmResults.__init__(self,parent)
def OnGoBack(self, event):
for _ in [self.txtA, self.txtB, self.txtC, self.txtD]:
_.SetLabel('')
self.Hide()
app = wx.App(False)
results = Results(None)
questions = Questions(None)
questions.Show()
app.MainLoop()

WxPython GUI programming - NameError: name "self" is not defined

I'm creating a program to edit a .txt file.
I have 2 files inside a folder:
gui.py & edit_text.py
Here's the code for gui.py
# -*- coding: utf-8 -*-
import wx
import wx.xrc
class Main ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Editor MAVB", pos = wx.DefaultPosition, size = wx.Size( 250,180 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.Size( 250,180 ), wx.Size( 250,180 ) )
layout_sizer = wx.BoxSizer( wx.VERTICAL )
self.text1 = wx.StaticText( self, wx.ID_ANY, u"Escolha o arquivo que será editado:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.text1.Wrap( -1 )
layout_sizer.Add( self.text1, 1, wx.ALL|wx.EXPAND, 5 )
self.filePicker = wx.FilePickerCtrl( self, wx.ID_ANY, wx.EmptyString, u"Selecione um arquivo", u"*.txt", wx.DefaultPosition, wx.Size( 210,-1 ), wx.FLP_DEFAULT_STYLE|wx.FLP_FILE_MUST_EXIST|wx.FLP_SMALL )
layout_sizer.Add( self.filePicker, 0, wx.ALL|wx.EXPAND, 5 )
self.null_text = wx.StaticText( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.null_text.Wrap( -1 )
layout_sizer.Add( self.null_text, 0, wx.ALL, 5 )
self.edit_button = wx.Button( self, wx.ID_ANY, u"Alterar arquivo", wx.DefaultPosition, wx.DefaultSize, 0 )
layout_sizer.Add( self.edit_button, 0, wx.ALL, 5 )
self.status_text = wx.StaticText( self, wx.ID_ANY, u"Aguardando arquivo...", wx.DefaultPosition, wx.DefaultSize, 0 )
self.status_text.Wrap( -1 )
layout_sizer.Add( self.status_text, 0, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( layout_sizer )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.edit_button.Bind( wx.EVT_BUTTON, self.editar_txt )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def editar_txt( self, event ):
event.Skip()
And here is the code for edit_txt.py
# -*- coding: utf-8 -*-
import gui
import wx
class MyFrame(gui.Main):
def __init__(self, parent):
gui.Main.__init__(self, parent)
infile = self.filePicker.GetTextCtrlValue()
outfile_path = infile[:len(infile)-4] + "_editado.txt"
def editar_txt(self, infile):
outfile = []
with open(infile) as f:
for line in f:
line_ed = line.replace("|VENDAS|0|", "|VENDAS|2|")
outfile.append(line_ed)
with open(outfile_path, "w") as g:
for line in outfile:
g.write(line)
f.close()
g.close()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None)
self.SetTopWindow(self.frame)
self.frame.Show(True)
print("\n----------------------------------------\nEditor MAVB - inicializado com sucesso. \n----------------------------------------")
return True
if __name__ == "__main__":
app = MyApp(redirect=False)
app.MainLoop()
When I enter into the program folder and run edit_txt.py, I got the following error:
Error in line
infile = self.filePicker.GetTextCtrlValue()
NameError: name 'self' is not defined
I've created a Main class in gui.py
Imported gui.py script into edit_txt.py
Created a inherited MyFrame class from the gui.Main class
Initialized MyFrame class as soon as I open the program
Then I tried to get the infile path using the command: infile = self.filePicker.GetTextCtrlValue()
Questions:
Why isn't this working?
How can I make it work?
You are trying to access an instance property inherited from gui.Main as a class property. Generally speaking, you are trying to statically access a non-static property.
If you define infile and outfile_path as instance properties for MyFrame, you can then access them with self.Property.
(Please note that this way you need to change references to the editar_txt method where it is referenced, because the argument is no longer necessary.)
Below the modified MyFrame class in edit_txt.py :
class MyFrame(gui.Main):
def __init__(self, parent):
gui.Main.__init__(self, parent)
self.infile = self.filePicker.GetTextCtrlValue()
self.outfile_path = self.infile[:len(self.infile)-4] + "_editado.txt"
def editar_txt(self):
outfile = []
with open(self.infile) as f:
for line in f:
line_ed = line.replace("|VENDAS|0|", "|VENDAS|2|")
outfile.append(line_ed)
with open(self.outfile_path, "w") as g:
for line in outfile:
g.write(line)
f.close()
g.close()
Why isn't it working? Because the following line:
infile = self.filePicker.GetTextCtrlValue()
is outside any function, and is in the class definition. It is trying to execute this line as the class is being defined to create an infile attribute on the class, and as self is not defined at this time, it complains about self not being defined.
How can you make it work? Presumably, you intended that line and the one after it to be in your __init__() method. Indent them accordingly.

How to scroll Panel with GridBagSizer in wxPython

I need to make a Panel scrollable. I've used GridBagSizer
Code:
import wx
class MyFrame( wx.Frame ):
def __init__( self, parent, ID, title ):
wx.Frame.__init__( self, parent, ID, title, wx.DefaultPosition, wx.Size( 400, 300 ) )
self.InitUI()
self.Center()
self.Show()
def InitUI(self):
MPanel = wx.Panel(self)
GridBag = wx.GridBagSizer(2, 2)
CO = ["RED", "BLUE"]
for i in range(10):
X = wx.StaticText(MPanel, size=(50,50), style=wx.ALIGN_CENTER, label="")
X.SetBackgroundColour(CO[i%2])
GridBag.Add(X, pos=(i+1, 1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=1)
GridBag.AddGrowableCol(1)
MPanel.SetSizerAndFit(GridBag)
class MyApp( wx.App ):
def OnInit( self ):
self.fr = MyFrame( None, -1, "K" )
self.fr.Show( True )
self.SetTopWindow( self.fr )
return True
app = MyApp( 0 )
app.MainLoop()
How can I do this?
Try if following solution helps you:
import wx
import wx.lib.scrolledpanel as scrolled
class MyPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent, -1)
self.SetAutoLayout(1)
self.SetupScrolling()
Now Instead of using MPanel=wx.Panel(self), use `MPanel = MyPanel(self) and rest of your code will remain as is.
Below is the modified code:
class MyFrame( wx.Frame ):
def __init__( self, parent, ID, title ):
wx.Frame.__init__( self, parent, ID, title, wx.DefaultPosition, wx.Size( 400, 300 ) )
self.InitUI()
self.Center()
self.Show()
def InitUI(self):
MPanel = MyPanel(self)
GridBag = wx.GridBagSizer(2, 2)
CO = ["RED", "BLUE"]
for i in range(10):
X = wx.StaticText(MPanel, size=(50,50), style=wx.ALIGN_CENTER, label="")
X.SetBackgroundColour(CO[i%2])
GridBag.Add(X, pos=(i+1, 1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=1)
GridBag.AddGrowableCol(1)
MPanel.SetSizerAndFit(GridBag)
class MyApp( wx.App ):
def OnInit( self ):
self.fr = MyFrame( None, -1, "K" )
self.fr.Show( True )
self.SetTopWindow( self.fr )
return True
app = MyApp( 0 )
app.MainLoop()

wxPython hide and show panel

I am creating a Python application that requires a login on start up. I want to have a main panel that will hold my login panel and on successful login the login panel will hide and the main wx.Notebook will show. The following code works, but if in the login panel I re-size the application, after I successfully login and go to the main wx.Notebook the wx.Notebook does not fit the size of the screen. If I resize again while in the main wx.Notebook the main wx.Notebook will fit the window. How do I get the main wx.Notebook to automatically re-size to the window?
Main.py
import wx
import os
from titlePanel import titlePanel
from OneLblOneCB_HorzBoxSizer_Panel import OneLblOneCB_HorzBoxSizer_Panel
from OneLblOneMultiTxt_HorzBoxSizer_Panel import OneLblOneMultiTxt_HorzBoxSizer_Panel
from OneLblOneSingleTxt_HorzBoxSizer_Panel import OneLblOneSingleTxt_HorzBoxSizer_Panel
from OneLblTxtFile_HorzBoxSizer_Panel import OneLblTxtFile_HorzBoxSizer_Panel
from OneBtn_HorzBoxSizer_Panel import OneBtn_HorzBoxSizer_Panel
from LoginPanel import LoginPanel
from ProjectsPanel import ProjectsPanel
from EvDB import EvDB
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title=title, size=(650,725))
# Create Database Tables
self.db = EvDB(self)
self.db.createTbls()
# Setting up the menu.
filemenu= wx.Menu()
ID_LOGIN = wx.NewId()
ID_LOGOUT = wx.NewId()
# wx.ID_ABOUT and wx.ID_EXIT are standard IDs provided by wxWidgets.
menuOpen = filemenu.Append(wx.ID_OPEN, "&Open"," Open and existing file")
menuAbout = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
filemenu.AppendSeparator()
menuLogin = filemenu.Append(ID_LOGIN, 'Login')
menuLogout = filemenu.Append(ID_LOGOUT, 'Logout')
filemenu.AppendSeparator()
menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
# Creating the menubar.
menuBar = wx.MenuBar()
menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content.
# Set events.
self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen )
self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout )
self.Bind(wx.EVT_MENU, self.OnLogin, menuLogin )
self.Bind(wx.EVT_MENU, self.OnLogout, menuLogout )
self.Bind(wx.EVT_MENU, self.OnExit, menuExit )
main = wx.Panel(self)
self.mainLogin = LoginPanel(main,-1,addSpacers=1)
self.mainLogin.Show()
# Create a notebook on the panel
self.nb = wx.Notebook(main)
self.nb.Hide()
# create the page windows as children of the notebook
flowchartPg = wx.Panel(self.nb)
entryPg = wx.ScrolledWindow(self.nb, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style=wx.VSCROLL)
entryPg.SetScrollRate( 5, 5 )
projectsPg = ProjectsPanel(self.nb, -1)
# add the pages to the notebook with the label to show on the tab
self.nb.AddPage(projectsPg, "Projects")
self.nb.AddPage(entryPg, "Entry")
self.nb.AddPage(flowchartPg, "Flowchart")
self.entTitle = titlePanel(entryPg, -1)
self.entDescr = OneLblOneMultiTxt_HorzBoxSizer_Panel(entryPg,-1,
name="entDescr", lbl="Description")
self.srcTypeList = ['None','Website', 'Youtube', 'PDF', 'Book']
self.entSourceType = OneLblOneCB_HorzBoxSizer_Panel(entryPg,-1,
name="entSourceType", lbl="Source Type: ", cbList=self.srcTypeList, startVal='None')
self.entSource = OneLblTxtFile_HorzBoxSizer_Panel(entryPg,-1,
name="entSource", lbl="Source: ")
self.entSource.singleTxt.SetEditable(False)
self.entSource._filename.Disable()
self.entAuthor = OneLblOneSingleTxt_HorzBoxSizer_Panel(entryPg,-1,
name="entAuthor", lbl="Author: ", addSpacers=0)
self.entAuthorCre = OneLblOneMultiTxt_HorzBoxSizer_Panel(entryPg,-1,
name="entAuthorCre", lbl="Author's Credentials: ")
self.asPrjList = ['None','Project1', 'Project2', 'Project3', 'Project4']
self.entAsProject = OneLblOneCB_HorzBoxSizer_Panel(entryPg,-1,
name="asProject", lbl="Assign to Project: ", cbList=self.asPrjList, startVal='None')
self.saveOrEditList = ['New','Ev1', 'Ev2', 'Ev3', 'Ev4']
self.entSaveOrEdit = OneLblOneCB_HorzBoxSizer_Panel(entryPg,-1,
name="saveOrEdit", lbl="New or Edit: ", cbList=self.saveOrEditList, startVal='New')
self.entRemarks = OneLblOneMultiTxt_HorzBoxSizer_Panel(entryPg,-1,
name="sourceRemarks", lbl="Evidence Remarks: ")
self.entRemarks.multiTxt.SetEditable(False)
self.entAddBtn = OneBtn_HorzBoxSizer_Panel(entryPg, -1, name="entAddBtn", btn="Add")
self.entSaveBtn = OneBtn_HorzBoxSizer_Panel(entryPg, -1, name="entSaveBtn", btn="Save")
#self.loginTest = LoginPanel(entryPg, -1,addSpacers=1)
self.entSaveBtn.button.Hide()
# Bindings
self.Bind(wx.EVT_COMBOBOX, self.SourceTypeEvtComboBox, self.entSourceType.cb)
self.Bind(wx.EVT_COMBOBOX, self.AsProjectEvtComboBox, self.entAsProject.cb)
self.Bind(wx.EVT_COMBOBOX, self.SaveOrEditEvtComboBox, self.entSaveOrEdit.cb)
self.Bind(wx.EVT_BUTTON, self.EvtAddBtn, self.entAddBtn.button)
self.Bind(wx.EVT_BUTTON, self.EvtSaveBtn, self.entSaveBtn.button)
self.Bind(wx.EVT_BUTTON, self.EvtLoginBtn, self.mainLogin.loginBtns.LoginBtn)
self.Bind(wx.EVT_BUTTON, self.EvtLogoutBtn, self.mainLogin.loginBtns.LogoutBtn)
# Creating Sizers
mainSizer = wx.BoxSizer(wx.VERTICAL)
entryPgBox = wx.BoxSizer(wx.VERTICAL)
# Adding Panels to BoxSizer entry panel sizer
mainSizer.AddSpacer(10)
mainSizer.Add(self.nb, 1, wx.ALL|wx.EXPAND)
mainSizer.Add(self.mainLogin, 1, wx.ALL|wx.EXPAND)
entryPgBox.AddSpacer(20)
entryPgBox.Add(self.entAsProject, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entSaveOrEdit, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entTitle, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entDescr, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entSourceType, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entSource, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entAuthor, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entAuthorCre, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entRemarks, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
entryPgBox.Add(self.entAddBtn, 0, wx.EXPAND)
entryPgBox.Add(self.entSaveBtn, 0, wx.EXPAND)
entryPgBox.AddSpacer(10)
# Setting Layouts
entryPg.SetAutoLayout(True)
entryPg.SetSizer(entryPgBox)
entryPgBox.Fit(entryPg)
main.SetAutoLayout(True)
main.SetSizer(mainSizer)
mainSizer.Fit(main)
self.Layout()
self.Show()
def OnLogin(self,e):
self.nb.Hide()
self.mainLogin.Show()
self.Layout()
self.mainLogin.Layout()
def OnLogout(self,e):
self.mainLogin.Show()
self.nb.Hide()
self.Layout()
self.mainLogin.Layout()
def EvtLoginBtn(self,e):
self.nb.Show()
self.mainLogin.Hide()
self.Layout()
self.nb.Layout()
LoginPanel.py
class LoginPanel(wx.Panel):
def __init__(self, parent, ID, addSpacers):
wx.Panel.__init__(self, parent, ID)
sizer = wx.BoxSizer(wx.VERTICAL)
self.userNamePnl = OneLblOneSingleTxt_HorzBoxSizer_Panel(self,-1,
name="loginUser", lbl="Username: ", addSpacers=1)
self.passwordPnl = OneLblOneSingleTxt_HorzBoxSizer_Panel(self,-1,
name="loginPass", lbl="Password: ", addSpacers=1)
self.loginBtns = LoginBtnsPanel(self,-1)
if addSpacers == 1:
sizer.AddStretchSpacer()
sizer.Add(self.userNamePnl,0,wx.EXPAND)
sizer.AddSpacer(10)
sizer.Add(self.passwordPnl,0,wx.EXPAND)
sizer.AddSpacer(10)
sizer.Add(self.loginBtns,0,wx.EXPAND)
if addSpacers == 1:
sizer.AddStretchSpacer()
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
Got it! I was trying to redraw the frame with Layout(), but I needed to redraw the BoxSizer with Layout()
I added the following code to the login button:
def EvtLoginBtn(self,e):
self.nb.Show()
self.mainLogin.Hide()
self.mainSizer.Layout()
Call the Layout() method of the Frame and Panel like this
def EvtLoginBtn(self,e):
self.nb.Show()
self.mainLogin.Hide()
self.Layout()
self.nb.Layout()
The last call is probably not needed. Just check the program without it as well. The Layout() method redraws the Frame or Panel or whichever widget it is a method of.
UPDATE
Your code is obviously very big and has several other parts which I do not know. Anyways, here's something that I came up with, along the lines of the code you have provided, to show how you can do this. Hope this helps:
Main.py
import wx
from LoginPanel import LoginPanel
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Something something", pos = wx.DefaultPosition, size = wx.Size( 300,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
BoxSizer0 = wx.BoxSizer( wx.VERTICAL )
# Add login panel
self.login_panel = LoginPanel(self)
BoxSizer0.Add(self.login_panel, 1, wx.EXPAND | wx.ALL, 0)
# Add notebook panel and its pages
self.nb = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
self.nb_subpanel1 = wx.Panel( self.nb, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
self.nb.AddPage( self.nb_subpanel1, u"something", False )
self.nb_subpanel2 = wx.Panel( self.nb, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
self.nb.AddPage( self.nb_subpanel2, u"something else", False )
BoxSizer0.Add( self.nb, 1, wx.EXPAND |wx.ALL, 0 )
# Adds a logout button
self.logout_button = wx.Button( self, wx.ID_ANY, u"Logout", wx.DefaultPosition, wx.DefaultSize, 0 )
BoxSizer0.Add( self.logout_button, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
# Hide nb and logout button
self.nb.Hide()
self.logout_button.Hide()
self.SetSizer( BoxSizer0 )
self.Layout()
self.Centre( wx.BOTH )
self.Show()
# Connect Events
self.logout_button.Bind( wx.EVT_BUTTON, self.on_logout )
# Virtual event handlers, override them in your derived class
def on_logout( self, event ):
self.nb.Hide()
self.logout_button.Hide()
self.login_panel.Show()
self.Layout()
if __name__ == "__main__":
app = wx.App()
MyFrame(None)
app.MainLoop()
LoginPanel.py
import wx
class LoginPanel ( wx.Panel ):
def __init__( self, parent ):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 300,300 ), style = wx.TAB_TRAVERSAL )
BoxSizer01 = wx.BoxSizer( wx.VERTICAL )
self.login_button = wx.Button( self, wx.ID_ANY, u"Login", wx.DefaultPosition, wx.DefaultSize, 0 )
self.login_button.SetDefault()
BoxSizer01.Add( self.login_button, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
self.SetSizer( BoxSizer01 )
self.Layout()
# Connect Events
self.login_button.Bind( wx.EVT_BUTTON, self.on_login )
# Virtual event handlers, overide them in your derived class
def on_login( self, event ):
self.Hide()
self.Parent.nb.Show()
self.Parent.logout_button.Show()
self.Parent.Layout()

Categories