I can not navigate between the panels of my App through the buttons. I followed a lot of tutorials like this one but none solve my problem.
Thank for Help.
####################-----Principal Panel (first Panel)
import wx
from OtherPanel import OtherPanel
class MyPanel(wx.Panel):
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent = parent, size=(600, 500))
self.SetBackgroundColour(wx.Colour(250, 250, 250))
parent.Center()
self.histoPanel = OtherPanel(self)
self.home()
self.panel = wx.Panel(self)
def home(self):
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour(wx.Colour(250, 250, 250))
bS =wx.Button(self, -1,"Go some where ",(200,30), size=(150,150))
self.Bind(wx.EVT_BUTTON, self.Sy, bS)
bOthe = wx.Button(self, -1,"Go to OtherPanel",(400,30),(150,150))
self.Bind(wx.EVT_BUTTON, self.onOpenFrame,bOthe)
def onOpenFrame(self, event):
"""
Opens secondary frame
"""
self.Hide()
self.histoPanel.Show()
def Sy(self, event):
"""
I have another panel (panel 3)
"""
self.Hide()
#self.panel3.Show()
--Second Panel (another Panel)
this panel is displayed when you click on the button of the first panel
import wx
class OtherPanel(wx.Panel):
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent = parent)
self.panel = wx.Panel(self)
self.SetBackgroundColour(wx.Colour(250, 250, 250))
self.Center()
self.homeHist()
self.Show()
def homeHist(self):
bBack = wx.Button(self, -1, "", pos=(20,30), size=(50,50))
self.Bind(wx.EVT_BUTTON, self.onClose, bBack)
def onClose(self, event):
self.Close()
------My Frame---.
here is my Frame/Windows. he must wear all the panels in turn
import wx
from MyPanel import MyPanel
from OtherPanel import OtherPanel
class MyFrame(wx.Frame):
""""""
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, size = (600,500))
self.myPanel = MyPanel(self)
self.otherpanel = OtherPanel(self)
self.otherpanel.Hide()
self.menu()
self.CreateStatusBar(style= wx.BORDER_NONE)
self.SetBackgroundColour("gray")
self.SetStatusText("\tthank")
def menu(self):
menubar = wx.MenuBar()
fileMenu = wx.Menu()
menubar.SetBackgroundColour(wx.Colour(1, 1, 6))
fileMenu.AppendSeparator()
live = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit\tCtrl+Q', '\tlive my app')
fileMenu.Append(live)
self.Bind(wx.EVT_MENU, self.Onexit, live)
menubar.Append(fileMenu, '\t&Menu')
self.SetMenuBar(menubar)
def Onexit(self, event):
self.Close(True)
def Bouton(self, event):
if self.myPanel.IsShown():
self.SetTitle("Panel Two Showing")
self.myPanel.Hide()
self.otherpanel.Show()
else:
self.SetTitle("Panel One Showing")
self.myPanel.Show()
self.otherpanel.Hide()
self.Layout()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
frame.Show()
app.MainLoop()
In your MyPanel.__init__ you are creating an instance of OtherPanel assigned to self.histoPanel as a child of the MyPanel, and then MyPanel's event handlers are hiding itself, which in turn hides its children including the self.histoPanel. You're also creating some panels assigned to self.panel which don't seem to be used for anything.
The way you are doing it in the MyFrame class is much better. It creates both panels and hides one. Then in MyFrame.Bouton it hides one and shows the other, depending on the current state. So what you need to do is get rid of all the extra panels in MyPanel (self.histoPanel and also the various self.panels that are never used for anything) and then you just need to have the button event ask the parent frame to swap the panels instead of trying to do it itself.
Here is an example of what Robin is suggesting in his answer:
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.panel = wx.Panel(self)
self.btn = wx.Button(self.panel, label="Panel 1", size=(250,75))
self.btn.Bind(wx.EVT_BUTTON, self.switch)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn)
self.panel.SetSizer(vbox1)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel)
self.SetSizer(vbox)
self.Show()
def switch(self, event):
self.parent.Swap()
class MyOtherPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.panel = wx.Panel(self)
self.btn = wx.Button(self.panel, label="Panel 2", size=(175,250))
self.btn.Bind(wx.EVT_BUTTON, self.switch)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn)
self.panel.SetSizer(vbox1)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel)
self.SetSizer(vbox)
self.Show()
self.panel.Hide()
def switch(self, event):
self.parent.Swap()
class PanelSwitcher(wx.Frame):
def __init__(self):
super().__init__(None)
vbox = wx.BoxSizer(wx.VERTICAL)
self.panel1 = MyPanel(self)
self.panel2 = MyOtherPanel(self)
vbox.Add(self.panel1)
vbox.Add(self.panel2)
self.SetSizer(vbox)
self.Show()
def Swap(self):
if self.panel1.panel.IsShown():
self.panel1.panel.Hide()
self.panel2.panel.Show()
else:
self.panel2.panel.Hide()
self.panel1.panel.Show()
self.Layout()
if __name__ == "__main__":
app = wx.App()
PanelSwitcher()
app.MainLoop()
Related
I've read other answers here, but they all seem to deal with just closing an app altogether, making sure all processes and frames and such are destroyed in the process. What I want to do is a little different.
My app consists of three frames (StartFrame, ParaFrame, ResultFrame) as well as a custom class for storing and manipulating data. The basics are: StartFrame is just some text and a "start" button. "Start" creates an instance of ParaFrame, hides the StartFrame, and shows the ParaFrame instance. Paraframe has a bunch of widgets for the user to select a file and how to analyze it. When all the fields are entered, an "Analyze" button pops up, which (when clicked) instantiates the custom DataHandler class, sets its parameters according to the user selections, calls a DataHandler method which analyzes the data, hides itself, and instantiates+shows the ResultsFrame. Not surprisingly, the ResultsFrame shows the results of the analysis.
I want to add a "Start Over" control which will destroy everything (all the frames, panels, the DataHandler instance, etc.) and display a fresh StartFrame instance, or otherwise destroy everything except the already-instantiated-but-hidden StartFrame, showing that frame again, but I'm at a loss.
A simplified example follows:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(900,600),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
self.frm2 = ParaFrame(None)
self.Hide()
self.frm2.Show()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(950,800),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
self.resfrm = ResultFrame(self, dhandler.data, dhandler.data2)
self.Hide()
self.resfrm.Show()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="results", size=(1535,935))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm.frm2.Destroy()
frm.Show()
def main():
import wx.lib.mixins.inspection
app = wx.App()
frm = StartFrame(None)
frm.Show()
wx.lib.inspection.InspectionTool().Show(refreshTree=True)
app.MainLoop()
if __name__ == "__main__":
main()
As you can see, in the ResultFrame I have a "Start Over" button bound to a method in which I try to destroy the ParaFrame instance (and thus the DataHandler and ResultFrame instances spawned from it) by using frm.frm2.Destroy(), but get an error:
Traceback (most recent call last):
File "C:\Python\Scripts\stackexchange code.py", line 102, in OnRestart
frm.frm2.Destroy()
NameError: name 'frm' is not defined
If I change the line to just frm2.Destroy(), I get the same error, but stating name 'frm2' is not defined.
What am I doing wrong here, and how can I accomplish my goal? I'm still newish to OOP and quite new to wxPython, so any help is appreciate it. All I want is for that button to destroy everything and display the/an initial StartFrame again. Thank you :)
As long as you create each class without a parent, you can use self.Destroy() after creating the next frame in the chain, without it destroying any children. (Pass any data required as a parameter other than parent)
So your code, looks something like this:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
frm2 = ParaFrame(None)
frm2.Show()
self.Destroy()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
resfrm = ResultFrame(None, dhandler.data, dhandler.data2)
resfrm.Show()
self.Destroy()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="Results", size=(900,600))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm = StartFrame(None)
frm.Show()
self.Destroy()
def main():
app = wx.App()
frm = StartFrame(None)
frm.Show()
app.MainLoop()
if __name__ == "__main__":
main()
I want to open a dialog modeless with Show(). After opening I can click on the parent window so the dialog opened successfully modeless.
The problem I have is that the modeless dialog always stays on top of the parent window. I want the parent to get on top when I click on it.
It doesn't matter wether I give the dialog a parent window or not. I test for the wx.STAY_ON_TOP style which is False for the dialog.
With simple code below (copied and modified from https://www.tutorialspoint.com/wxpython/wx_dialog_class.htm) I'm having the same problem.
How can I get a modeless dialog that can get behind the parent window?
import wx
# -----------------------------------------------------------------------------------
class MyDialog(wx.Dialog):
def __init__(self, parent, title):
super(MyDialog, self).__init__(parent, title=title, size=(250, 150))
panel = wx.Panel(self)
self.btn = wx.Button(panel, wx.ID_OK, label="ok", size=(50, 20), pos=(75, 50))
style = self.GetWindowStyle()
if style & wx.STAY_ON_TOP:
print('STAY_ON_TOP = True')
else:
print('STAY_ON_TOP = False')
# -----------------------------------------------------------------------------------
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title=title, size=(300, 300))
self.InitUI()
def InitUI(self):
panel = wx.Panel(self)
btn1 = wx.Button(panel, label="Modal Dialog", pos=(20, 10))
btn2 = wx.Button(panel, label="Modeless Dialog Parent", pos=(20, 40))
btn3 = wx.Button(panel, label="Modeless Dialog Parentless", pos=(20, 70))
btn1.Bind(wx.EVT_BUTTON, self.OnModal)
btn2.Bind(wx.EVT_BUTTON, self.OnModelessParent)
btn3.Bind(wx.EVT_BUTTON, self.OnModelessParentless)
self.Show(True)
def OnModal(self, event):
MyDialog(self, "Dialog").ShowModal()
def OnModelessParent(self, event):
dlg = MyDialog(self, "Dialog").Show()
def OnModelessParentless(self, event):
dlg = MyDialog(None, "Dialog").Show()
# -----------------------------------------------------------------------------------
ex = wx.App()
Mywin(None, 'Modal / Modeless')
ex.MainLoop()
Adding the style wx.DIALOG_NO_PARENT to your dialog's constructor allows the dialogs to float behind the frame. Ex:
import wx
# -----------------------------------------------------------------------------------
class MyDialog(wx.Dialog):
def __init__(self, parent, title):
super(MyDialog, self).__init__(parent, title=title, size=(250, 150),
style=wx.DEFAULT_DIALOG_STYLE | wx.DIALOG_NO_PARENT)
panel = wx.Panel(self)
self.btn = wx.Button(panel, wx.ID_OK, label="ok", size=(50, 20), pos=(75, 50))
style = self.GetWindowStyle()
if style & wx.STAY_ON_TOP:
print('STAY_ON_TOP = True')
else:
print('STAY_ON_TOP = False')
# -----------------------------------------------------------------------------------
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title=title, size=(300, 300))
self.InitUI()
def InitUI(self):
panel = wx.Panel(self)
btn1 = wx.Button(panel, label="Modal Dialog", pos=(20, 10))
btn2 = wx.Button(panel, label="Modeless Dialog Parent", pos=(20, 40))
btn3 = wx.Button(panel, label="Modeless Dialog Parentless", pos=(20, 70))
btn1.Bind(wx.EVT_BUTTON, self.OnModal)
btn2.Bind(wx.EVT_BUTTON, self.OnModelessParent)
btn3.Bind(wx.EVT_BUTTON, self.OnModelessParentless)
self.Show(True)
def OnModal(self, event):
MyDialog(self, "Dialog").ShowModal()
def OnModelessParent(self, event):
MyDialog(self, "Dialog").Show()
def OnModelessParentless(self, event):
MyDialog(None, "Dialog").Show()
# -----------------------------------------------------------------------------------
ex = wx.App()
Mywin(None, 'Modal / Modeless')
ex.MainLoop()
I removed the variable assignment dlg = on your 2 modeless event handlers because Show() returns True not the dialog instance.
It should also be noted that dialogs aren't automatically destroyed and you must call Destroy() manually to release their memory when you're done with them.
The following code makes a window to behave like a wx.Dialog but it works perfectly only in Windows. In macOS the buttons in the main window are not disabled and in Linux the main window can be maximized and minimized.
How can I have in macOS and Linux the same modal behavior I have in Windows? I know I could disable the buttons manually and I guess there should be a way to handle the minimize and maximize buttons, but perhaps there is an easier way.
import wx
class MyFrame(wx.Frame):
def __init__(self):
title='Multiple consecutive windows (ShowModal)'
super().__init__(None, title=title)
self.WinNum = 5
#### Widgets
self.panel = wx.Panel(self)
self.buttonShow = wx.Button(self.panel, pos=(50, 50), label='ShowModal')
self.buttonTest = wx.Button(self.panel, pos=(50, 100), label='Test')
#### Bind
self.buttonShow.Bind(wx.EVT_BUTTON, self.ShowWindows)
#### Position of the window
self.SetPosition(pt=(50, 50))
def ShowWindows(self, event):
i = 0
while i < self.WinNum:
a = WinModal(i)
a.ShowModal()
i += 1
class WinModal(wx.Frame):
def __init__(self, ThisWinNum):
title = 'This is window number: ' + str(ThisWinNum)
super().__init__(None, title=title)
#### Variables
self.ThisWinNum = ThisWinNum
#### Widgets
self.panel = wx.Panel(self)
self.buttonOk = wx.Button(self.panel, pos=(50, 50), label='Ok')
#### Positions
self.SetPosition(pt=(200, 200))
#### Bind
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Bind(wx.EVT_BUTTON, self.onOk)
def ShowModal(self):
"""
This function is the one giving the wx.FileDialog behavior
"""
self._disabler = wx.WindowDisabler(self)
self.Show()
self.eventLoop = wx.GUIEventLoop()
self.eventLoop.Run()
def OnClose(self, event):
"""
To handle closing the windows because you need to exit the eventLoop
of the modal window.
"""
del self._disabler
self.eventLoop.Exit()
self.Destroy()
def onOk(self, event):
print(self.ThisWinNum)
self.cancel = False
self.OnClose(event)
if __name__ == '__main__':
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()
else:
pass
Probably my question was not correctly formulated. Now I realize that what I wanted to know was how to create a custom dialog window.
This can be done by deriving the custom class from wx.Dialog instead of wx.Frame. The class wx.Dialog gives an empty space that you can fill with widgets just like a normal wx.Frame and also has the ShowModal() method in it. Therefore, you can show your window as a modal window.
import wx
class MainWin(wx.Frame):
def __init__(self):
super().__init__(None, title='My modal window')
####---- Variables
self.frameFvar = None
####---- Widgets
self.panel = wx.Panel(self)
self.buttonF = wx.Button(self.panel, label='Show Normal')
self.buttonM = wx.Button(self.panel, label='Show Modal')
####---- Sizer
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.buttonF, border=20, flag=wx.ALIGN_CENTER|wx.ALL)
self.sizer.Add(self.buttonM, border=20, flag=wx.ALIGN_CENTER|wx.ALL)
self.sizerM = wx.BoxSizer(wx.HORIZONTAL)
self.sizerM.Add(self.sizer, border=20,
flag=wx.EXPAND|wx.ALIGN_CENTER|wx.ALL)
self.panel.SetSizer(self.sizerM)
self.sizerM.Fit(self)
####---- Position
self.SetPosition(pt=(50, 50))
####---- Bind
self.buttonF.Bind(wx.EVT_BUTTON, self.ShowAsNormal)
self.buttonM.Bind(wx.EVT_BUTTON, self.ShowAsModal)
#---
def ShowAsNormal(self, event):
if self.frameFvar == None:
self.frameF = AsFrame(self)
self.frameF.Show()
self.frameFvar = True
else:
self.frameF.Raise()
#---
def ShowAsModal(self, event):
self.frameM = AsDialog(self)
if self.frameM.ShowModal() == wx.ID_OK:
print("Exited by Ok button")
else:
print("Exited by X button")
self.frameM.Destroy()
#---
#---
class AsFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent=parent, title='Shown as a wx.Frame')
####---- Variables
self.parent = parent
####---- Widgets
self.a = MyPanel(self)
####---- Position
self.SetPosition(pt=(50, 200))
####---- Bind
self.Bind(wx.EVT_CLOSE, self.OnClose)
#---
def OnClose(self, event):
self.parent.frameFvar = None
self.Destroy()
#---
#---
class AsDialog(wx.Dialog):
def __init__(self, parent):
super().__init__(parent=parent, title='Shown as a wx.Dialog')
####---- Variables
self.SetEscapeId(12345)
####---- Widgets
self.a = MyPanel(self)
self.buttonOk = wx.Button(self, wx.ID_OK)
####---- Sizers
self.sizerB = wx.StdDialogButtonSizer()
self.sizerB.AddButton(self.buttonOk)
self.sizerB.Realize()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.a, border=10, flag=wx.EXPAND|wx.ALIGN_LEFT|wx.ALL)
self.sizer.Add(self.sizerB, border=10,
flag=wx.EXPAND|wx.ALIGN_RIGHT|wx.ALL)
self.SetSizer(self.sizer)
####---- Position
self.SetPosition(pt=(550, 200))
#---
#---
class MyPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent=parent)
####---- Variables
self.parent = parent
####---- Widgets
label = ("The same window shown as a wx.Frame or a wx.Dialog")
self.text = wx.StaticText(self, label=label, pos=(10, 10))
#---
#---
if __name__ == '__main__':
app = wx.App()
frameM = MainWin()
frameM.Show()
app.MainLoop()
I want the main frame refresh to update the label When I click the "done" button on MyDialog, But now it doesn't work.
Does there anything wrong? Thanks.
This is the code:
MyDialog: the child dialog where there is a button on it to update the label of the main frame
MainFrame: the main Frame, there is a button on it to start my dialog
# -*- coding: utf-8 -*-
import wx
#Dialog
class MyDialog(wx.Dialog):
"""setting MyDialog."""
def __init__(self):
self.dlg_main = wx.Dialog.__init__(self, None, -1, title="setting", size=(300, 300))
self.btn_ok = wx.Button(self, label="done", pos=(30, 30), size=(50, 26))
self.Bind(wx.EVT_BUTTON, self.__OnButtonClick_save, self.btn_ok,)
def __OnButtonClick_save(self, event):
self.Destroy()
main = MainFrame()
**main.set_label_name('test')**
main.Destroy()
def start_dialog():
my_dialog = MyDialog()
my_dialog.ShowModal()
my_dialog.Destroy()
#Main Frame
class MainFrame(wx.Frame):
def __init__(self):
self.main_frame = wx.Frame.__init__(self, None, -1, title='simple', size=(400, 400))
self.Centre()
self.label_name = wx.StaticText(self, label="Hello,everyone", pos=(30, 30))
self.btn_set = wx.Button(self, label="set", pos=(30, 60))
self.Bind(wx.EVT_BUTTON, self.on_button_click, self.btn_set)
def set_label_name(self, str):
print(str)
self.label_name.SetLabel('hello, Boys')
def on_button_click(self, event):
start_dialog()
def show_main():
main = wx.App()
main_win = MainFrame()
main_win.Show()
main.MainLoop()
if __name__ == '__main__':
show_main()
I have got the method, thanks all!
The point is how to call the parent method, so , use self.parent.xxx to fix the problem.
The code like this:
# -*- coding: utf-8 -*-
import wx
#Dialog
class MyDialog(wx.Dialog):
"""setting MyDialog."""
def __init__(self, parent, title):
super(MyDialog, self).__init__(parent, title=title, size=(300, 300))
self.parent = parent
panel = wx.Panel(self)
btn_ok = wx.Button(panel, label="done", pos=(30, 30), size=(50, 26))
btn_ok.Bind(wx.EVT_BUTTON, self.__OnButtonClick_save)
def __OnButtonClick_save(self, event):
#THis is the different
self.parent.set_label_name('test')
self.Destroy()
def start_dialog():
my_dialog = MyDialog()
my_dialog.ShowModal()
my_dialog.Destroy()
#Main Frame
class MainFrame(wx.Frame):
def __init__(self):
self.main_frame = wx.Frame.__init__(self, None, -1, title='simple', size=(400, 400))
self.init_ui()
def init_ui(self):
self.label_name = wx.StaticText(self, label="Hello,everyone", pos=(30, 30))
btn_set = wx.Button(self, label="set", pos=(30, 60))
btn_set.Bind(wx.EVT_BUTTON, self.on_button_click)
self.Centre()
def set_label_name(self, str):
self.label_name.SetLabel('hello, Boys')
def on_button_click(self, event):
my_dialog = MyDialog(self, "setting")
my_dialog.ShowModal()
my_dialog.Destroy()
def show_main():
main = wx.App()
main_win = MainFrame()
main_win.Show()
main.MainLoop()
if __name__ == '__main__':
show_main()
Thanks for the idea in this answer Wxpython show dialog on main frame startup
I can't get the listctrl widget to expand.
example picture: http://img109.imageshack.us/img109/3171/22488459.jpg
This code simply creates a dialog box and creates a CheckListCtrlMixin which is a ListCtrl with check boxes.
import wx
import re, os, sys
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
CheckListCtrlMixin.__init__(self)
ListCtrlAutoWidthMixin.__init__(self)
class QueueDialog(wx.Dialog):
def __init__(self, parent, title):
super(QueueDialog, self).__init__(parent=parent,
title=title, size=(400, 500))
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
sb = wx.StaticBox(panel, label='Queue')
sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
panel2 = wx.Panel(panel)
hbox3 = wx.BoxSizer(wx.VERTICAL)
hbox3.Add(panel2, proportion=1, flag=wx.EXPAND|wx.ALL)
listB = CheckListCtrl(panel2)
listB.InsertColumn(0, "Test", width=100)
listB.InsertColumn(1, "Status", wx.LIST_FORMAT_RIGHT)
dalist = ["heh", "ha", "hello"]
for name in dalist[0:3]:
index = listB.InsertStringItem(sys.maxint, name[0:-1])
sbs.Add(hbox3, proportion=1,flag=wx.EXPAND|wx.ALL)
panel.SetSizer(sbs)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
okButton = wx.Button(self, label='OK')
closeButton = wx.Button(self, label='Cancel')
hbox2.Add(okButton)
hbox2.Add(closeButton, flag=wx.LEFT, border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(panel, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
vbox.Add(hbox2, flag= wx.ALIGN_CENTER|wx.BOTTOM, border=10)
self.SetSizer(vbox)
def OnClose(self, e):
self.Destroy()
class window(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 400))
e = QueueDialog(None, title='Queue')
e.ShowModal()
e.Destroy()
self.Centre()
self.Show(True)
app = wx.App(0)
window(None, -1, 'e')
app.MainLoop()
I don't know why you have the second panel, but it's really not needed and makes things more complex. Here's one version that works on my machine:
import wx
import re, os, sys
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
CheckListCtrlMixin.__init__(self)
ListCtrlAutoWidthMixin.__init__(self)
class QueueDialog(wx.Dialog):
def __init__(self, parent, title):
super(QueueDialog, self).__init__(parent=parent,
title=title, size=(400, 500))
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
sb = wx.StaticBox(panel, label='Queue')
sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
hbox3 = wx.BoxSizer(wx.VERTICAL)
listB = CheckListCtrl(panel)
listB.InsertColumn(0, "Test", width=100)
listB.InsertColumn(1, "Status", wx.LIST_FORMAT_RIGHT)
hbox3.Add(listB, 1, wx.EXPAND)
dalist = ["heh", "ha", "hello"]
for name in dalist[0:3]:
index = listB.InsertStringItem(sys.maxint, name[0:-1])
sbs.Add(hbox3, proportion=1,flag=wx.EXPAND|wx.ALL)
panel.SetSizer(sbs)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
okButton = wx.Button(self, label='OK')
closeButton = wx.Button(self, label='Cancel')
hbox2.Add(okButton)
hbox2.Add(closeButton, flag=wx.LEFT, border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(panel, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
vbox.Add(hbox2, flag= wx.ALIGN_CENTER|wx.BOTTOM, border=10)
self.SetSizer(vbox)
def OnClose(self, e):
self.Destroy()
class window(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 400))
e = QueueDialog(None, title='Queue')
e.ShowModal()
e.Destroy()
self.Centre()
self.Show(True)
app = wx.App(0)
window(None, -1, 'e')
app.MainLoop()