wx Python subclass Dialog - python

I have a source file containing the following:
class Dialog1 ( wx.Dialog ):
def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Hello", pos = wx.DefaultPosition, size = wx.Size( 342,253 ), style = wx.DEFAULT_DIALOG_STYLE )
Im trying to instantiate this in another source file like so:
dlg = Dialog1(wx.Dialog).__init__(self, None)
However, I get the following error:
Traceback (most recent call last):
File "scripts\motors\motors.py", line 281, in onListOption
dlg = Dialog1(wx.Dialog).__init__(self, None)
File "...",
line 21, in __init__
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Hello", pos = wx.DefaultPosition, size = wx.Size( 342,253 ), style = wx.DEFAULT_DIALOG_STYLE )
File "c:\Python27\lib\site-packages\wx-3.0-msw\wx\_windows.py", line 734, in __init__
_windows_.Dialog_swiginit(self,_windows_.new_Dialog(*args, **kwargs))
TypeError: in method 'new_Dialog', expected argument 1 of type 'wxWindow *'
Any idea why this is happening? I have tried passing wx.Window to the Dialog init but it doesnt make a difference. Can't someon explain why this is happening?

dlg = Dialog1(parent_window)
is the way to go. Where parent_window will be the parent of the dialog. See classes in Python.
Quoting from the link:
When a class defines an init() method, class instantiation
automatically invokes init() for the newly-created class instance.
Here is a working minimal code snippet:
import wx
class Dialog1 ( wx.Dialog ):
def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Hello",
pos = wx.DefaultPosition, size = wx.Size( 342,253 ),
style = wx.DEFAULT_DIALOG_STYLE )
app = wx.App()
dlg = Dialog1(None)
dlg.Show()
app.MainLoop()

Related

Windows WxPython open excel file that's already open

