文件列表小部件



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

否则,制作类似内容的最佳方法是什么。我可能可以将wxListBox划分为子类,并使用wxFileSystemWatcher来保持视图的同步,但这将是乏味的。有更好的方法吗?

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

正如Igor上面所说,考虑到您提出的要求,我认为除了使用wxFileSystemWatcher之外,没有其他方法可以做到这一点。

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

// 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. 如果要显示图标或元数据,列表控件可能比列表框更合适。列表控件还将允许对列表进行排序

最新更新