wxpython - 使用 treectrl 将本地 html 文件加载到面板中

wxpython - Using treectrl to load local html files into a panel

我试图在 wxPython 中制作一个帮助菜单,它在左侧有一个树控件,在右侧有一个 html 查看器; treecontrol 充当一种导航菜单,单击 treecontrol 中的项目时,相应的本地 .html 文件应加载到左侧面板中。

但是,当我尝试实现它时,我无法将任何事件绑定到树控件中的不同节点。这就是我目前所知道的 -- 谁能告诉我哪里出错了?

代码:

import wx
import wx.html


class HelpMenu(wx.Frame):
    def __init__(self, parent):
        tstr = "Need help?"
        super(HelpMenu, self).__init__(
            parent, -1, title=tstr, size=wx.Size(800, 500), style=wx.CAPTION |
            wx.CLOSE_BOX | wx.SYSTEM_MENU | wx.RESIZE_BORDER)

        splitter = wx.SplitterWindow(self)
        window1 = NavBar(splitter)
        window2 = htmlPanel(splitter)
        splitter.SplitVertically(window1, window2)
        splitter.SetSashGravity(0.5)
        # splitter.SetMinimumPaneSize(20)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.EXPAND)
        self.SetSizer(sizer)


class htmlPanel(wx.Panel):
    def __init__(self, parent):
        super(htmlPanel, self).__init__(parent)

        html = wx.html.HtmlWindow(self)
        if 'gtk2' in wx.PlatformInfo:
            html.SetStandardFonts()

        # htmlszr = wx.BoxSizer(wx.VERTICAL)
        # htmlszr.Add(html, 0, wx.EXPAND)
        html.LoadPage('.\index.html')
        # self.SetSizer(htmlszr)


class NavTree(wx.TreeCtrl):
    def __init__(self, parent, id, pos, size, style):
        super(NavTree, self).__init__(parent, id, pos, size, style)


class NavBar(wx.Panel):
    def __init__(self, parent):
        super(NavBar, self).__init__(parent)

        self.tree = NavTree(
            self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TR_HAS_BUTTONS)
        self.root = self.tree.AddRoot('Help Contents')
        self.welcome = self.tree.AppendItem(self.root, 'Start Page')
        self.background = self.tree.AppendItem(self.root, 'Background')
        self.method = self.tree.AppendItem(self.root, 'Calculation Method')
        self.using = self.tree.AppendItem(self.root, 'Using the Calculator')
        self.start = self.tree.AppendItem(self.using, 'Selecting Data Type')
        self.params = self.tree.AppendItem(self.using, 'Setting Parameters')
        self.results = self.tree.AppendItem(self.using, 'Viewing Results')
        self.interp = self.tree.AppendItem(self.root, 'Interpreting Results')
        # insert more children of interp here for various issues concerning
        # interpretation
        self.welcome.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._welcome)
        self.background.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._background)
        self.method.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._method)
        self.using.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._using)
        self.start.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._start)
        self.params.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._params)
        self.results.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._results)
        self.interp.Bind(wx.EVT_TREE_ITEM_ACTIVATE, self._interp)

        self.treeszr = wx.BoxSizer(wx.VERTICAL)
        self.treeszr.Add(self.tree, 0, wx.EXPAND)
        self.SetSizer(self.treeszr)

        def _welcome(self, event):
            htmlPanel.html.LoadPage('.\Help\index.html')

        def _background(self, event):
            htmlPanel.html.LoadPage('.\Help\background.html')

        def _method(self, event):
            htmlPanel.html.LoadPage('.\Help\method.html')

        def _using(self, event):
            htmlPanel.html.LoadPage('.\Help\use.html')

        def _start(self, event):
            htmlPanel.html.LoadPage('.\Help\start.html')

        def _params(self, event):
            htmlPanel.html.LoadPage('\Help\params.html')

        def _results(self, event):
            htmlPanel.html.LoadPage('\Help\results.html')

        def _interp(self, event):
            htmlPanel.html.LoadPage('\Help\interpretation.html')


if __name__ == "__main__":
    app = wx.App(False)
    frame = HelpMenu(None)
    frame.Show()
    app.MainLoop()

输出:

>>> Traceback (most recent call last):
  File "c:\Python\testing\splitterwindow.py", line 100, in <module>
    frame = HelpMenu(None)
  File "c:\Python\testing\splitterwindow.py", line 13, in
__init__
    window1 = NavBar(splitter)
  File "c:\Python\testing\splitterwindow.py", line 60, in __init__
    self.welcome.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._welcome)
AttributeError: 'TreeItemId' object has no attribute 'Bind'
>>> C:\Python\testing>

我暗暗怀疑 self.welcome 不是指节点本身,而是指其他东西,这就是错误的来源。我只是不太确定如何在 treecontrol 中引用实际的 node/text 以便能够将事件处理程序绑定到它。

编辑 Rolf 已经完成了 99% 的工作,除了这种奇怪的行为,其中只有根填充 -- none of the children .请参阅下面的屏幕截图。

这是您的代码模型,我已经对其进行了调整,以使用 treectrl 中的标签来决定要显示的内容。

import wx
import wx.html


