screen keyboard

You could use a RadioBox to allow the user to select which type of item to select, and then refill the combo with the items of that type.

···

On 6/1/11 10:31 AM, duncan smith wrote:

Hello,
I have a simple problem (I think) for which I can't find a simple
solution. I have two types of item that I want the user to be able to
select from a combobox. (This is not the same issue I posted about a
couple of months ago.) I'd like to be able to add a separator as I would
for a menu. Just checking if there's a reasonably simple way of doing
that before I start looking at ComboCtrl and OwnerDrawnComboBox (or more
likely, just abandon the idea of separating the items). Cheers.

--
Robin Dunn
Software Craftsman

Hello,
       I am having a few issues with the Treebook control on Windows XP. I have written an application (Python 2.6, wxPython 2.8) that works fine on Ubuntu 10.04, but I cannot get the same functionality on Windows.

I cannot edit the treebook labels by double clicking, even if I set the wx.TR_EDIT_LABELS style on the underlying TreeCtrl instance (which seems not to be needed on Linux).

I cannot delete a treebook page by hitting the delete key.

The treebook is not resized when pages are deleted (or on manual resizing of the window). (In fact I've also managed to break this on Ubuntu when stripping down the code to a reasonable length, although the resize event generated in the OnEndEdit method does have the desired effect. I'll investigate this. Nevertheless, my code that does work as expected on Ubuntu does not on XP, so any hints would be appreciated.) Code below. Thanks.

Duncan

############################code#########################

import wx

class Frame(wx.Frame):
     def __init__(self, prnt):
         wx.Frame.__init__(self, id=wx.ID_ANY, name='Frame', parent=prnt,
               pos=wx.Point(280, 247), size=wx.Size(1288, 767),
               style=wx.DEFAULT_FRAME_STYLE, title='Example')
         self.SetClientSize(wx.Size(1280, 733))
         self.SetMinSize(wx.Size(600, 400))
         self.Bind(wx.EVT_KEY_UP, self.OnFrameKeyUp)
         self.treebook = wx.Treebook(self, wx.ID_ANY,
                                     style=wx.BK_DEFAULT)
         self.treebook.Bind(wx.EVT_TREEBOOK_NODE_EXPANDED,
                            self.OnTreebook)
         self.treebook.Bind(wx.EVT_TREEBOOK_NODE_COLLAPSED,
                            self.OnTreebook)
         tc = self.treebook.GetTreeCtrl()
         tc.SetWindowStyle(tc.GetWindowStyle()|wx.TR_EDIT_LABELS)
         tc.Bind(wx.EVT_LEFT_DCLICK, self.OnFrameLeftDclick)
         self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndEdit)
         # add some panels
         panel1 = wx.Panel(self.treebook)
         panel2 = wx.Panel(self.treebook)
         panel3 = wx.Panel(self.treebook)
         self.treebook.AddPage(panel1, 'First')
         self.treebook.AddPage(panel2, 'Second')
         self.treebook.AddSubPage(panel3, 'Subpanel')
         self.SendSizeEvent()

     def OnTreebook(self, event):
         self.SendSizeEvent()
         event.Skip()

     def OnFrameKeyUp(self, event):
         if event.GetKeyCode() == wx.WXK_DELETE:
             self.treebook.DeletePage(self.treebook.GetSelection())
         event.Skip()

     def OnFrameLeftDclick(self, event):
         tc = event.GetEventObject()
         item, flags = tc.HitTest(event.GetPosition())
         if item:
             print item
             tc.EditLabel(item)
             event.Skip()

     def OnEndEdit(self, event):
         wx.CallAfter(self.SendSizeEvent)
         event.Skip()

app = wx.PySimpleApp()
frame = Frame(None)
frame.Show()
app.MainLoop()

#################################end code###########################

[snip]

It seems that label editing for wx.ListCtrl in the wxPython (2.8.10.1) demo does not work under Windows XP. Can anyone confirm whether or not label editing is possible on XP? If not I need to redesign my application (even if I can sort out the other issues). Thanks.

Duncan

That should have been wx.TreeCtrl, not wx.ListCtrl. And setting the appropriate style works. Regarding the wx.Treebook; after hours of searching and trying various things I found this.

http://old.nabble.com/--wxwindows-Patches-1886815---wxTreebook---Allowing-label-edition-td15291536.html

It seems that the wx.TR_EDIT_LABELS style must be set when the underlying tree control is created. But the programmer has no control over the styles that are set. I assume that on Linux the relevant style is set, and on Windows it isn't. So it seems that label editing is simply not available on Windows, unless someone knows of a workaround. If so, I'd appreciate it. Thanks.

Duncan

···

On 05/05/12 18:11, duncan smith wrote:

[snip]

