Reputation: 23
When I'm running the following code, I received the error (image attached) I have a button called btn
and when I add it to my right panel I cannot move its position, does anyone knows how can I do that? And another issue is that I'd like to call that specific button when I click on Big Script
on the left panel, however I have no clue how to do this, I tried to put the button on the OnSelChanged
method but I wasn't able to make it work.
The whole code is down below so it's easier to copy-paste it.
import wx
from wx.core import Font, Position, Size
import wx.lib.newevent
from wx.lib.agw.customtreectrl import CustomTreeCtrl
def onButton(event):
print("Button Pressed")
#---------------------------------------------------------------------------
class MyTree(wx.TreeCtrl):
"""
Our customized TreeCtrl class.
"""
def __init__(self, parent, id, position, size, style):
"""
Initialize our tree.
"""
wx.TreeCtrl.__init__(self, parent, id, position, size, style)
root = self.AddRoot('Programmer')
os = self.AppendItem(root, '🧙 Big Script')
pl = self.AppendItem(root, '📊 Big Script2')
tk = self.AppendItem(root, 'Big Script3')
cl = self.AppendItem(pl, 'Random Scripts')
sl = self.AppendItem(pl, 'Miscelanious')
self.AppendItem(os, 'Script1')
self.AppendItem(os, 'Script2')
self.AppendItem(os, 'Script3')
self.AppendItem(os, 'Script4')
self.AppendItem(cl, 'Script1')
self.AppendItem(cl, 'Script2')
self.AppendItem(cl, 'Script3')
self.AppendItem(sl, '1')
self.AppendItem(sl, '2')
self.AppendItem(sl, '3')
self.AppendItem(sl, '4')
self.AppendItem(tk, 'Script1')
self.AppendItem(tk, 'Script2')
self.AppendItem(tk, 'Script3')
self.AppendItem(tk, 'Script4+')
self.AppendItem(tk, 'Script5')
#---------------------------------------------------------------------------
class MyFrame(wx.Frame):
"""
Our customized window class.
"""
def __init__(self, parent, id, title):
"""
Initialize our window.
"""
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(800, 600))
#self.SetIcon(wx.Icon('./icons/wxwin.ico', wx.BITMAP_TYPE_ICO))
#------------
# Create a splitter window.
self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE)
# Create the left panel.
leftPanel = wx.Panel(self.splitter, -1)
# Create our tree and put it into the left panel.
self.tree = MyTree(leftPanel, 1,
wx.DefaultPosition,
wx.DefaultSize,
wx.TR_HIDE_ROOT |
wx.TR_HAS_BUTTONS)
self.tree.SetBackgroundColour('#3DB2FF')
# Bind the OnSelChanged method to the tree.
self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1)
# Create the right panel.
rightPanel = wx.Panel(self.splitter, -1, style=wx.SUNKEN_BORDER)
rightPanel.SetBackgroundColour('#79B4B7')
# Create a widget to display static text
# and store it in the right panel.
self.display = wx.StaticText(rightPanel, -1, '', style=wx.ALIGN_CENTER)
#item = self.display.SetLabel(self.tree.GetItemText())
#print(item)
# Put the left and right panes into the split window.
self.splitter.SplitVertically(leftPanel, rightPanel, 200)
# Minimum size of subwindow.
self.splitter.SetMinimumPaneSize(1)
#------------
# Create a box sizer that will contain the left panel contents.
leftBox = wx.BoxSizer(wx.VERTICAL)
# Add the tree to the box sizer.
leftBox.Add(self.tree, 1, wx.EXPAND)
# Set the size of the right panel to that required by the tree.
leftPanel.SetSizer(leftBox)
# Create the right box sizer that will contain the panel's contents.
rightBox = wx.BoxSizer(wx.VERTICAL)
# Add the display widget to the right panel.
rightBox.Add(self.display, 0, wx.ALL, 1)
self.button = wx.Button(rightPanel, wx.ID_ANY, 'Test', pos=(225, 2000))
rightBox.Add(self.button)
self.button.Bind(wx.EVT_BUTTON, onButton)
print(self.button.GetScreenPosition())
# Set the size of the right panel to that
# required by the display widget.
rightPanel.SetSizer(rightBox)
#------------
# Create the window in the centre of the screen.
self.Centre()
#-----------------------------------------------------------------------
def OnSelChanged(self, event):
"""
Method called when selected item is changed.
"""
# Get the selected item object.
item = event.GetItem()
overview = """
This demo simply catches all key events and prints info about them.
It is meant to be used as a compatibility test for cross platform work.
"""
# Display the selected item text in the text widget.
if self.tree.GetItemText(item) == '🧙 Big Script':
self.display.SetLabel(f"{self.tree.GetItemText(item)}\n {overview}")
else:
self.display.SetLabel(self.tree.GetItemText(item))
return item
#print(self.tree.GetItemText(item))
#---------------------------------------------------------------------------
class MyApp(wx.App):
"""
Our application class.
"""
def OnInit(self):
"""
Initialize by creating the split window with the tree.
"""
frame = MyFrame(None, -1, 'Test1')
frame.Show(True)
self.SetTopWindow(frame)
return True
#---------------------------------------------------------------------------
if __name__ == '__main__':
app = MyApp(0)
app.MainLoop()
One last question would be, do you know any resources other than the documentation to understand more in depth about this library? (Youtube videos, Udemy, etc)
Upvotes: 0
Views: 551
Reputation: 22443
A few things to mention:
Using a position
statement when using a sizer is pointless, it will be ignored.
The sizer
type determines placement. You have chosen a vertical boxsizer, so everything will be arranged vertically. You can use an alignment style when adding a widget or choose a different sizer type, more befitting your requirements.
I've moved the callback function of the button inside the class.
The button callback function can be called separately, if you are not depending on the event values and you send a dummy event parameter, usually None
import wx
from wx.core import Font, Position, Size
import wx.lib.newevent
from wx.lib.agw.customtreectrl import CustomTreeCtrl
#---------------------------------------------------------------------------
class MyTree(wx.TreeCtrl):
"""
Our customized TreeCtrl class.
"""
def __init__(self, parent, id, position, size, style):
"""
Initialize our tree.
"""
wx.TreeCtrl.__init__(self, parent, id, position, size, style)
root = self.AddRoot('Programmer')
os = self.AppendItem(root, '🧙 Big Script')
pl = self.AppendItem(root, '📊 Big Script2')
tk = self.AppendItem(root, 'Big Script3')
cl = self.AppendItem(pl, 'Random Scripts')
sl = self.AppendItem(pl, 'Miscelanious')
self.AppendItem(os, 'Script1')
self.AppendItem(os, 'Script2')
self.AppendItem(os, 'Script3')
self.AppendItem(os, 'Script4')
self.AppendItem(cl, 'Script1')
self.AppendItem(cl, 'Script2')
self.AppendItem(cl, 'Script3')
self.AppendItem(sl, '1')
self.AppendItem(sl, '2')
self.AppendItem(sl, '3')
self.AppendItem(sl, '4')
self.AppendItem(tk, 'Script1')
self.AppendItem(tk, 'Script2')
self.AppendItem(tk, 'Script3')
self.AppendItem(tk, 'Script4+')
self.AppendItem(tk, 'Script5')
#---------------------------------------------------------------------------
class MyFrame(wx.Frame):
"""
Our customized window class.
"""
def __init__(self, parent, id, title):
"""
Initialize our window.
"""
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(800, 600))
#self.SetIcon(wx.Icon('./icons/wxwin.ico', wx.BITMAP_TYPE_ICO))
#------------
# Create a splitter window.
self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE)
# Create the left panel.
leftPanel = wx.Panel(self.splitter, -1)
# Create our tree and put it into the left panel.
self.tree = MyTree(leftPanel, 1,
wx.DefaultPosition,
wx.DefaultSize,
wx.TR_HIDE_ROOT |
wx.TR_HAS_BUTTONS)
self.tree.SetBackgroundColour('#3DB2FF')
# Bind the OnSelChanged method to the tree.
self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1)
# Create the right panel.
rightPanel = wx.Panel(self.splitter, -1, style=wx.SUNKEN_BORDER)
rightPanel.SetBackgroundColour('#79B4B7')
# Create a widget to display static text
# and store it in the right panel.
self.display = wx.StaticText(rightPanel, -1, '', style=wx.ALIGN_CENTER)
#item = self.display.SetLabel(self.tree.GetItemText())
#print(item)
# Put the left and right panes into the split window.
self.splitter.SplitVertically(leftPanel, rightPanel, 200)
# Minimum size of subwindow.
self.splitter.SetMinimumPaneSize(1)
#------------
# Create a box sizer that will contain the left panel contents.
leftBox = wx.BoxSizer(wx.VERTICAL)
# Add the tree to the box sizer.
leftBox.Add(self.tree, 1, wx.EXPAND)
# Set the size of the right panel to that required by the tree.
leftPanel.SetSizer(leftBox)
# Create the right box sizer that will contain the panel's contents.
rightBox = wx.BoxSizer(wx.VERTICAL)
# Add the display widget to the right panel.
rightBox.Add(self.display, 0, wx.ALL, 1)
#self.button = wx.Button(rightPanel, wx.ID_ANY, 'Test', pos=(225, 2000))
# You're using a Sizer to arrange the contents of rightPanel so "position" is meaningless
self.button = wx.Button(rightPanel, wx.ID_ANY, 'Test')
# Use an alignment parameter or choose a sizer other than a boxsizer
rightBox.Add(self.button,0,wx.ALIGN_RIGHT|wx.ALL, 20)
self.button.Bind(wx.EVT_BUTTON, self.onButton)
# Set the size of the right panel to that
# required by the display widget.
rightPanel.SetSizer(rightBox)
#------------
# Create the window in the centre of the screen.
self.Centre()
#-----------------------------------------------------------------------
def onButton(self, event):
print("Button Pressed")
def OnSelChanged(self, event):
"""
Method called when selected item is changed.
"""
# Get the selected item object.
item = event.GetItem()
overview = """
This demo simply catches all key events and prints info about them.
It is meant to be used as a compatibility test for cross platform work.
"""
# Display the selected item text in the text widget.
if self.tree.GetItemText(item) == '🧙 Big Script':
self.display.SetLabel(f"{self.tree.GetItemText(item)}\n {overview}")
# We can call the event function, as long as we set a value of something for the event parameter
self.onButton(None)
else:
self.display.SetLabel(self.tree.GetItemText(item))
#---------------------------------------------------------------------------
class MyApp(wx.App):
"""
Our application class.
"""
def OnInit(self):
"""
Initialize by creating the split window with the tree.
"""
frame = MyFrame(None, -1, 'Test1')
frame.Show(True)
self.SetTopWindow(frame)
return True
#---------------------------------------------------------------------------
if __name__ == '__main__':
app = MyApp()
app.MainLoop()
Upvotes: 1
Reputation: 276
First, there's www.wxpython.org. Then there's discuss.wxpython.org. But the real way to learn is to find the demo for your platform, which has easy to navigate examples with code you can steal. Go to www.wxpython.org and scroll down to the "extra files" section to find the demo. As to your button position question, the best way to control the positions of things in wxpython is to use sizers. See the demo for examples.
Upvotes: 1