wxPython clearing hinted text causes crash - python

As the title says when I implement code to clear hinted text and it is run the application crashes.
As far as I know this is only on Mac OS X 10.8 but that is also all I have been able to run it on.
On other code it does run and only once I enter text into it (After giving focus) does it crash. But this app crashes immediately (I think something to do with no other widgets and so it get focus right away). Updated example so it no longer crashes right away now you have to click on the combo box and try to type in it for it to crash.
This however does not occur if the text is anything but "" it seems.
Code
import wx
class MyCrashyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
# another widget to take focus at first otherwise it crashes instantly!
sizer = wx.BoxSizer(wx.VERTICAL)
self.text_ctrl = wx.TextCtrl(self, -1, value = "There are major problems here.\nWithout this to auto take focus this will crash immediatly just by trying to clear the hint.\nNow you have to click on the combo ctrl and try to type.", style = wx.TE_MULTILINE)
self.search_ctrl = wx.ComboBox(self, -1)
self.search_ctrl.SetMinSize((650, -1))
self.search_ctrl.SetSize((650, -1))
self.search_ctrl.SetHint("This is are hint text; once it is clear and you try to type something in it it will crash on Mac OS X")
sizer.Add(self.text_ctrl, flag = wx.EXPAND)
sizer.Add(self.search_ctrl)
self.SetSizer(sizer)
self.FirstTimeSearchGetsFocus = True
self.Bind(wx.EVT_BUTTON, lambda e: e.Skip(), self.text_ctrl)
self.search_ctrl.Bind(wx.EVT_SET_FOCUS, self.OnSearchFocus)
self.text_ctrl.SetFocus()
def OnSearchFocus(self, event):
print "Search Focus"
if 1==1:
print "First time"
# clear the hinted text
self.search_ctrl.SetHint("")
self.search_ctrl.Clear()
self.search_ctrl.Refresh()
self.FirstTimeSearchGetsFocus = False
event.Skip()
if __name__ == "__main__":
app = wx.App(False)
f = wx.Frame(None, -1)
MyCrashyPanel(f)
f.Show()
app.MainLoop()
Crash Report
[Too big get here http://pastebin.com/9B1Sgh3P ]

If it crashes, it's a bug in wxWidgets, so the only things to do are to:
Try with a later version, i.e. 2.9.5 or svn/git if you can build it yourself.
Report the bug if it still persists there, following the usual guidelines.

Related

GetPosition() not working with wxPython

I'm new to Python (and programming in general) so forgive me if this is a dumb question.
I'm following a tutorial in a book for creating a GUI in Python. Right now I'm learning about how to make a Spin Control increment some static text. When I run it, the spin control shows up but the console says "value = event.GetPosition()
AttributeError: 'CommandEvent' object has no attribute 'GetPosition'"
The code is:
import wx
class Frame(wx.Frame):
def __init__(self, title):
wx.Frame.__init__(self, None,\
title=title, size=(300,250))
panel = wx.Panel(self)
sc = wx.SpinCtrl(panel, value='0', pos=(130, 50), size=(70, 25))
self.valueText = wx.StaticText(panel, label='', pos=(130,80))
sc.Bind(wx.EVT_SPINCTRL, self.spinControl)
def spinControl(self, event):
# Get spin control value
value = event.GetPosition()
# Update static text
self.valueText.SetLabel(str(value))
app = wx.App()
frame = Frame("wxPython Widgets!")
frame.Show()
app.MainLoop()
That code is literally copy/pasted from the book's website. I have wxPython installed and everything works perfectly up to that point.
Halp!
I've been working through that same book Python in a Day 2. I believe the content is already outdated.
If you change the line with GetPosition() to
value = event.GetEventObject().GetValue()
is correct. I can confirm that it works for Python 2.7.11.
Jeremiah
If you change the line with GetPosition() to
value = event.GetEventObject().GetValue()
it will work. The event just doesnt have the GetPosition attribute, so it cannot eb executed.
If you want to check which functions and attributes are available, you can use
print(dir(event))
This will show you everything which is available inside the event.
Michael

wxPython: How can I listen to EVT_CHAR events on a multiline TextCtrl?

I am able to successfully listen to EVT_CHAR events on a TextCtrl but when I change the TextCtrl to use TE_MULTILINE then the binding seems to stop working.
self.input = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self.input.Bind(wx.EVT_CHAR, self.OnChar)
I am using 3.0.3.dev1820+49a8884 osx-cocoa (phoenix).
How can I listen to EVT_CHAR events on a multiline TextCtrl?
The code exhibited in the question should work, and does if you're not on a Mac. The fact that it doesn't work on Macs is a bug - I reported it at https://github.com/wxWidgets/Phoenix/issues/804 and it's confirmed by the maintainers.
The bug will be fixed in wxPython 4.1, which at the time of writing is not yet released.
If you have to use a version of wxPython that doesn't have the fix, then depending upon your objectives it may be adequate to bind to wx.EVT_TEXT or wx.EVT_KEY_DOWN instead, although neither has quite the same behaviour as wx.EVT_CHAR.
I could not reproduce your problem. Here's the working code that I modified from the Mouse vs the Python blog. I only changed the style of text control to wx.TE_MULTILINE and it still works on Windows7 (wxPython2.8.12.1). Could it be a Phoenix bug?
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Char Event Tutorial")
# Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
btn = wx.TextCtrl(panel, value="", style=wx.TE_MULTILINE)
btn.Bind(wx.EVT_CHAR, self.onCharEvent)
def onCharEvent(self, event):
keycode = event.GetKeyCode()
controlDown = event.CmdDown()
altDown = event.AltDown()
shiftDown = event.ShiftDown()
print keycode
if keycode == wx.WXK_SPACE:
print "you pressed the spacebar!"
elif controlDown and altDown:
print keycode
event.Skip()
# Run the program
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyForm()
frame.Show()
app.MainLoop()

Enter key in wx.TextCtrl on Mac has no effect

When I run the program below on Mac OS X Yosemite, pressing the enter key inside the TextCtrl doesn't have any effect on the contents of the TextCtrl at all (I need it to enter a newline in the text).
Adding or removing the TE_PROCESS_ENTER style doesn't have any effect at all; the EVT_TEXT_ENTER event doesn't get fired. Pressing enter does trigger an EVT_KEY_UP event with keycode 13, by the way.
Strangely enough, pressing Ctrl+Enter does cause a newline to be entered inside the TextCtrl, but it also doesn't fire an EVT_TEXT_ENTER event.
What is happening here? Of course I could work around this and detect keycode 13, but of course that doesn't really solve the problem.
#!/usr/bin/env pythonw
import wx
class MainWindow(wx.Frame):
def __init__(self, title):
wx.Frame.__init__(self, None, title=title, size=(500,500))
self.tc = wx.TextCtrl(self, wx.TE_MULTILINE|wx.TE_PROCESS_ENTER, size=(200,100))
self.tc.Bind(wx.EVT_KEY_UP, self.OnKeyUp, self.tc)
self.tc.Bind(wx.EVT_TEXT_ENTER, self.OnEnter, self.tc)
self.Show(True)
def OnKeyUp(self, event):
print event.GetKeyCode()
def OnEnter(self, event):
# Never gets called
print "enter!"
if __name__ == '__main__':
app = wx.App()
frame = MainWindow('Test')
app.MainLoop()
I'm on Mac OS X (Yosemite), using python 2.7.9 (through homebrew) and wxPython 3.0.2.0.
the problem is in the call to the wxTextCtrl constructor; the flags are not being passed in correctly.
self.tc = wx.TextCtrl(self, wx.TE_MULTILINE|wx.TE_PROCESS_ENTER, size=(200,100))
should really be
self.tc = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER, size=(200,100))
The text control was not being initialized to be a multi-line control.

