So this is a pretty basic program but for some reason it keeps crashing wtih exit code 139. I've looked online at the error code and it has to do with memory management but a basic form with a few plaintext, buttons, and fields should not be too much for a 64 bit machine with 16GB of RAM. I have another class that is almost identical and it works fine. Where am I going wrong here?
import wx
class mainForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Test")
self.panel = wx.Panel(self)
vbox_main = wx.BoxSizer(wx.VERTICAL) # main vertical box
url_box = wx.BoxSizer(wx.HORIZONTAL)
url_label = wx.StaticText(self.panel, label="URL:")
self.url_entry = wx.TextCtrl(self.panel)
url_box.Add(url_box)
url_box.Add(url_label)
url_box.Add(self.url_entry)
file_box = wx.BoxSizer(wx.HORIZONTAL)
file_label = wx.StaticText(self.panel, label="File")
self.file_entry = wx.TextCtrl(self.panel)
file_button = wx.Button(self.panel, label="Search")
file_button.Bind(wx.EVT_BUTTON, self.search)
file_box.Add(file_label)
file_box.Add(self.file_entry)
file_box.Add(file_button)
mode_box=wx.BoxSizer(wx.HORIZONTAL)
mode_label=wx.StaticText(self.panel, label='Mode')
#self.mode_button = buttons.GenToggleButton(self.panel, -1, "Autonomous Mode")
mode_box.Add(mode_label)
#mode_box.Add(self.mode_button)
go_box = wx.BoxSizer(wx.HORIZONTAL)
go_button = wx.Button(self.panel, label='Go!')
go_button.Bind(wx.EVT_BUTTON, self.submit)
go_box.Add(go_button)
vbox_main.Add(url_box)
vbox_main.Add(file_box)
vbox_main.Add(mode_box)
vbox_main.Add(go_box)
self.panel.SetSizer(vbox_main)
self.Show(True)
def search(self):
pass
def submit(self):
pass
You can not add wxBoxSizer himself and you need to comment the line:
url_box.Add(url_box)
Related
In my app, I want to handle allocation / deallocation of sizers inside a scrolledPanel. In my first try, I was hiding / showing the contents of the sizers, but this was causing a lot of problems. The hidden sizers would "stay there", effectively ocuppying space, it would not update propely, etc. The solution that worked better was to destroy and create them over and over again.
But this that its problems too. The scrolledPanel blinks while I'm updating it and seems to be resource heavy. In my real app, I put the references of the buttons and checkboxes in lists and it becames more dificult to handle them.
So, if anyone has a better solution, I'm all ears!
I'm up to a hiding / showing solution! Something to reset the size of the scrolledPanel to accomodate only the sizer it currently has it would be nice too.
Thanks!
import wx
import wx.lib.scrolledpanel as scrolled
class WaterDataBase(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.setupSizers()
self.setupData()
def setupSizers(self):
masterSizer = wx.BoxSizer(wx.HORIZONTAL)
itemsSizer = wx.BoxSizer(wx.VERTICAL)
itemsSizer.Add(self.addSearchControl(), flag=wx.ALL, border=7)
self.scrolledPanelSizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_panel = scrolled.ScrolledPanel(self, wx.ID_ANY, size=(200, 200))
self.scrolled_panel.SetSizer(self.scrolledPanelSizer)
itemsSizer.Add(self.scrolled_panel, flag=wx.ALL, border=7)
masterSizer.Add(itemsSizer)
self.scrolled_panel.SetupScrolling()
self.SetSizer(masterSizer)
def addSearchControl(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.searchField = wx.TextCtrl(self, -1)
self.searchField.Bind(wx.EVT_TEXT, self.OnSearched)
sizer.Add(self.searchField)
return sizer
def setupData(self):
self.words = "I'm trying to make this work, please. Let's keep it on! The day is beautiful today. Together we are stronger!".split()
for word in self.words:
self.addSizerToPanel(word)
def createSizer(self, word):
# Creates a sizer with a CheckBox and a StaticText to display.
sizer = wx.BoxSizer(wx.HORIZONTAL)
checkBox = wx.CheckBox(self.scrolled_panel, -1)
text = wx.StaticText(self.scrolled_panel, -1, word)
sizer.Add(checkBox, flag=wx.ALL, border=5)
sizer.Add(text, flag=wx.LEFT, border=5)
return sizer
def addSizerToPanel(self, word):
sizer = self.createSizer(word)
self.scrolledPanelSizer.Add(sizer, flag=wx.ALL, border=5)
def OnSearched(self, event):
query = self.searchField.GetValue().lower()
result = []
# If query's empty, print all words
if not query or query.isspace():
for word in self.words:
result.append(word)
else:
for word in self.words:
if word.lower().find(query) != -1:
result.append(word)
# Destroy all panel sizers and put exactly the ones we want.
self.scrolled_panel.DestroyChildren()
for word in result:
self.addSizerToPanel(word)
self.scrolled_panel.Layout()
self.scrolled_panel.Scroll(0, 0) # Using this to cause the scrollPanel get back to the top.
app = wx.App()
frame = WaterDataBase(None).Show()
app.MainLoop()
So, it seems I've made it, finally. I still wants the advice about reseting the size of the scrolledPanel. xD
import wx
import wx.lib.scrolledpanel as scrolled
class Frame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.sizerRefs = []
self.words = []
self.setupSizers()
self.setupData()
def setupSizers(self):
masterSizer = wx.BoxSizer(wx.HORIZONTAL)
itemsSizer = wx.BoxSizer(wx.VERTICAL)
itemsSizer.Add(self.addSearchControl(), flag=wx.ALL, border=7)
self.scrolledPanelSizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_panel = scrolled.ScrolledPanel(self, wx.ID_ANY, size=(200, 200))
self.scrolled_panel.SetSizer(self.scrolledPanelSizer)
itemsSizer.Add(self.scrolled_panel, flag=wx.ALL, border=7)
masterSizer.Add(itemsSizer)
self.scrolled_panel.SetupScrolling()
self.SetSizer(masterSizer)
def addSearchControl(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.searchField = wx.TextCtrl(self, -1)
self.searchField.Bind(wx.EVT_TEXT, self.OnSearched)
sizer.Add(self.searchField)
return sizer
def setupData(self):
self.words = "I'm trying to make this work, please. Let's keep it on! The day is beautiful today. Together we are stronger!".split()
for i in range(0, len(self.words)):
self.addSizerToPanel(i)
def createSizer(self, index):
sizer = wx.BoxSizer(wx.HORIZONTAL)
checkBox = wx.CheckBox(self.scrolled_panel, -1)
text = wx.StaticText(self.scrolled_panel, -1, self.words[index])
sizer.Add(checkBox, flag=wx.ALL, border=5)
sizer.Add(text, flag=wx.LEFT, border=5)
self.sizerRefs.append(sizer)
return sizer
def addSizerToPanel(self, index):
sizer = self.createSizer(index)
self.scrolledPanelSizer.Add(sizer, flag=wx.ALL, border=5)
def hideAllSizers(self):
for sizer in self.sizerRefs:
sizer.ShowItems(False)
def unhideSizer(self, index):
self.sizerRefs[index].ShowItems(True)
def OnSearched(self, event):
query = self.searchField.GetValue().lower()
result = [] # Storing the indexes of the words found
# If query's empty, print all words
if not query or query.isspace():
for i in range(0, len(self.words)):
result.append(i)
else:
for i in range(0, len(self.words)):
if self.words[i].lower().find(query) != -1:
result.append(i)
# Hides all panel sizers and unhide exactly the ones we want.
self.hideAllSizers()
for i in range(0, len(result)):
self.unhideSizer(result[i])
self.scrolled_panel.Layout()
self.scrolled_panel.Scroll(0, 0) # Using this to cause the scrollPanel get back to the top.
app = wx.App()
frame = Frame(None).Show()
app.MainLoop()
I am developing a wxpython, i am looking for button generating, for example.
In text box enter the value how many button have to generate.
While submitting that, i have to show in panel as many as button
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Background Reset Tutorial",size=wx.Size(500,500))
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
self.txt = wx.TextCtrl(self.panel,id=wx.ID_ANY,pos=(185,40))
txtSizer = wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.panel,id=wx.ID_ANY,label="Submit",pos=
(190,70),size=(100,30))
self.btn.Bind(wx.EVT_BUTTON,self.onSubmit)
def onSubmit(self,event):
gettxt = self.txt.GetValue()
I got the solution
def onBtn(self,event):
self.val = self.txtstring1.GetValue()
Blue = wx.Button(self,label="Blue",pos=(30,50))
Blue.Bind(wx.EVT_BUTTON,self.onBlue)
Green = wx.Button(self,label="Green",pos=(300,50))
Green.Bind(wx.EVT_BUTTON,self.onGreen)
for self.button_name in range(self.val):
self.btn = wx.Button(self, label=str(self.button_name),pos=(50,50))
self.btn.Bind(wx.EVT_BUTTON, lambda evt, temp=self.button_name:
self.OnButton(evt, temp))
self.widgetSizer.Add(self.btn, 0, wx.ALL|wx.CENTER, 5)
As someone pretty new to wxpython, I'm attempting to write a login script for an imaginary program. On startup, buttons ask if you want to create a new account or register a new one. When either one is clicked, I want all the widgets on the page to disappear, leaving a blank frame for other widgets to be imposed on. However I'm not sure how to .Hide() specific widgets -- my existing widgets are not being recognized as variables. Here's my relevant code:
class Welcome(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "ImageViewer", size=(500,350))
panel = wx.Panel(self)
text = wx.StaticText(panel, -1, "Welcome to ImageViewer. Do you have an account?", (50,10))
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
text.SetFont(font)
yesbutton = wx.Button(panel, label="Yes, I wish to log in", pos=(50,150), size=(150,60))
self.Bind(wx.EVT_BUTTON, self.loginwindow, yesbutton)
nobutton = wx.Button(panel, label="No, I wish to register", pos=(270,150), size=(150,60))
self.Bind(wx.EVT_BUTTON, self.registerwindow, nobutton)
def loginwindow(self, event):
self.Hide(self.text) #Error occurs here
AttributeError: 'Welcome' object has no attribute 'text'
I'm not sure if there is a better way of doing this (if there is please let me know) but for now I'm just not sure why I can't access these variables.
text isn't made an attribute of of the Welcome class, so when you try and call it in your loginwindow function it's out of scope.
When you declare it in your init method make it self.text
Edit: This code works.
class Welcome(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, None, id, "ImageViewer", size=(500,350))
panel = wx.Panel(self)
self.text = wx.StaticText(panel, -1, "Welcome to ImageViewer. Do you have an account?", (50,10))
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
self.text.SetFont(font)
yesbutton = wx.Button(panel, label="Yes, I wish to log in", pos=(50,150), size=(150,60))
self.Bind(wx.EVT_BUTTON, self.loginwindow, yesbutton)
def loginwindow(self, event):
self.text.Hide() #Error occurs here
I am programming an application using wxpython and wx.lib.pubsub. in python 2.7.3
1- There is a Frame with a menu item. When this menu is clicked, a message is published by pubsub.
2- This message destroys (if possible) and creates a "first level" dialogue.
3- "First Level" dialogue has an list of valules and an "add value" button. (NOTE: Such list of variables can be modified so I am trying to update this list)
4- When the "add value" button is clicked, another message is published by pubsub.
5- This message creates a "Second Level" dialogue, so a new name for the new variable can be written.
6- There is a "continue" button in this "second level" dialogue which has two consequences:
First one: Self.Destroy();
Second one: goes to step 2, i.e. destroys the "first level" dialogue and creates it again.
To that point the program seems to work fine, however, when I finish "adding" variables to the "first level" dialogue I Destroy it and then I cannot go back to the main Frame stated in step 1.
Why is this happening?
All the Dialogues are shown via ShowModal(). However if I use only Show() it seems to work fine but, since the program has many menus and items, ShowModal() is preferred.
Any idea why it works with Show() but not with ShowModal()?
If there is a simpler way to perform the task I want to do, it would be appreciated.
import wx
from wx.lib.pubsub import Publisher as pub
class itemReceiver(object):
def __init__(self):
pub.subscribe(self.__OnShowDialog, 'show.dialog')
def __OnShowDialog(self, message):
self.dlgParent = message.data[0]
print str(self.dlgParent)
self.valuesToShow = message.data[1]
print self.valuesToShow
#try to destroy dialog before creating a new one
try:
self.manageParametersDialog.Destroy()
except:
pass
self.manageParametersDialog = manageParamsDialog(self.dlgParent, self.valuesToShow)
print "ready to show first level dialogue"
self.manageParametersDialog.ShowModal() #if .Show() instead, there is no problem
class secondaryReceiver(object):
def __init__(self):
pub.subscribe(self.__OnShowDialog, 'add.item')
def __OnShowDialog(self, message):
dlgParent = message.data[0]
dlgGrandParent = message.data[1]
self.variableList = message.data[2]
editParameterDialog = editParamDlg(dlgParent, dlgGrandParent, self.variableList)
editParameterDialog.ShowModal()
class manageParamsDialog (wx.Dialog):
def __init__(self, parent, valueList):
self.valueList = valueList
self.parent = parent
wx.Dialog.__init__(self, parent, -1, "first level dialogue", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
sizer=wx.BoxSizer(wx.VERTICAL)
self.optionList = wx.ListBox(self, -1, size=(200, 70), choices = valueList)
sizer.Add(self.optionList)
addButton = wx.Button(self, -1, 'Add New')
self.Bind(wx.EVT_BUTTON, self.OnButton, addButton)
sizer.Add(addButton)
cancelButton = wx.Button(self, -1, 'Cancel')
self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)
sizer.Add(cancelButton)
self.SetSizer(sizer)
self.Fit()
def OnButton (self, e):
pub.sendMessage('add.item', [self, self.parent, self.valueList])
def OnCancel(self,e):
self.Destroy()
class editParamDlg(wx.Dialog):
def __init__(self, parent, grandParent, variableList):
self.variableList = variableList
self.grandParent = grandParent
wx.Dialog.__init__(self, parent, -1, "second level dialogue", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
hboxSizer = wx.BoxSizer(wx.HORIZONTAL)
self.textInput = wx.TextCtrl(self, -1)
hboxSizer.Add(self.textInput)
addButton = wx.Button(self, -1, 'Continue')
self.Bind(wx.EVT_BUTTON, self.OnAdd, addButton)
hboxSizer.Add(addButton)
cancelButton = wx.Button(self, -1, 'Cancel')
self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)
hboxSizer.Add(cancelButton)
self.SetSizer(hboxSizer)
self.Fit()
def OnAdd(self, e):
self.variableList.append(self.textInput.GetValue())
self.Destroy()
pub.sendMessage('show.dialog',[self.grandParent, self.variableList])
def OnCancel(self,e):
self.Destroy()
class ToolbarFrame(wx.Frame):
#this ToolbarFrame is the main window, with a Toolbar and a white panel below.
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "this is a frame", size=(480, 320))
myPanel = wx.Panel(self)
myPanel.SetBackgroundColour("White")
menuBar = wx.MenuBar()
fileMenu = wx.Menu()
menuItem = wx.MenuItem(fileMenu, -1, "menu item", "opens dialog via pubsub")
self.Bind(wx.EVT_MENU, self.OnMenuItem, menuItem)
fileMenu.AppendItem(menuItem)
menuBar.Append(fileMenu, "File")
self.SetMenuBar(menuBar)
def OnMenuItem(self, e):
pub.sendMessage('show.dialog', [self, ["one", "two", "three"]])
app = wx.PySimpleApp()
frame = ToolbarFrame(parent=None, id=-1)
frame.Show()
newItemListener = itemReceiver()
editParameterListener = secondaryReceiver()
app.MainLoop()
try changing secondaryReciever as follows
class secondaryReceiver(object):
def __init__(self):
pub.subscribe(self.__OnShowDialog, 'add.item')
def __OnShowDialog(self, message):
dlgParent = message.data[0]
dlgGrandParent = message.data[1]
self.variableList = message.data[2]
editParameterDialog = editParamDlg(dlgParent, dlgGrandParent, self.variableList)
editParameterDialog.ShowModal()
#this line will not execute till the dialog closes
self.dlgParent.optionList.SetItems(editParameterDialog.variableList)
editParameterDialog.Destroy()
and also change editParamDlg
def OnAdd(self, e):
self.variableList.append(self.textInput.GetValue())
self.Close()
the problem was that you would call the show.modal from that OnAdd ... which would try to destroy the existing window and then open a new one... but the old one wasnt destroyed ... this left weird remnants that caused you errors ... and really all you want to do is update the item list ...
I have created a pop up window, but the TextCtrl is not fully expanded to fill up the window. It works great if I use StaticText instead, (but if content too large then I would need the scroll bar, that is why I am using TextCtrl now). Please provide some guidance.
self.description = WindowPopup(self, wx.SIMPLE_BORDER, content)
btn = event.GetEventObject()
dw = wx.DisplaySize()[0]
width = self.description.GetSize()[0]
y = btn.ClientToScreen((0,0))[1]
height = btn.GetSize()[1]
x = dw - width - 20 - 10
self.description.Position((x, y), (0, height))
self.description.Show(True)
class WindowPopup(wx.PopupWindow):
""" Pops up a window to provide description for the selection """
def __init__(self, parent, style, content):
wx.PopupWindow.__init__(self, parent, style)
self.SetSize((700, 287))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
st = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE | wx.TE_READONLY)
st.SetValue(content)
sizer.Add(st, 0, wx.EXPAND)
panel.SetSizer(sizer)
I suspect your problem is that the panel is not as big as the popupwindow ... so even though the textfield is expanding to fill its sizer area it is not filling the popup its self.
try using something like
def __init__(...):
...
self.SetMinSize((700,287))
sizer2 = wx.BoxSizer()
sizer2.Add(panel)
self.SetSizer(sizer2)
also make sure that you are calling layout on it at some point (note this is totally untested... so it may need some tweeks, or even worse just be wrong...)
The actual answer is:
sizer = wx.BoxSizer(wx.VERTICAL)
st = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE | wx.TE_READONLY, size = (500, 174))
st.SetValue(content)
self.SetSize((500, 174))
sizer.Add(st, 0, wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
self.Show(True)
Credits to Joran for noticing Layout().
PopupWindow does not require an additional panel, because the window itself can have sizer set to it. This has been realized by using the wxPython Widget Inspection Tool.
Make sure TextCtrl and PopupWindow have the same size.