It seems that label editing for wx.ListCtrl in the wxPython (2.8.10.1)
demo does not work under Windows XP. Can anyone confirm whether or not
label editing is possible on XP? If not I need to redesign my
application (even if I can sort out the other issues). Thanks.

Duncan

[snip]

It seems that label editing for wx.ListCtrl in the wxPython (2.8.10.1)
demo does not work under Windows XP. Can anyone confirm whether or not
label editing is possible on XP? If not I need to redesign my
application (even if I can sort out the other issues). Thanks.

Duncan

That should have been wx.TreeCtrl, not wx.ListCtrl. And setting the
appropriate style works. Regarding the wx.Treebook; after hours of
searching and trying various things I found this.

http://old.nabble.com/--wxwindows-Patches-1886815---wxTreebook---Allowing-label-edition-td15291536.html

It seems that the wx.TR_EDIT_LABELS style must be set when the
underlying tree control is created. But the programmer has no control
over the styles that are set. I assume that on Linux the relevant style
is set, and on Windows it isn't.

They are different implementations so more likely the wx.TreeCtrl used on linux doesn't require the flag to be set before creation, or something like that.

So it seems that label editing is
simply not available on Windows, unless someone knows of a workaround.
If so, I'd appreciate it. Thanks.

It is not hard to implement a book-like class yourself. You simply need to have your tree and the panels you want to display, hide all but one of the panels, and put them all in a sizer. When a selection in the tree is made then you hide the one currently shown, show the new one, and call Layout so the sizer will resize or reposition the newly shown panel if needed. This will give you more control over how the tree is created, how it is sized, etc.

BTW, a comment from your sample code: Key events are sent only to the widget that has the focus, and since they are not command events they do not propagate up the window hierarchy. Since you were binding your key handler to the frame then this is why the delete key did not do anything for you.

···

On 5/6/12 8:19 AM, duncan smith wrote:

On 05/05/12 18:11, duncan smith wrote:

--
Robin Dunn
Software Craftsman

Unfortunately I've lost Robin's reply to this, but it helped. What I had already started to implement as a solution is pasted below. I tried to implement label editing by subclassing wx.Treebook and using a wx.TextCtrl. It seems to work fairly well apart from two issues.

1. When editing, if I left click on the text control to place the cursor, then I lose the control. i.e. I think the tree control is processing the event and the text control is losing focus, triggering its UpdateParent method. I could be wrong. I've tried a number of things, but haven't been able to fix this.

