I'm using wxpython to create a GUI.
The idea is that whenever I select a row, something will happen on notebook1 and notebook 2, and different tabs will appear with different related information.
However, when I bind an event when selecting a row, weird beird black squares appear on the tab titles. What's wrong?
import wx
import threading
from time import sleep
class VAR():
def __init__(self):
self.result_row = ''
var = VAR()
class TabOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the first tab", (20, 20))
class TabTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the second tab", (20, 20))
class GUI(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(1000, 1000), style=wx.DEFAULT_FRAME_STYLE &
~wx.MAXIMIZE_BOX ^ wx.RESIZE_BORDER, pos=(100, 0))
self.panel = wx.Panel(self)
self.hsizer = wx.BoxSizer(wx.VERTICAL)
first_panel = wx.Panel(self.panel, size=(1000, 420))
self.hsizer.Add(first_panel, 1)
self.second_panel = wx.Panel(self.panel, size=(1000, 600))
self.notebook1 = wx.Notebook(self.second_panel, size=(1000, 230))
self.notebook2 = wx.Notebook(self.second_panel, size=(1000, 400))
self.hsizer.Add(self.second_panel, 1)
self.second_panel_sizer = wx.BoxSizer(wx.VERTICAL)
self.second_panel_sizer.Add(self.notebook1, 1, wx.EXPAND)
self.second_panel_sizer.Add(self.notebook2, 2, wx.EXPAND)
self.second_panel.SetSizerAndFit(self.second_panel_sizer)
self.panel.SetSizerAndFit(self.hsizer)
var.result_row = wx.ListCtrl(
first_panel, -1, style=wx.LC_REPORT, size=(980, 245), pos=(0, 175))
var.result_row.InsertColumn(0, "No.")
var.result_row.InsertColumn(1, "2 ")
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.SelectRow, var.result_row)
def SelectRow(self, event):
while (self.notebook1.GetPageCount()):
self.notebook1.DeletePage(0)
while (self.notebook2.GetPageCount()):
self.notebook2.DeletePage(0)
tab1 = TabOne(self.notebook1)
self.notebook1.AddPage(tab1, "Tab 1")
sizer = wx.BoxSizer()
sizer.Add(self.notebook1, 1, wx.EXPAND)
self.second_panel.SetSizer(sizer)
tab2 = TabTwo(self.notebook2)
self.notebook2.AddPage(tab2, "Tab 2")
sizer = wx.BoxSizer()
sizer.Add(self.notebook2, 1, wx.EXPAND)
self.second_panel.SetSizer(sizer)
def InfiniteProcess():
for i in range(100):
sleep(0.1)
var.result_row.Append(str(i))
finish = False
a = threading.Thread(target=InfiniteProcess)
a.setDaemon(1)
a.start()
app = wx.App()
frame = GUI(None, -1, "a")
frame.Show()
app.MainLoop()
sample
Related
I have two BoxSizers, the first one
sizer = wx.BoxSizer (wx.VERTICAL)
sizer.Add (self.grid2, 1, wx.EXPAND)
panel2.SetSizer (sizer)
and another vertical BoxSizers, to the left of the button grid, both BoxSizers interfere.
vbox1 = wx.FlexGridSizer (rows = 1, cols = 3, hgap = 5, vgap = 5)
buttonsBox1 = wx.BoxSizer (wx.VERTICAL)
buttonsBox1.Add (self.buttonoborved)
vbox1.Add (buttonsBox1)
vbox1.Add (self.grid2)
vbox1.Add (midPan1, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)
panel2.SetSizer (vbox1)
An error occurs - Adding a window already in a sizer, detach it first!
How can they be called at the same time.
Edit:
That are two BoxSizer, one in other, but how can be put buttons in there.
import wx
import wx.grid
from wx.lib.scrolledpanel import ScrolledPanel
class TestPanel(ScrolledPanel):
def __init__(self, parent):
ScrolledPanel.__init__(self, parent, wx.ID_ANY, size=(640, 480))
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self._create_table(), 1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(self.sizer)
self.SetupScrolling()
self.SetAutoLayout(1)
def _create_table(self):
_table = wx.grid.Grid(self, -1)
_table.CreateGrid(0, 2)
for i in range(1723): # Work normally If I use 1722 rows
_table.AppendRows()
_table.SetCellValue(i, 0, str(i))
return _table
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
title="Scroll table", size=(640, 480))
self.fSizer = wx.BoxSizer(wx.VERTICAL)
self.fSizer.Add(TestPanel(self), 1, wx.EXPAND)
self.SetSizer(self.fSizer)
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = TestFrame()
app.MainLoop()
It depends where you want to place the buttons but let's assume they should be at the bottom.
import wx
import wx.grid
from wx.lib.scrolledpanel import ScrolledPanel
class TestPanel(ScrolledPanel):
def __init__(self, parent):
ScrolledPanel.__init__(self, parent, wx.ID_ANY, size=(640, 480))
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self._create_table(), 1, wx.EXPAND | wx.ALL, 5)
self.b1 = wx.Button(self, -1, "Button 1")
self.b2 = wx.Button(self, -1, "Button 2")
self.b3 = wx.Button(self, -1, "Button 3")
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
button_sizer.Add(self.b1)
button_sizer.Add(self.b2)
button_sizer.Add(self.b3)
self.sizer.Add(button_sizer)
self.SetSizer(self.sizer)
self.SetupScrolling()
self.SetAutoLayout(1)
def _create_table(self):
_table = wx.grid.Grid(self, -1)
_table.CreateGrid(0, 2)
for i in range(1723): # Work normally If I use 1722 rows
_table.AppendRows()
_table.SetCellValue(i, 0, str(i))
return _table
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
title="Scroll table", size=(640, 480))
self.fSizer = wx.BoxSizer(wx.VERTICAL)
self.fSizer.Add(TestPanel(self), 1, wx.EXPAND)
self.SetSizer(self.fSizer)
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = TestFrame()
app.MainLoop()
I want to recreate a grid. For example: old grid is 4x4, I want change it to 5x5.
Here is my code:
import wx
import wx.xrc
import wx.grid
class MyFrame2(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)
bSizer4 = wx.BoxSizer(wx.VERTICAL)
self.m_grid2 = wx.grid.Grid(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
# Grid
self.m_grid2.CreateGrid(4, 4)
bSizer4.Add(self.m_grid2, 0, wx.ALL, 5)
self.m_button3 = wx.Button(self, wx.ID_ANY, u"MyButton", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer4.Add(self.m_button3, 0, wx.ALL, 5)
self.m_button3.Bind(wx.EVT_BUTTON, self.OnClick)
self.SetSizer(bSizer4)
self.Layout()
def OnClick(self, event):
self.m_grid2.CreateGrid(5, 5)
self.Layout()
app = wx.App()
frame = MyFrame2(None)
frame.Show(True)
app.MainLoop()
It raise an error when I run that:
File "C:\Python27\lib\site-packages\wx-3.0-msw\wx\grid.py", line 1221, in CreateGrid
return _grid.Grid_CreateGrid(*args, **kwargs)
wx._core.PyAssertionError: C++ assertion "!m_created" failed at ..\..\src\generic\grid.cpp(2325) in wxGrid::CreateGrid(): wxGrid::CreateGrid or wxGrid::SetTable called more than once
It seems I can't recreate this grid again. How can do this job?
If you don't want to Append the rows and columns, then you'll just have to recreate the grid itself. Here's a fairly simple demo that demonstrates how to do that:
import wx
import wx.grid as gridlib
########################################################################
class MyGrid(gridlib.Grid):
#----------------------------------------------------------------------
def __init__(self, parent, rows, cols):
gridlib.Grid.__init__(self, parent)
self.CreateGrid(rows, cols)
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.grid_created = False
row_sizer = wx.BoxSizer(wx.HORIZONTAL)
col_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
rows_lbl = wx.StaticText(self, label="Rows", size=(30, -1))
row_sizer.Add(rows_lbl, 0, wx.ALL|wx.CENTER, 5)
self.rows = wx.TextCtrl(self)
row_sizer.Add(self.rows, 0, wx.ALL|wx.EXPAND, 5)
cols_lbl = wx.StaticText(self, label="Cols", size=(30, -1))
col_sizer.Add(cols_lbl, 0, wx.ALL|wx.CENTER, 5)
self.cols = wx.TextCtrl(self)
col_sizer.Add(self.cols, 0, wx.ALL|wx.EXPAND, 5)
grid_btn = wx.Button(self, label="Create Grid")
grid_btn.Bind(wx.EVT_BUTTON, self.create_grid)
self.main_sizer.Add(row_sizer, 0, wx.EXPAND)
self.main_sizer.Add(col_sizer, 0, wx.EXPAND)
self.main_sizer.Add(grid_btn, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(self.main_sizer)
#----------------------------------------------------------------------
def create_grid(self, event):
""""""
rows = int( self.rows.GetValue() )
cols = int( self.cols.GetValue() )
if self.grid_created:
for child in self.main_sizer.GetChildren():
widget = child.GetWindow()
if isinstance(widget, gridlib.Grid):
self.main_sizer.Remove(widget)
grid = MyGrid(self, rows, cols)
self.main_sizer.Add(grid, 0, wx.ALL, 5)
self.grid_created = True
self.main_sizer.Layout()
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="grids", size=(800, 600))
panel = MyPanel(self)
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
You may only call the CreateGrid function once. if you want to change the size, you need to use the functions AppendCols, AppendRows, DeleteCols or DeleteRows.
def OnClick(self, event):
self.m_grid2.AppendCols(1)
self.m_grid2.AppendRows(1)
self.Layout()
Lokla
I want to ask is it possible to add wx.Panel with event button in wxpython? There are plenty examples how to switch panels Hide first one and show second, but they are useless for me. I want to create panel with add button. For example I have panel something like this
import wx
import wx.grid as grid
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent = parent)
class SecondPanel(wx.Panel):
def __init__(self, parent,a,b):
wx.Panel.__init__(self, parent=parent)
MyGrid=grid.Grid(self)
MyGrid.CreateGrid(a, b)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(MyGrid, 0, wx.EXPAND)
self.SetSizer(sizer)
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="test",
size=(800,600))
self.splitter = wx.SplitterWindow(self)
self.panelOne = MainPanel(self.splitter)
self.panelTwo = SecondPanel(self.splitter, 1, 1)
txtOne = wx.StaticText(self.panelOne, -1, label = "piradoba", pos = (20,10))
self.txtTwo = wx.StaticText(self.panelOne, -1, label = "", pos = (40,80))
self.txtPlace = wx.TextCtrl(self.panelOne, pos = (20,30))
button = wx.Button(self.panelOne, label = "search", pos = (40,100))
button.Bind(wx.EVT_BUTTON, self.Onbutton)
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.splitter.SetMinimumPaneSize(20)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.splitter, 1, wx.EXPAND)
self.SetSizer(sizer)
def Onbutton(self, event):
var=self.txtPlace.GetValue()
if len(var) == 9 or len(var) == 11:
???????????????????????????????????????????????
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
for example now I want to add new panel with this event what can I do? and I want to create this panel with event.
I don't know if it is what you need but in this example you have:
panel with button and event
button call function in mainframe
mainframe add next panel (with grid) to boxsizer
Tested on Linux Mint + Python 2.7.4
import wx
import wx.grid as grid
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent = parent)
self.txtOne = wx.StaticText(self, -1, label = "piradoba", pos = (20,10))
self.txtPlace = wx.TextCtrl(self, pos = (20,30))
self.txtTwo = wx.StaticText(self, -1, label = "", pos = (20,40))
button = wx.Button(self, label = "search", pos = (20,70))
button.Bind(wx.EVT_BUTTON, self.onButton)
def onButton(self, event):
var=self.txtPlace.GetValue()
if len(var) == 9 or len(var) == 11:
print "???"
# MainPanel->SplitterWindow->MainFrame ( 2x GetParent() )
self.GetParent().GetParent().AddPanel()
class SecondPanel(wx.Panel):
def __init__(self, parent,a,b):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
MyGrid=grid.Grid(self)
MyGrid.CreateGrid(a, b)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(MyGrid, 0, wx.EXPAND)
self.SetSizer(sizer)
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="test", size=(800,600))
self.splitter = wx.SplitterWindow(self)
self.panelOne = MainPanel(self.splitter)
self.panelTwo = SecondPanel(self.splitter, 1, 1)
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.splitter.SetMinimumPaneSize(20)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.splitter, 2, wx.EXPAND)
self.SetSizer(self.sizer)
def AddPanel(self):
self.newPanel = SecondPanel(self, 1, 1)
self.sizer.Add(self.newPanel, 1, wx.EXPAND)
self.sizer.Layout()
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
im having a little issue with NoteBook switching. When I switch notebook tabs, I will need to resize to make the wigdets display properly. I tried using self.Refresh() but that does not seem to do anything. If you have trouble understanding me, please run the following code, then switch tabs and resize, you will notice that there is problems, displaying things correctly. I do not know if this is a problem with wxPython but I think it is with my code.
IMAGE_NAME = []
IMAGE_DATA = []
IMAGEMORE_NAME=[]
IMAGEMORE_DATA=[]
import sys
import wx
def deletepic(self):
try:
self.parent.bitmap.Destroy()
except:
print sys.exc_info()
def sendnewpic(self):
if self.parent.bitmap: deletepic(self)
if IMAGE_DATA[self.image_listsel] != '':
try:
print IMAGE_DATA[self.image_listsel]
bmp = wx.Image(IMAGE_DATA[self.image_listsel], wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.parent.scroll_img.SetScrollbars(1, 1, bmp.GetWidth(), bmp.GetHeight())
self.parent.bitmap = wx.StaticBitmap(self.parent.scroll_img, -1, bmp, (0, 0))
self.parent.Refresh()
except:
pass
def areachange(self, pg):
print pg
try:
if IMAGE_DATA[self.image_listsel] == '':
deletepic(self)
except:
pass
if pg == "Regular Pictures":
self.images_area.Show()
self.scroll_img.Show()
self.btnTwo.Show()
else:
self.images_area.Hide()
self.scroll_img.Hide()
self.btnTwo.Hide()
if pg == "More Pictures":
self.images_area.Show()
self.scroll_img.Show()
self.imageboxersiz.Show()
else:
self.imageboxersiz.Hide()
self.Refresh()
class imageTab(wx.Panel):
def __init__(self, parent, grandparent):
wx.Panel.__init__(self, parent)
self.parent = grandparent
self.image_listsel = 0
self.listBox = wx.ListBox(self, size=(200, -1), choices=IMAGE_NAME, style=wx.LB_SINGLE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
self.sizerMain = wx.BoxSizer()
self.listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.reName)
self.listBox.Bind(wx.EVT_LISTBOX, self.imagesel)
btn = wx.Button(self, label="Create New",size=(200, 40))
btnTwo = wx.Button(self, label="Test 2",size=(200, 40))
btn.Bind(wx.EVT_BUTTON, self.newAddImage)
self.sizer.Add(self.listBox, proportion=1, flag=wx.TOP | wx.EXPAND | wx.LEFT, border=5)
btnSizer.Add(btn, 0, wx.ALL, 5)
btnSizer.Add(btnTwo, 0, wx.ALL, 5)
self.sizer.Add(btnSizer)
self.sizerMain.Add(self.sizer, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=0)
self.SetSizer(self.sizerMain)
def imagesel(self, evt):
self.image_listsel = self.listBox.GetSelection()
sendnewpic(self)
def newAddImage(self, evt):
IMAGE_NAME.append('hi')
IMAGE_DATA.append('')
self.listBox.Set(IMAGE_NAME)
self.listBox.SetSelection(len(IMAGE_NAME)-1)
self.imagesel(None) #making it a selected image, globally
def reName(self,parent):
sel = self.listBox.GetSelection()
text = self.listBox.GetString(sel)
renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
if renamed != '':
IMAGE_NAME.pop(sel)
IMAGE_NAME.insert(sel,renamed)
self.listBox.Set(IMAGE_NAME)
self.listBox.SetSelection(sel)
class objectTab(wx.Panel):
def __init__(self, parent, grandparent):
wx.Panel.__init__(self, parent)
self.parent = grandparent
self.image_listsel = 0
self.listBox = wx.ListBox(self, size=(200, -1), choices=IMAGEMORE_NAME, style=wx.LB_SINGLE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
self.sizerMain = wx.BoxSizer()
self.listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.reName)
self.listBox.Bind(wx.EVT_LISTBOX, self.imagesel)
btn = wx.Button(self, label="Create New",size=(200, 40))
btnTwo = wx.Button(self, label="Test 2",size=(200, 40))
btn.Bind(wx.EVT_BUTTON, self.newAddImage)
self.sizer.Add(self.listBox, proportion=1, flag=wx.TOP | wx.EXPAND | wx.LEFT, border=5)
btnSizer.Add(btn, 0, wx.ALL, 5)
btnSizer.Add(btnTwo, 0, wx.ALL, 5)
self.sizer.Add(btnSizer)
self.sizerMain.Add(self.sizer, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=0)
self.SetSizer(self.sizerMain)
def imagesel(self, evt):
self.image_listsel = self.listBox.GetSelection()
def newAddImage(self, evt):
IMAGEMORE_NAME.append('New image')
IMAGEMORE_DATA.append('')
self.listBox.Set(IMAGEMORE_NAME)
self.listBox.SetSelection(len(IMAGEMORE_NAME)-1)
self.imagesel(None) #making it a selected image, globally
def reName(self,parent):
sel = self.listBox.GetSelection()
text = self.listBox.GetString(sel)
renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
if renamed != '':
IMAGEMORE_NAME.pop(sel)
IMAGEMORE_NAME.insert(sel,renamed)
self.listBox.Set(IMAGEMORE_NAME)
self.listBox.SetSelection(sel)
class MyPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
self.notebook = wx.Notebook(self, size=(225, -1))
self.tab_images = imageTab(self.notebook, self)
self.notebook.AddPage(self.tab_images, "Regular Pictures", select=True)
self.tab_imagesmore = objectTab(self.notebook, self)
self.notebook.AddPage(self.tab_imagesmore, "More Pictures")
self.scroll_img = wx.ScrolledWindow(self, -1)
self.scroll_img.SetScrollbars(1, 1, 600, 400)
self.images_area = wx.StaticBox(self, -1, '')
self.sizerBox = wx.StaticBoxSizer(self.images_area, wx.HORIZONTAL)
self.sizerBox2 = wx.BoxSizer()
self.sizerBox.Add(self.scroll_img, 1, wx.EXPAND|wx.ALL, 10)
self.sizerBox2.Add(self.sizerBox, 1, wx.EXPAND|wx.ALL, 10)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.notebook, proportion=0, flag=wx.EXPAND)
btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
self.btnTwo = wx.Button(self, label="Load File", size=(200, 40))
self.bmp = None
self.bitmap = None
self.imageboxersiz=wx.ComboBox(self, -1, "None Selected!",(0, 0), (190,20),IMAGE_NAME, wx.CB_DROPDOWN)
btnSizer.Add(self.imageboxersiz, 0, wx.TOP, 15)
btnSizer.Add(self.btnTwo, 0, wx.TOP, 15)
self.sizerBox2.Add(btnSizer)
#
self.sizer.Add(self.sizerBox2, proportion=1, flag=wx.EXPAND)
self.SetSizer(self.sizer)
self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
areachange(self, self.notebook.GetPageText(0))
def OnClickTop(self, event):
self.scroll_img.Scroll(600, 400)
def OnClickBottom(self, event):
self.scroll_img.Scroll(1, 1)
def OnPageChanged(self, event):
new = event.GetSelection()
areachange(self, self.notebook.GetPageText(new))
event.Skip()
def OnPageChanging(self, event):
event.Skip()
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = MyPanel(self)
self.Show()
app = wx.App(False)
win = MainWindow(None, size=(600, 400))
app.MainLoop()
Thank you very much.
Just change the self.Refresh() to self.Layout(). Worked for me on Windows 7 anyway.
I was trying to get my first wxWindow application to work and I ran into following difficulty:
I create wxPanel and add a wxNotebook object to it. Then I add a page to notebook created from another wxPanel object. How do I access a value of TextCtrl from first wxPanel in the second one?
import wx
class BasicApp(wx.App):
def OnInit(self):
frame = BasicFrame(None, -1, "Test App")
panel = BasicPanel(frame, -1);
frame.Show(True)
self.SetTopWindow(frame)
return True;
class BasicFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title,
wx.DefaultPosition, wx.Size(400, 300))
self.CreateStatusBar()
class BasicPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.lblText1 = wx.StaticText(self, -1, "Text1:");
self.txtText1 = wx.TextCtrl(self, 1001, "Text1", size = wx.Size(140, -1));
self.line1 = wx.BoxSizer(wx.HORIZONTAL);
self.line1.Add(self.lblText1, 0, wx.EXPAND);
self.line1.Add(self.txtText1, proportion=1, flag=wx.LEFT, border=5);
self.nb = wx.Notebook(self, -1);
tab1 = Tab1(self.nb, -1);
self.nb.AddPage(tab1, "Tab1");
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.line1, 0, wx.EXPAND)
self.sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.SetAutoLayout(1)
self.sizer.Fit(self)
self.Show(1)
class Tab1(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id);
self.lblText2 = wx.StaticText(self, -1, "Text2:");
self.txtText2 = wx.TextCtrl(self, 1101, "Text2", size = wx.Size(140, -1));
self.line1 = wx.BoxSizer(wx.HORIZONTAL);
self.line1.Add(self.lblText2, 0, wx.EXPAND);
self.line1.Add(self.txtText2, 0, wx.EXPAND);
self.lblMessage = wx.StaticText(self, -1, "Message:");
self.txtMessage = wx.TextCtrl(self, 1102, "", style = wx.TE_MULTILINE);
self.cmdCreate = wx.Button(self, 1103, "Create");
self.cmdCreate.Bind(wx.EVT_BUTTON, self.Create_OnClick)
self.line3 = wx.BoxSizer(wx.HORIZONTAL);
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.line1, 0, wx.EXPAND)
self.sizer.Add(self.lblMessage, 0, wx.EXPAND)
self.sizer.Add(self.txtMessage, 1, wx.EXPAND)
self.sizer.Add(self.cmdCreate, 0, wx.LEFT)
self.SetSizer(self.sizer)
self.SetAutoLayout(1)
self.sizer.Fit(self)
self.Show(1)
def Create_OnClick(self, event):
text1 = "";
text2 = self.txtText2.GetValue();
self.txtMessage.SetValue(text1 + " " + text2);
app = BasicApp(0)
app.MainLoop()
To be more specific I want to be able to access value of txtText1 in Create_OnClick() method. How could this be achieved?
One solution is to pass the control to the constructor of the tab, then you can directly reference it. For example:
class Tab1(wx.Panel):
def __init__(self, parent, id, textCtrl1):
wx.Panel.__init__(self, parent, id);
self.textCtrl1 = textCtrl1
...
def Create_OnClick(self, event):
text1 = self.textCtrl1
Another solution is to move the Create_OnClick handler to the base panel since it knows about all of the other panels (and thus, their children). Or, create a separate controller class that knows about the various widgets and can have handlers that act on behalf of them all.