首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >文件列表小部件

文件列表小部件
EN

Stack Overflow用户
提问于 2021-05-22 11:19:43
回答 1查看 128关注 0票数 1

我想要一个列表小部件,它是一个单一目录中的文件的平面视图。它应该是实时监测,理想情况下,我应该能够禁用它自己,暂时更新,如果有很多事情要在短时间内发生。是否有一个标准的小部件可以做到这一点?快速搜索会弹出wxGenericDirCtrl,但据我所知,它不可能只显示单个目录的文件(而不是目录)。与其说是一张单子,不如说是一棵树。

否则,做类似事情的最好方法是什么。我可能会将wxListBox子类化,并使用wxFileSystemWatcher来保持视图的同步,但这将是一件乏味的事情。有更好的办法吗?

我在Windows上;可移植性不是问题。我的目标是Windows 7到10。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-22 15:59:25

如前所述,鉴于您所述的要求,我认为除了使用wxFileSystemWatcher之外,还有其他方法可以做到这一点。

我收集了一个示例,说明如何根据文件系统观察者的报告来更新列表框。我不得不承认,这确实比我想象的要复杂得多,但我不认为这太乏味了。

代码语言:javascript
运行
复制
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include <wx/fswatcher.h>
#include <wx/filepicker.h>
#include <vector>

class MyFrame: public wxFrame
{
    public:
        MyFrame();
    private:
        // Event handlers
        void OnWatcher(wxFileSystemWatcherEvent& event);
        void OnDirChanged(wxFileDirPickerEvent& event);

        // Helper functions
        wxString StripPath(const wxString&);
        void DeleteFromListbox(const wxString&);

        wxFileSystemWatcher m_watcher;
        wxListBox* m_listBox;
};

MyFrame::MyFrame()
        :wxFrame(NULL, wxID_ANY, "Filesystem watcher frame", wxDefaultPosition,
                 wxSize(600, 400))
{
    // Set up the UI elements.
    wxPanel* mainPanel = new wxPanel(this,wxID_ANY);
    wxDirPickerCtrl* dirPicker = new wxDirPickerCtrl(mainPanel, wxID_ANY);
    m_listBox = new wxListBox(mainPanel, wxID_ANY);

    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    sizer->Add(dirPicker, wxSizerFlags(0).Expand().Border(wxALL));
    sizer->Add(m_listBox, wxSizerFlags(1).Expand().Border(wxALL&~wxTOP));

    mainPanel->SetSizer(sizer);
    Layout();

    // Set up the event handlers.
    m_watcher.SetOwner(this);
    dirPicker->Bind(wxEVT_DIRPICKER_CHANGED, &MyFrame::OnDirChanged, this);
    Bind(wxEVT_FSWATCHER, &MyFrame::OnWatcher, this);
}

void MyFrame::OnWatcher(wxFileSystemWatcherEvent& event)
{
    wxFileName name = event.GetPath();

    // Ignore all watch events for folders.
    if ( name.IsDir() )
    {
        return;
    }

    wxFileName newName = event.GetNewPath();
    int changeType = event.GetChangeType();

    switch ( changeType )
    {
        case wxFSW_EVENT_CREATE :
            m_listBox->Append( StripPath(name.GetFullPath()) );
            break;
        case wxFSW_EVENT_DELETE :
            DeleteFromListbox( StripPath(name.GetFullPath()) );
            break;
        case wxFSW_EVENT_RENAME :
            DeleteFromListbox( StripPath(name.GetFullPath()) );
            m_listBox->Append( StripPath(newName.GetFullPath()) );
            break;
        case wxFSW_EVENT_MODIFY :
            wxFALLTHROUGH;
        case wxFSW_EVENT_ACCESS :
            wxFALLTHROUGH;
        case wxFSW_EVENT_ATTRIB :
            wxFALLTHROUGH;
#ifndef __WINDOWS__
        case wxFSW_EVENT_UNMOUNT :
            wxFALLTHROUGH;
#endif // __WINDOWS__
        case wxFSW_EVENT_WARNING :
            wxFALLTHROUGH;
        case wxFSW_EVENT_ERROR  :
            wxFALLTHROUGH;
        default:
            break;
    }
}

void MyFrame::OnDirChanged(wxFileDirPickerEvent& event)
{
    if ( !::wxDirExists(event.GetPath()) )
    {
        return;
    }
    
    // Remove the current folder from the watch and add the new one.
    m_watcher.RemoveAll();

    wxString pathWithSep = event.GetPath();
    if ( pathWithSep.Right(1) != wxFileName::GetPathSeparator() )
    {
        pathWithSep << wxFileName::GetPathSeparator();
    }
    m_watcher.Add(wxFileName(pathWithSep));

    // Get a list of the files in new folder.
    std::vector<wxString> files;
    wxDir dir(pathWithSep);
    wxString curName;
    if ( dir.GetFirst(&curName, "*", wxDIR_FILES) )
    {
        files.push_back(StripPath(curName));
    }
    while ( dir.GetNext(&curName) )
    {
        files.push_back(StripPath(curName));
    }

    // Replace the current contents of the listbox with the new filenames.
    m_listBox->Clear();
    for ( auto it = files.begin() ; it != files.end() ; ++it )
    {
        m_listBox->Append(*it);
    }
}

wxString MyFrame::StripPath(const wxString& name)
{
    wxFileName fn(name);
    return fn.GetFullName();
}

void MyFrame::DeleteFromListbox(const wxString& name)
{
    int index = m_listBox->FindString(name);
    if ( index != wxNOT_FOUND )
    {
        m_listBox->Delete(static_cast<unsigned int>(index));
    }
}

class MyApp : public wxApp
{
    public:
        virtual bool OnInit()
        {
            MyFrame* frame = new MyFrame();
            frame->Show();
            return true;
        }
};

wxIMPLEMENT_APP(MyApp);

这只是一个简单的例子。还有一些改进的余地:

  1. 我不知道如果在枚举过程中对文件夹中的文件进行更改会发生什么。如果这是一个问题,我想您可以在枚举期间收集监视事件,然后在枚举完成后解决这些事件。如果被枚举的文件夹可以包含多个文件,则最好在辅助线程中进行枚举,如果要显示图标或元数据,则
  2. 可能比列表框更适合进行枚举。列表控件还将允许对列表进行排序。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67648890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档