class HelpMenu(wx.Frame):
    def __init__(self, parent):
        tstr = "Need help?"
        super(HelpMenu, self).__init__(
            parent, -1, title=tstr, size=wx.Size(800, 500), style=wx.CAPTION |
            wx.CLOSE_BOX | wx.SYSTEM_MENU | wx.RESIZE_BORDER)

        splitter = wx.SplitterWindow(self)
        window1 = NavBar(splitter)
        window2 = htmlPanel(splitter)
        splitter.SplitVertically(window1, window2)
        splitter.SetSashGravity(0.5)
        # splitter.SetMinimumPaneSize(20)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.EXPAND)
        self.SetSizer(sizer)
        self.Show()

class htmlPanel(wx.Panel):
    def __init__(self, parent):
        super(htmlPanel, self).__init__(parent)

        self.html = wx.html.HtmlWindow(self)
        if 'gtk2' in wx.PlatformInfo:
            self.html.SetStandardFonts()

        htmlszr = wx.BoxSizer(wx.VERTICAL)
        htmlszr.Add(self.html, 1, wx.EXPAND)
        self.html.LoadPage('index.html')
        self.SetSizer(htmlszr)


class NavTree(wx.TreeCtrl):
    def __init__(self, parent, id, pos, size, style):
        super(NavTree, self).__init__(parent, id, pos, size, style)


class NavBar(wx.Panel):
    def __init__(self, parent):
        super(NavBar, self).__init__(parent)
        self.tree = NavTree(
            self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TR_HAS_BUTTONS)
        self.parent = parent
        self.root = self.tree.AddRoot('Help Contents')
        self.welcome = self.tree.AppendItem(self.root, 'Start Page')
        self.background = self.tree.AppendItem(self.root, 'Background')
        self.method = self.tree.AppendItem(self.root, 'Calculation Method')
        self.using = self.tree.AppendItem(self.root, 'Using the Calculator')
        self.start = self.tree.AppendItem(self.using, 'Selecting Data Type')
        self.params = self.tree.AppendItem(self.using, 'Setting Parameters')
        self.results = self.tree.AppendItem(self.using, 'Viewing Results')
        self.interp = self.tree.AppendItem(self.root, 'Interpreting Results')
        # insert more children of interp here for various issues concerning
        # interpretation
        self.tree.ExpandAll()
        self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._click)

        self.treeszr = wx.BoxSizer(wx.VERTICAL)
        self.treeszr.Add(self.tree, 1, wx.EXPAND)
        self.SetSizer(self.treeszr)

    def _click(self, event):
        item = event.GetItem()
        label = self.tree.GetItemText(item)
        print(label)
        if label == 'Help Contents':
            self._welcome()
        elif label == 'Background':
            self._background()
        elif label == 'Calculation Method':
            self._method()
        elif label == 'Start Page':
            self._start()
        elif label == 'Selecting Data Type':
            self._using()
        elif label == 'Setting Parameters':
            self._params()                                            
        elif label == 'Viewing Results':
            self._results()        
        elif label == 'Interpreting Results':
            self._interp()

    def _welcome(self):
        self.parent.GetWindow2().html.LoadPage('index.html')

    def _background(self):
        self.parent.GetWindow2().html.LoadPage('background.html')

    def _method(self):
        self.parent.GetWindow2().html.LoadPage('method.html')

    def _using(self):
        self.parent.GetWindow2().html.LoadPage('use.html')

    def _start(self):
        self.parent.GetWindow2().html.LoadPage('index.html')

    def _params(self):
        self.parent.GetWindow2().html.LoadPage('params.html')

    def _results(self):
        self.parent.GetWindow2().html.LoadPage('results.html')

    def _interp(self):
        self.parent.GetWindow2().html.LoadPage('interp.html')

if __name__ == "__main__":
    app = wx.App(False)
    frame = HelpMenu(None)
    frame.Show()
    app.MainLoop()

这里是 NavBar class 的变体,使用 lists 作为文本和相关的 html 文件,仅使用索引位置进行链接。

class NavBar(wx.Panel):
    def __init__(self, parent):
        super(NavBar, self).__init__(parent)
        self.labs = ['Help Contents', 'Start Page', 'Background', 'Calculation Method', 'Using the Calculator',\
                     'Selecting Data Type', 'Setting Parameters', 'Viewing Results', 'Interpreting Results']
        self.pages = ['index.html','index.html','background.html','method.html',None,'use.html',\
                      'params.html','results.html','interp.html']
        self.tree = NavTree(
            self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TR_HAS_BUTTONS)
        self.parent = parent
        self.root = self.tree.AddRoot(self.labs[0])
        self.tree.AppendItem(self.root, self.labs[1])
        self.tree.AppendItem(self.root, self.labs[2])
        self.tree.AppendItem(self.root, self.labs[3])
        self.using = self.tree.AppendItem(self.root, self.labs[4])
        self.tree.AppendItem(self.using, self.labs[5])
        self.tree.AppendItem(self.using, self.labs[6])
        self.tree.AppendItem(self.using, self.labs[7])
        self.tree.AppendItem(self.root, self.labs[8])
        # insert more children of interp here for various issues concerning
        # interpretation
        self.tree.ExpandAll()
        self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._click)

        self.treeszr = wx.BoxSizer(wx.VERTICAL)
        self.treeszr.Add(self.tree, 1, wx.EXPAND)
        self.SetSizer(self.treeszr)

    def _click(self, event):
        item = event.GetItem()
        label = self.tree.GetItemText(item)
        if label:
            pass
        else:
            return
        index = self.labs.index(label)
        if self.pages[index]:
            self.parent.GetWindow2().html.LoadPage(self.pages[index])