2. After renaming (which works fine as long as I don't left click) I'd like to resize the tree control. Elsewhere I bind events such as wx.EVT_TREEBOOK_NODE_EXPANDED to a handler that simply sends a resize event to the treebook, which works. But calling self.SendSizeEvent() at the end of the UpdateLabel method doesn't resize the tree control to reflect the edited text.

Any pointers appreciated. Thanks.

Duncan

###############################code##########################

import wx

import sys

class Treebook(wx.Treebook):
     def __init__(self, *args, **kwargs):
         wx.Treebook.__init__(self, *args, **kwargs)
         self.text = TextCtrl(self)
         self.text.Show(False)
         self.item = None

     def EditLabel(self, item):
         # allow label editing on Windows
         if sys.platform.startswith('win'):
             self._EditLabel(item)
         else:
             wx.Treebook.GetTreeControl().EditLabel(self, item)

     def _EditLabel(self, item):
         self.item = item
         tc = self.GetTreeCtrl()
         self.text.SetValue(tc.GetItemText(item))
         self.text.SetInsertionPointEnd()
         self.text.SetSelection(-1, -1)
         self.text.SetRect(tc.GetBoundingRect(item, textOnly=True))
         self.text.Show(True)
         self.text.SetFocus()

     def UpdateLabel(self, s):
         tc = self.GetTreeCtrl()
         if not tc.GetItemText(self.item) == s:
             tc.SetItemText(self.item, s)

class TextCtrl(wx.TextCtrl):
     def __init__(self, *args, **kwargs):
         wx.TextCtrl.__init__(self, *args, **kwargs)
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
         self.Bind(wx.EVT_KILL_FOCUS, self.UpdateParent)
         self.Bind(wx.EVT_TEXT_ENTER, self.UpdateParent)

     def OnKeyDown(self, event):
         keycode = event.GetKeyCode()
         if keycode == wx.WXK_ESCAPE:
             tb = self.GetParent()
             self.SetValue(tb.GetItemText(tb.item))
         event.Skip()

     def UpdateParent(self, event):
         self.GetParent().UpdateLabel(self.GetValue())
         self.HideAndMove()

     def HideAndMove(self):
         self.Show(False)
         self.SetPosition((0,0))
         self.SetSize((0,0))

[snip]

OK. Making the underlying TreeCtrl the parent of the TextCtrl solves 1. Still struggling with 2. though. Cheers.

Duncan

···

On 12/05/12 21:59, duncan smith wrote:

Unfortunately I've lost Robin's reply to this, but it helped. What I had
already started to implement as a solution is pasted below. I tried to
implement label editing by subclassing wx.Treebook and using a
wx.TextCtrl. It seems to work fairly well apart from two issues.

1. When editing, if I left click on the text control to place the
cursor, then I lose the control. i.e. I think the tree control is
processing the event and the text control is losing focus, triggering
its UpdateParent method. I could be wrong. I've tried a number of
things, but haven't been able to fix this.

2. After renaming (which works fine as long as I don't left click) I'd
like to resize the tree control. Elsewhere I bind events such as
wx.EVT_TREEBOOK_NODE_EXPANDED to a handler that simply sends a resize
event to the treebook, which works. But calling self.SendSizeEvent() at
the end of the UpdateLabel method doesn't resize the tree control to
reflect the edited text.

Hello,
       I have two wx applications, and want to be able to launch one from the other (in a separate process). For this I need to identify the path to one file from within the other file. Essentially I have something along the lines of the two files below.

################App1.py################

import wxversion

wxversion.ensureMinimal('2.8')

import wx

import App2 # solely to retrieve the file path

print App2.__file__

#################end###################

################App2.py################

import wxversion

wxversion.ensureMinimal('2.8')

import wx

#################end###################

This fails with a wxversion.AlreadyImportedError

I can obviously search for App2.py rather than importing it and using App2.__file__ to retrieve the path. But I was just wondering if there is a neater way of handling this. Replacing,

wxversion.ensureMinimal('2.8')

with

try:
     wxversion.ensureMinimal('2.8')
except wxversion.AlreadyImportedError:
     pass

in *both* files appears to do the trick. However, I am a bit confused as to why the exception is being raised in App1.py, rather than App2.py (or at all really). I'd appreciate any advice before I start using try ... except to allow the use of __file__. I imagine there are probably cases (different versions required) where it would be a bad idea. TIA.

Duncan

That's what I would do. Importing means that you are going to execute code, which means that the state of the importing application is going to change, even if the imported module doesn't really do anything significant. Personally I would rather keep them as separate as possible.

···

On 6/8/12 7:34 PM, duncan smith wrote:

Hello,
I have two wx applications, and want to be able to launch one from the
other (in a separate process). For this I need to identify the path to
one file from within the other file. Essentially I have something along
the lines of the two files below.

################App1.py################

import wxversion

wxversion.ensureMinimal('2.8')

import wx

import App2 # solely to retrieve the file path

print App2.__file__

#################end###################

################App2.py################

import wxversion

wxversion.ensureMinimal('2.8')

import wx

#################end###################

This fails with a wxversion.AlreadyImportedError

I can obviously search for App2.py rather than importing it and using
App2.__file__ to retrieve the path.

--
Robin Dunn
Software Craftsman

Not the way I’d do it but you could, in each app module, try:

if name == “main”:

import wxversion
wxversion.ensureMinimal(‘2.8’)
import wx

or:

if name <> “main”:

import sys

sys.exit(0)

or something like on windows:

find app2.py | python.exe app1.py

if you’re doing:

import app2

then very likely app2.py is in the PYTHONPATH environment variable;

and you might get away with doing something like:

found = [x for x in os.environ[‘PYTHONPATH’].split(os.pathsep) if “app2.py” in os.listdir(x)]

if not found:

found = [x for x in os.environ[‘PATH’].split(os.pathsep) if “app2.py” in os.listdir(x)]

Assuming that both App1 and App2 are packages you could do something
like having a file called AppLocation.py in each package that just
contains something along the lines of:
from sys.path import split """ Define a value AppPath that gives a path to this package """ (AppPath, _dummy) = split(__file__)
Then in each of your two apps you could do:

`from App*X*      .AppLocataion

import AppPath`

and take it from there, you could even construct the full

application path in there for neatness.

Gadget/Steve
···

On 11/06/2012 8:12 PM, Robin Dunn wrote:

  On

6/8/12 7:34 PM, duncan smith wrote:

    Hello,


    I have two wx applications, and want to be able to launch one

from the

    other (in a separate process). For this I need to identify the

path to

    one file from within the other file. Essentially I have

something along

    the lines of the two files below.




    ################App1.py################




    import wxversion




    wxversion.ensureMinimal('2.8')




    import wx




    import App2 # solely to retrieve the file path




    print App2.__file__




    #################end###################




    ################App2.py################




    import wxversion




    wxversion.ensureMinimal('2.8')




    import wx




    #################end###################






    This fails with a wxversion.AlreadyImportedError




    I can obviously search for App2.py rather than importing it and

using

    App2.__file__ to retrieve the path.
  That's what I would do.  Importing means that you are going to

execute code, which means that the state of the importing
application is going to change, even if the imported module
doesn’t really do anything significant. Personally I would rather
keep them as separate as possible.