I wanted to run the demo to see if the TreeCtrl widget is the right tool for a small project I have… but it fails running:
c:\wxPython-demo\demo>python demo.py
Traceback (most recent call last):
File "c:\wxPython-demo\demo\demo.py", line 3, in <module>
import Main
File "c:\wxPython-demo\demo\Main.py", line 59, in <module>
from distutils.version import LooseVersion
ModuleNotFoundError: No module named 'distutils'
c:\wxPython-demo\demo>pip install distutils
ERROR: Could not find a version that satisfies the requirement distutils (from versions: none)
ERROR: No matching distribution found for distutils
c:\wxPython-demo\demo>python --version
Python 3.12.0
c:\wxPython-demo\demo>python -c "import wx;print(wx.__version__)"
4.2.1
The project requires a “single-plane outliner” à la EccoPro. Is the TreeCtrl widget the right tool for this?
well, I’ve got a some Ecco shoes and the company is still going well (quality, I suppose, price accordingly), but EccoPro seems to have gone to the walls (for the demo see)
No harm done here. I was looking at how you addressed a OP, which also could be a new user(noob). I hope they are not offended and go elsewhere, because they spent their time and trouble to not only create an account, but to log in and post only to be greeted by a smart assed post. Sorry for the longest run on sentence ever written by a novice pressman.
>>> import distutils
<stdin>:1: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
As Main.py imports distutils, which is deprecated in python 3.12 a possible solution, as recommended in the PEP 632
import packaging instead and use that.
See: Version Handling - Packaging
>>> from distutils.version import LooseVersion
>>> import wx
>>> import version
>>> version.VERSION_STRING
'4.2.1'
>>> wx.VERSION_STRING
'4.2.1'
>>> if LooseVersion(version.VERSION_STRING) != LooseVersion(wx.VERSION_STRING):
... print("Wrong version")
... else:
... print("Correct version")
...
Correct version
>>>
>>> from packaging.version import Version
>>> Version(wx.VERSION_STRING)
<Version('4.2.1')>
>>> parse(wx.VERSION_STRING)
<Version('4.2.1')>
>>> str(Version(wx.VERSION_STRING))
'4.2.1'
>>> if str(version.VERSION_STRING) != str(Version(wx.VERSION_STRING)):
... print("Wrong version")
... else:
... print("Correct version")
...
Correct version
>>>
For your first question, I can run wxdemo 4.2.1 / Python 3.12 on Windows:
C:\usr\home>wxdemo
sys.version_info(major=3, minor=12, micro=1, releaselevel='final', serial=0) 3.12.1 (tags/v3.12.1:2305ca5, Dec 7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] ['C:\\Python312\\Scripts\\wxdemo.exe']
Launch Demo for wxPython V4.2.1
Looking for wxPython-demo-4.2.1 at C:\Users\omoto\AppData\Local\wxPython
Launching C:\Users\omoto\AppData\Local\wxPython\wxPython-demo-4.2.1\demo\demo.py
Demo starting as PID 15460 - may take a few seconds!
Closing Launcher App!
c:\wxPython-demo>dir /b
demo
README.txt
samples
c:\wxPython-demo>dir wxdemo*.* /s
Volume in drive C is Data
Volume Serial Number is D850-C463
File Not Found
If you installed wxPython from PyPI, you will find “wxdemo.exe” in the “Scripts” directory where python is installed (for example, “C:\Python312\Scripts\wxdemo.exe”).
I forgot to mention that. I usually add the directory to the environment variable PATH.
I never remember quite how different Windows can be to Unix.
I assumed that the wxpython demo would be the same and have the same structure.
Ah, well, never mind. The use of packaging.version probably still holds true, at least for Linux.
I guess if I see c:\ in a question, I should take that as a warning, that I should probably refrain from commenting and leave it to others.
The CustomTreeCtrl allows you to add horizontal separators between items. Below is a slightly modified version of the example in the documentation to demonstrate:
import wx
import wx.lib.agw.customtreectrl as CT
class MyFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent, -1, "CustomTreeCtrl Demo", size=(400, 600))
# Create a CustomTreeCtrl instance
custom_tree = CT.CustomTreeCtrl(self, agwStyle=wx.TR_DEFAULT_STYLE|wx.TR_MULTIPLE|CT.TR_AUTO_CHECK_CHILD|CT.TR_AUTO_CHECK_PARENT)
# Add a root node to it
root = custom_tree.AddRoot("The Root Item")
# Create an image list to add icons next to an item
il = wx.ImageList(16, 16)
fldridx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16)))
fldropenidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16, 16)))
fileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16, 16)))
custom_tree.SetImageList(il)
custom_tree.SetItemImage(root, fldridx, wx.TreeItemIcon_Normal)
custom_tree.SetItemImage(root, fldropenidx, wx.TreeItemIcon_Expanded)
for x in range(15):
child = custom_tree.AppendItem(root, "Item %d" % x)
custom_tree.SetItemImage(child, fldridx, wx.TreeItemIcon_Normal)
custom_tree.SetItemImage(child, fldropenidx, wx.TreeItemIcon_Expanded)
for y in range(5):
last = custom_tree.AppendItem(child, "item %d-%s" % (x, chr(ord("a")+y)), ct_type=1)
custom_tree.SetItem3State(last, True)
custom_tree.SetItemImage(last, fldridx, wx.TreeItemIcon_Normal)
custom_tree.SetItemImage(last, fldropenidx, wx.TreeItemIcon_Expanded)
for z in range(5):
# Set ct_type=1 to add a checkbox to the item
item = custom_tree.AppendItem(last, "item %d-%s-%d" % (x, chr(ord("a")+y), z), ct_type=1)
custom_tree.SetItemImage(item, fileidx, wx.TreeItemIcon_Normal)
custom_tree.AppendSeparator(root)
custom_tree.Expand(root)
if __name__ == '__main__':
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
You can use whatever images you like.
You simply have to load the wx.ImageList with your images.
In the case of RichardT’s example:
# Create an image list to add icons next to an item
b1 = wx.Bitmap('b1.png')
b2 = wx.Bitmap('b2.png')
b3 = wx.Bitmap('b3.png')
il = wx.ImageList(16, 16)
fldridx = il.Add(b1)
fldropenidx = il.Add(b2)
fileidx = il.Add(b3)
custom_tree.SetImageList(il)