how to create read only text ctrl but support copy paste event

In my application i have text control.
I want my text ctrl should be read only but when some one right click on this he is able to copy the value from that ctrl and he can paste that value in other text control.
If i made my text control read only with wx.TE_READONLY then copy/paste is not working.
Is there any requirement to handle other type of wx event or i have to set more type of wx style flags while creating the text control object.
Thanks in advance.
Hmm Im on windows 7 and don't have any problem copying from a textCtrl that has the wx.READ_ONLY style flag set.
You said you wanted to paste into another textCtrl -obviously you can't have the wx.READ_ONLY style flag set in the textCtrl you want to be able to paste into.
Try out the demo below, you should be able to copy from the textCtrl on the left(which is read only) to the one on the right(which doesn't have the read only style set).
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, id=-1):
wx.Frame.__init__(self,parent,id, size=(200,200))
self.panel = wx.Panel(self,wx.ID_ANY)
bsizer = wx.BoxSizer()
read_only_txtCtrl = wx.TextCtrl(self,-1,
"This textCtrl is read only",
style=wx.TE_MULTILINE|wx.TE_READONLY)
editable_txtCtrl = wx.TextCtrl(self,-1,
"This textCtrl is editable",
style=wx.TE_MULTILINE)
bsizer.Add(read_only_txtCtrl, 1, wx.EXPAND)
bsizer.Add(editable_txtCtrl, 1, wx.EXPAND)
self.SetSizerAndFit(bsizer)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MainWindow(None)
frame.SetSize((200,200))
frame.Show()
app.MainLoop()
We should bind wx.EVT_TEXT_COPY and wx.EVT_TEXT_PASTE with text control.
one can copy and paste data from text ctrl although text ctrl is read only mode.
Actually I had the same challenge. I needed a textbox where users could paste information (or open -> read file via a menu). The app would then analyze the info for correctness. But I didn't want to allow editing in the textbox - it would suggest that you could correct in the same textbox, while the app was for analysis only. Yeah, requirements, I know.
Weird thing was, I could make a readonly TextCtrl under MacOSX that would allow pasting (but not editing), but not on Windows.
In order to support both, I ended up creating a read/writesuper(MyWin, self).init(None, size=(800,600)) textbox (to allow pasting under windows) and binding wx.EVT_TEXT events to it (apart from wx.EVT_TEXT_PASTE for the obvious pasting). The EVT_TEXT handler that's triggered when the textctrl's contents change, simply shows a dialog that you aren't allowed to do this.
In the app a boolean this.painted plays the following role: when this.painted is true, then modifications of the textctrl aren't allowed. So, the onpaste handler first sets this.painted to false, then modifies the TextCtrl's contents, then sets this.painted to true (otherwise the dialog alert would also go off during the paste event, which I wanted to allow). Unfortunately when the EVT_TEXT handler goes off, the window's contents have already been modified by a user hitting some key. Therefore the app also needs a backup buffer to put back into the TextCtrl when such editing has been detected.
According to the Python docs, TextCtrl.ChangeValue() instead of SetValue() should not trigger the EVT_TEXT event (which would be handy) but I couldn't get that to work, might be my mistake due to not-enough-time-to-investigate-because-it-should-have-been-done-yesterday.
Not an elegant solution, but works.
import wx
class MyWin(wx.Frame):
def __init__(self):
super(MyWin, self).__init__(None, size=(800,600))
self.painted = True
self.backup = ''
self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.HSCROLL)
self.text.Bind(wx.EVT_TEXT_PASTE, self.onpaste)
self.text.Bind(wx.EVT_TEXT, self.ontextchange)
self.Show()
def onpaste(self, event):
if not wx.TheClipboard.IsOpened():
buf = wx.TextDataObject()
wx.TheClipboard.Open()
success = wx.TheClipboard.GetData(buf)
wx.TheClipboard.Close()
if success:
self.painted = False
self.backup = buf.GetText()
self.text.SetValue(self.backup)
self.painted = True
def ontextchange(self, event):
if self.painted:
dlg = wx.MessageDialog(self, 'Editing not allowed', '', wx.OK)
dlg.ShowModal()
dlg.Destroy()
self.painted = False
self.text.SetValue(self.backup)
self.painted = True
app = wx.App()
frame = MyWin()
app.MainLoop()

