WXPython 事件处理 - 按钮

WXPython Event Handling - Button

当我运行以下代码时,我收到了错误消息(附图)我有一个名为btn的按钮,当我将它添加到我的右侧面板时,我无法移动它的位置,有谁知道我该怎么做?另一个问题是,当我点击 左侧面板 上的 Big Script 时,我想调用那个特定的按钮,但是我不知道该怎么做,我试过了将按钮放在 OnSelChanged 方法上,但我无法使其工作。

整个代码都在下面,所以复制粘贴它更容易。

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()

最后一个问题是,除了文档之外,您是否知道任何资源可以更深入地了解这个库? (Youtube 视频、Udemy 等)

首先,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 并向下滚动到“额外文件”部分以找到演示。 至于你的按钮位置问题,在 wxpython 中控制事物位置的最好方法是使用 sizer。有关示例,请参见演示。

有几件事要提一下:
使用 sizer 时使用 position 语句是没有意义的,它将被忽略。

sizer 类型决定位置。您选择了垂直 boxsizer,因此所有内容都将垂直排列。您可以在添加小部件时使用对齐样式或选择不同的 sizer 类型,更符合您的要求。

我把按钮的回调函数移到了class里面。

按钮回调函数可以单独调用,如果你不依赖于事件值并且你发送一个虚拟事件参数,通常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()