I'm trying to read data from an excel file in Windows, but I'd rather not have to close the excel file to do this.
However, when I try to select an excel file that I have open, I get the warning
This file is in use. Enter a new name or close the file that's in use by another program.
and when I try to open it anyway with pylightxl, I get the error
PermissionError: [Errno 13] Permission denied: 'example.xlsx'
Obviously if I close the open file, it works fine. But why should I? I've saved the excel file (which should write the changes to disk) and I want only to read the data with Python.
Here's my test code:
import wx
import wx.xrc
import pylightxl as xl
def print_sheet_names(file):
db = xl.readxl(file)
for name in db.ws_names:
print(name)
class MyFrame1 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 261,202 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.m_filePicker1 = wx.FilePickerCtrl( self, wx.ID_ANY, wx.EmptyString, u"Select a file", u"*.xlsx", wx.DefaultPosition, wx.DefaultSize, wx.FLP_OPEN )
bSizer1.Add( self.m_filePicker1, 0, wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.m_filePicker1.Bind( wx.EVT_FILEPICKER_CHANGED, self.open_file )
def __del__( self ):
pass
def open_file( self, event ):
file = self.m_filePicker1.GetPath()
print_sheet_names(file)
#print_sheet_names("example.xlsx")
app = wx.App(False)
frame = MyFrame1(None)
frame.Show(True)
app.MainLoop()

WxPython import widgets from other classes

I'm a beginner in WxPython and I've tried experimenting splitting up the code to make it organized and look neater. I've tried it with simple code but it doesn't work. Can anyone please give me a hand?
The code I've tried:
import wx
class text_ctrl ( wx.Panel ):
def __init ( self, parent ):
wx.Panel.__init__ ( self, parent = parent )
text = wx.TextCtrl ( self, pos = ( 100, 100 ) )
class Window ( wx.Frame ):
def __init__ ( self ):
super().__init__ ( parent = None, title = "Learn - Tab TextBox" )
panel = wx.Panel()
text_ctrl ( self )
self.Show()
if __name__ == "__main__":
app = wx.App()
window = Window()
app.MainLoop()
Problem: Textbox doesn't show up ( which is supposed to be the main point ).
For want of a nail the kingdom was lost
You are missing a __
Without the init, nothing occurs when you call text_ctrl
import wx
class text_ctrl ( wx.Panel ):
#def __init ( self, parent ):
def __init__ ( self, parent ):
wx.Panel.__init__ ( self, parent = parent )
text = wx.TextCtrl ( self, pos = ( 100, 100 ) )
class Window ( wx.Frame ):
def __init__ ( self ):
super().__init__ ( parent = None, title = "Learn - Tab TextBox" )
# panel = wx.Panel()
text_ctrl ( self )
self.Show()
if __name__ == "__main__":
app = wx.App()
window = Window()
app.MainLoop()

Code Layout guide for multiple frames in wxpython

EDITED ~ Now with code.
I’m new to coding, and struggling getting variables input into ‘frameA’ output into ‘frameB’. My question is, how should the layout of the code be written so that a variable entered into FrameA is usable, (and refreshed on user input - either on a button click or deselecting textctrl etc-) in frameB?
I’m using wxpython, and using Wx builder as a guide, but writing the actual UI code used myself to help understand what’s going on underneath. I’ve tried class -> def -> frame UI and the frames are organised as I want them, show and hide as I want and the variables I want are printable on entry/button clicks etc within that frame, but are not accessible from outside of that frame, even though I am returning the variables needed.
In this example I want to take what is written in frameA's textctrl, and save it as a variable accessible (and updated) to other classes, in this case FrameB.
import wx
var = "This Should change to whatever is typed in FrameA"
class FrameA ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = (0,0), size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
self.INPUT = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.INPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.INPUT.Bind( wx.EVT_TEXT, self.InputUpdate)
def InputUpdate(self, Evt):
var = self.INPUT.GetValue()
#print (var)
return var
class FrameB ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = (100,100), size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
self.OUTPUT = wx.StaticText( self, wx.ID_ANY, var, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.OUTPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
self.SetSizer( bSizer2 )
if __name__ == '__main__':
app = wx.App()
frmA = FrameA(None)
frmB = FrameB(None)
frmA.Centre()
frmB.Centre()
frmA.Show()
frmB.Show()
app.MainLoop()
As I’m still new I am at the point where I can understand each single line of code, but the larger organisation is still getting messy for me.
My understanding is that the code in its state above the edited 'var' can be accessed from within frameA only, and 'return var' might(?) update the 'global' var, but is not being refreshed into frameB. What am I missing? I've been trying to avoid using global variables as I've heard they're a bad habit to get into this early on...
Thanks, Sundown
If you want the value of var to be accessible to all classes then you need to add the line global var to the method InputUpdate() in Class FrameA before assigning the new value to var.
However, this will make var accessible to all classes in this module, only. If you split the code into two files, then you will have two modules and var will be accessible only in the module that defines it, unless you also import the module defining var in the other module.
Code with some relevant comments:
import wx
var = "This Should change to whatever is typed in FrameA"
class FrameA ( wx.Frame ):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=(0,0), size=(500,300), style=wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.INPUT = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
bSizer1.Add(self.INPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.SetSizer(bSizer1)
self.INPUT.Bind(wx.EVT_TEXT, self.InputUpdate)
def InputUpdate(self, Evt):
#### You need to add the following line before assigning the new value to
#### var in order to modify the global var variable and not the local
#### var variable
global var
var = self.INPUT.GetValue()
#print (var)
#### The try/except block is placed to avoid having an error if the text
#### in frameA changes but frameB does not exist anymore. The code inside
#### the try statement changes the text in frameB in real time.
try:
frmB.OUTPUT.SetLabel(var)
except Exception:
pass
class FrameB ( wx.Frame ):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=(100,100), size=(500,300), style=wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
bSizer2 = wx.BoxSizer(wx.VERTICAL)
self.OUTPUT = wx.StaticText(self, wx.ID_ANY, var, wx.DefaultPosition, wx.DefaultSize, 0)
bSizer2.Add(self.OUTPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
#### Button to check the value of the global var variable and make sure
#### that the code in InputUpdate actually changes the value of the global
#### variable var
self.button = wx.Button(self, wx.ID_ANY, label='Var Value')
bSizer2.Add(self.button, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.SetSizer(bSizer2)
self.button.Bind(wx.EVT_BUTTON, self.varValue)
def varValue(self, event):
#### Print the value of the global variable var
print(var)
if __name__ == '__main__':
app = wx.App()
frmA = FrameA(None)
frmB = FrameB(None)
frmA.Centre()
frmB.Centre()
frmA.Show()
frmB.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.

wxpython - One Frame, Multiple Panels, Modularized Code

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

Categories