geekdoc-python-zh/docs/pythonlibrary/wxpython-objectlistview-dou...

6.9 KiB
Raw Permalink Blame History

wxPython: ObjectListview -如何双击项目

原文:https://www.blog.pythonlibrary.org/2013/12/12/wxpython-objectlistview-double-click-items/

前几天我在做一个项目,在这个项目中我使用了精彩的 ObjectListView 小部件(wx 的包装器)。我想添加双击控件中的一个项目来打开 PDF 的功能。我知道我在网上的某个地方读到过如何做这类事情,但是再一次发现这些信息是一种拖累。所以现在知道了,这次决定分享一下。作为奖励,我还将向您展示如何在 Windows 上打开 PDF 文件!

深入研究代码

wxOLVDoubleclick

使用 ObjectListView 小部件非常容易。我在过去谈论过它,所以如果你愿意,你可以去看看那些以前的文章,我会在这篇文章的结尾链接到它们。无论如何,我总是发现显示代码然后解释发生了什么更容易,所以让我们在这里也这样做:


import glob
import os
import subprocess
import wx

from ObjectListView import ObjectListView, ColumnDefn

########################################################################
class File(object):
    """
    Model of the file object
    """

    #----------------------------------------------------------------------
    def __init__(self, path):
        """Constructor"""
        self.filename = os.path.basename(path)
        self.path = path

########################################################################
class UIPanel(wx.Panel):
    """
    Panel class
    """

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.base_path = os.path.dirname(os.path.abspath(__file__))
        self.data = []

        # -----------------------------------------------
        # create the widgets

        # add the data viewing control
        self.pdfOlv = ObjectListView(self, 
                                     style=wx.LC_REPORT|wx.SUNKEN_BORDER)
        self.pdfOlv.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.onDoubleClick)
        self.pdfOlv.SetEmptyListMsg("No PDFs Found!")
        self.updateDisplay()

        browseBtn = wx.Button(self, label="Browse")
        browseBtn.Bind(wx.EVT_BUTTON, self.getPdfs)

        # -----------------------------------------------
        # layout the widgets
        mainSizer = wx.BoxSizer(wx.VERTICAL)

        mainSizer.Add(self.pdfOlv, 1, wx.ALL|wx.EXPAND, 5)
        mainSizer.Add(browseBtn, 0, wx.ALL|wx.CENTER, 5)

        self.SetSizer(mainSizer)

    #----------------------------------------------------------------------
    def getPdfs(self, event):
        """
        Attempts to load PDFs into objectlistview
        """
        self.data = []

        dlg = wx.DirDialog(self, "Choose a directory:",
                          style=wx.DD_DEFAULT_STYLE)
        res = dlg.ShowModal()
        if res != wx.ID_OK:
            return
        path = dlg.GetPath()
        dlg.Destroy()

        pdfs = glob.glob(path + "/*.pdf")

        if pdfs:
            for pdf in pdfs:
                self.data.append(File(pdf))

            self.updateDisplay()

    #----------------------------------------------------------------------
    def onDoubleClick(self, event):
        """
        Opens the PDF that is double-clicked
        """
        obj = self.pdfOlv.GetSelectedObject()
        print "You just double-clicked on %s" % obj.path
        cmd = os.getenv("comspec")
        acrobat = "acrord32.exe"
        pdf = obj.path

        cmds = [cmd, "/c", "start", acrobat, "/s", pdf]
        subprocess.Popen(cmds)

    #----------------------------------------------------------------------
    def updateDisplay(self):
        """
        Updates the object list view control
        """
        self.pdfOlv.SetColumns([
            ColumnDefn("File", "left", 700, "filename")
            ])
        self.pdfOlv.SetObjects(self.data)

########################################################################
class MainFrame(wx.Frame):
    """
    Main frame
    """

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="DoubleClick OLV Demo",
                          size=(800,600))
        panel = UIPanel(self)
        self.createMenu()
        self.Show()

    #----------------------------------------------------------------------
    def createMenu(self):
        """
        Create the menus
        """
        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        closeMenuItem = fileMenu.Append(wx.NewId(), "Close",
                                        "Close the application")
        self.Bind(wx.EVT_MENU, self.onClose, closeMenuItem)

        menubar.Append(fileMenu, "&File")
        self.SetMenuBar(menubar)

    #----------------------------------------------------------------------
    def onClose(self, event):
        """
        Close the application
        """
        self.Close()

#----------------------------------------------------------------------
def main():
    """
    Run the application
    """
    app = wx.App(False)
    frame = MainFrame()
    app.MainLoop()

#----------------------------------------------------------------------
if __name__ == "__main__":
    main()

ObjectListView (OLV)小部件可以处理对象和字典。在这个例子中,我们创建了一个文件类,它将被提供给我们的 OLV 小部件。然后在 panel 类中,我们创建了带有浏览按钮的 OLV 小部件。为了获得双击效果,我们将 OLV 小部件绑定到 wx。EVT _ 列表 _ 项目 _ 激活。这不是一个非常直观的命名事件,但它确实可以捕捉双击。要实际使用这个脚本,您需要浏览到一个包含 pdf 的文件夹。一旦选择了文件夹,就会调用get pdf方法。

在所述方法中,我们使用 Python 的 glob 模块来查找 pdf。如果它返回一些那么我们通过向它附加 File 类的实例来更新我们的数据列表。现在你应该有了类似于你在文章开头看到的截图的东西。现在,当你双击项目时,它会打印出 PDF 的路径,然后尝试使用 Python 的 os 模块获取窗口的cmd.exe路径。然后,它将尝试使用 Python 的子进程模块调用带有几个标志和 PDF 路径的 Adobe Acrobat Reader 32 位版本。如果每个人都正常工作,您应该看到 Acrobat 加载了您选择的 PDF。

注意:当双击事件处理程序触发时,我收到一个 wxPyDeprecationWarning。我不完全确定为什么会发生这种情况因为它谈论的是关键事件但我只是认为我的读者应该知道他们可以忽略这一点因为我不认为这将对他们产生任何影响。

我在 Windows 7 上使用 ObjectListView 1.2、wxPython 2.9.4.0(经典)和 Python 2.7.3 测试了这段代码。