wx Python is not properly drawing customtree items

I am currently using wx.CustomTree, to use to display a series of configuration settings. I generally fill them with wx.TextCtrl / wx.Combobox, to allow the user to edit / enter stuff. Here is my code:
class ConfigTree(CT.CustomTreeCtrl):
"""
Holds all non gui drawing panel stuff
"""
def __init__(self, parent):
CT.CustomTreeCtrl.__init__(self, parent,
id = common.ID_CONTROL_SETTINGS,
style = wx.TR_DEFAULT_STYLE | wx.TR_HAS_BUTTONS
| wx.TR_HAS_VARIABLE_ROW_HEIGHT | wx.TR_SINGLE)
#self.HideWindows()
#self.RefreshSubtree(self.root)
self.population_size_ctrl = None
self.SetSizeHints(350, common.FRAME_SIZE[1])
self.root = self.AddRoot("Configuration Settings")
child = self.AppendItem(self.root, "Foo", wnd=wx.TextCtrl(self, wx.ID_ANY, "Lots Of Muffins"))
The problem is, any children nodes, the data for these nodes is not filled in. When i basically expand the configuration settings tree node. I see the "Foo" node, however the textbox is empty. This is the same for both text node, Until i actually click on the child node. I've looked tried every form of update / etc. Does anyone have any ideas?
To: Anurag Uniyal
Firstly sorry for not giving the rest of the code. I've gotten around this problem by simply resizing the window everytime i demo the application.
So i tried the code on my Macbook Pro running Mac OS X, with newest wx and python 2.6. I still have the same problem, however i noticed resizing the window, or even touching the scrollbar fixes the issue.
I also noticed however, there is absolutely NO problems running on Windows Vista / Windows 7.
So trying this on another macbook running an older version of wx + python. Results in the same problem :(
Is there anyway to force the panel to redraw it self? Which i am pretty sure happens when i resize the window.
If you don't have any ideas then i'll strip it down and make a demo example, im home and won't be at work until later tommorow.
You can use RefreshItems if you are using virtual controls, or you could refresh the panel, which would update the contents of all the children windows (widgets).
I tested it on window with wx version 2.8.10.1 and it works, which OS and wx version you are using?
here is self contained code, which can be copy-pasted and run
import wx
import wx.lib.customtreectrl as CT
class ConfigTree(CT.CustomTreeCtrl):
"""
Holds all non gui drawing panel stuff
"""
def __init__(self, parent):
CT.CustomTreeCtrl.__init__(self, parent,
id = -1,
style = wx.TR_DEFAULT_STYLE | wx.TR_HAS_BUTTONS
| wx.TR_HAS_VARIABLE_ROW_HEIGHT | wx.TR_SINGLE)
self.population_size_ctrl = None
self.SetSizeHints(350, 350)
self.root = self.AddRoot("Configuration Settings")
child = self.AppendItem(self.root, "Foo", wnd=wx.TextCtrl(self, wx.ID_ANY, "Lots Of Muffins"))
def main():
app = wx.App()
frame = wx.Frame(None, title="Test tree", size=(500,500))
p = wx.Panel(frame, size=(500,500))
tree = ConfigTree(p)
tree.SetSize((500,500))
frame.Show()
app.MainLoop()
if __name__ == '__main__':
main()

Categories

Resources