A wxListCtrl with 300 items will fill under wxWidgets 3.2.3 within 2 seconds, and under wxWidgets 3.3.0 it takes about a minute.
Platform: Windows 11-64 Intel Darkmode
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I cannot reproduce this (tried the default LC_LIST as well as LC_REPORT, with 500 items) either in the listctrl sample (can you?) or with a simple minimal application such as this
#include <wx/wx.h> #include <wx/listctrl.h> class MyFrame : public wxFrame { public: MyFrame(bool isReport, wxWindow* parent = nullptr) : wxFrame(parent, wxID_ANY, "Test") { const long itemCount = 300; int flags = 0; if ( isReport ) flags |= wxLC_REPORT; else flags |= wxLC_LIST; wxListCtrl* listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, flags); if ( isReport ) { listCtrl->AppendColumn("Item"); listCtrl->AppendColumn("SubItem 1"); listCtrl->AppendColumn("SubItem 2"); for ( long i = 0; i < itemCount; ++i ) { listCtrl->InsertItem(i, wxString::Format("Item %ld", i)); listCtrl->SetItem(i, 1, wxString::Format("SubItem 1 %ld", i)); listCtrl->SetItem(i, 2, wxString::Format("SubItem 2 %ld", i)); } } else { for ( long i = 0; i < itemCount; ++i ) listCtrl->InsertItem(i, wxString::Format("Item %ld", i)); } } }; class MyApp : public wxApp { public: bool OnInit() override { const bool isReport = wxMessageBox("Create wxListCtrl in report mode?", "wxListCtrl mode", wxYES_NO) == wxYES; (new MyFrame(isReport))->Show(); return true; } }; wxIMPLEMENT_APP(MyApp);
Unfortunately, you did not provide any information that could be helpful to reproduce the issue. For example, the styles used to create the control, the number of columns it has (if in report mode), whether images are used, how exactly do you add the items, does Windows being in the light mode make a difference, or other circumstances (e.g., wxNotebook or wxGLCanvas in the same top level window as your wxListCtrl).
IMO, adding 300 items taking a noticeable time already in 3.2 indicates that you are not doing something simple, IME, this should be practically instantaneous.
I tested with:
wxWidgets current master (8fc73d4) built with MSVC 2022 v17.7.6 as 64-bit Debug DLL
Windows 10 22H2 build 19045.3570 dark mode (Ryzen 5 2600 3.4 GHz, 48 GB RAM)
Windows 11 22H2 build 22621.2428 dark mode (i7 8850H 2.6 GHz, 32 GB RAM)
Relevant system variables: wx_msw_dark_mode set to 1, wx_msw_window_no_composited not set
BTW, scrolling the report list down in dark mode on Windows 11 in the listctrl sample often produces serious visual artifact. This probably requires its own Issue but I do not have time to look into it at the moment.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Actually, using a more complex test, I can observe a difference between dark and light mode on Windows 10 when using the master, with wxListCtrl in wxLC_REPORT mode. The list control has 500 items and 10 columns, filling it takes about 0.5 s in light mode but over 6 s in dark mode. IIRC, in dark mode, the list control content is custom drawn by wxWidgets?
#include <wx/wx.h> #include <wx/listctrl.h> #include <wx/stopwatch.h> #include <wx/wupdlock.h>
class MyFrame : public wxFrame { public: MyFrame(bool isReport, wxWindow* parent = nullptr) : wxFrame(parent, wxID_ANY, "Test"
)
{
m_mainPanel = new wxPanel(this);
wxBoxSizer* mainPanelSizer = new wxBoxSizer(wxVERTICAL);
int flags = 0; if ( isReport ) flags |= wxLC_REPORT; else
flags |= wxLC_LIST;
m_listCtrl = new wxListCtrl(m_mainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, flags);
mainPanelSizer->Add(m_listCtrl, wxSizerFlags().Proportion(4).Expand().Border());
wxTextCtrl* logCtrl = new wxTextCtrl(m_mainPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));
mainPanelSizer->Add(logCtrl, wxSizerFlags().Proportion(1).Expand().Border());
m_addListItemsTimer.Bind(wxEVT_TIMER, [this](wxTimerEvent&) {AddListItems();} );
m_addListItemsTimer.StartOnce(500);
SetSize(FromDIP(wxSize(1024, 800)));
m_mainPanel->SetSizer(mainPanelSizer);
}
private:
wxTimer m_addListItemsTimer;
wxPanel* m_mainPanel;
wxListCtrl* m_listCtrl;
void AddListItems()
{
const long itemCount = 500;
const bool isReport = m_listCtrl->GetWindowStyleFlag() & wxLC_REPORT;
wxStopWatch stopWatch;
wxLogMessage("Adding items...");
stopWatch.Start();
if ( isReport )
{
const long subItemCount = 9;
m_listCtrl->AppendColumn("Item");
for ( long i = 1; i <= subItemCount; ++i )
m_listCtrl->AppendColumn(wxString::Format("SubItem %ld", i));
#if 0
wxWindowUpdateLocker lock(this);
#endif
for ( long i = 0; i < itemCount; ++i )
{
long idx = m_listCtrl->InsertItem(i, wxString::Format("Item %ld", i));
for ( long j = 1; j <= subItemCount; ++j )
m_listCtrl->SetItem(idx, j, wxString::Format("SubItem %ld %ld", j, i));
}
m_listCtrl->SetColumnWidth(0, wxLIST_AUTOSIZE);
for ( long i = 1; i <= subItemCount; ++i )
m_listCtrl->SetColumnWidth(i, wxLIST_AUTOSIZE);
}
else { for ( long i = 0
; i < itemCount; ++i )
m_listCtrl->InsertItem(i, wxString::Format("Item %ld", i));
}
m_mainPanel->Layout();
wxLogMessage("Adding %ld items took %ld ms", itemCount, stopWatch.Time());
}
};
class MyApp : public wxApp
{
bool OnInit() override { const bool isReport = wxMessageBox("Create wxListCtrl in report mode?", "wxListCtrl mode", wxYES_NO) == wxYES; (new MyFrame(isReport))->Show(); return true; } }; wxIMPLEMENT_APP(MyApp);
Using wxWindowUpdateLocker when adding items shaves off about 1.5 s, so while using wxWindowUpdateLocker brings a significant improvement, the difference between dark and light modes is still VERY observable...
I did not test on Windows 11.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Two options I use: Report and SingleSel.
`
void BaseDialog::fillIndex( iONode Items, const char* itemtype, bool sort, const char* find) {
if(m_ItemList == NULL || Items == NULL)
return;
m_ItemType = itemtype;
m_Items = Items;
m_ItemList->Freeze();
m_ItemList->DeleteAllItems();
iOList sortlist = ListOp.inst();
int size = NodeOp.getChildCnt(Items);
for( int index = 0; index < size; index++ ) {
iONode Item = NodeOp.getChild( Items, index );
if( wItem.getid(Item) != NULL ) {
if( m_ItemType != NULL && !StrOp.equals(m_ItemType, NodeOp.getName(Item)) )
continue;
if( find != NULL && StrOp.len(find) > 0 ) {
if( StrOp.find(wItem.getid(Item), find) == NULL && StrOp.find(wItem.getdesc(Item), find) == NULL )
continue;
}
ListOp.add(sortlist, (obj)Item);
}
}
bool initSortOrder = false;
if( m_SortOrder > 0 ) {
ms_SortOrder = m_SortOrder==1?true:false;
m_SortOrder = 0;
initSortOrder = true;
}
if( m_SortCol == m_colID ) {
if( !initSortOrder ) {
if(sort) m_sortID = !m_sortID;
ms_SortOrder = m_sortID;
}
ListOp.sort(sortlist, &__sortID);
}
else {
ListOp.sort(sortlist, &__sortID);
}
if( m_SortCol == m_colIID ) {
if( !initSortOrder ) {
if(sort) m_sortIID = !m_sortIID;
ms_SortOrder = m_sortIID;
}
ListOp.sort(sortlist, &__sortIID);
}
else if( m_SortCol == m_colAddr ) {
if( !initSortOrder ) {
if(sort) m_sortAddr = !m_sortAddr;
ms_SortOrder = m_sortAddr;
}
ListOp.sort(sortlist, &__sortAddr);
}
else if( m_SortCol == m_colDesc ) {
if( !initSortOrder ) {
if(sort) m_sortDesc = !m_sortDesc;
ms_SortOrder = m_sortDesc;
}
ListOp.sort(sortlist, &__sortDesc);
}
else if( m_SortCol == m_colShow ) {
if( !initSortOrder ) {
if(sort) m_sortShow = !m_sortShow;
ms_SortOrder = m_sortShow;
}
ListOp.sort(sortlist, &__sortShow);
}
else if( m_SortCol == m_colPos ) {
if( !initSortOrder ) {
if(sort) m_sortPos = !m_sortPos;
ms_SortOrder = m_sortPos;
}
ListOp.sort(sortlist, &__sortPos);
}
else if( m_SortCol == m_colOri ) {
if( !initSortOrder ) {
if(sort) m_sortOri = !m_sortOri;
ms_SortOrder = m_sortOri;
}
ListOp.sort(sortlist, &__sortOri);
}
else if( m_SortCol == m_colLen ) {
if( !initSortOrder ) {
if(sort) m_sortLen = !m_sortLen;
ms_SortOrder = m_sortLen;
}
ListOp.sort(sortlist, &__sortLen);
}
else if( m_SortCol == m_colType ) {
if( !initSortOrder ) {
if(sort) m_sortType = !m_sortType;
ms_SortOrder = m_sortType;
}
ListOp.sort(sortlist, &__sortType);
}
else if( m_SortCol == m_colRTime ) {
if( !initSortOrder ) {
if(sort) m_sortRTime = !m_sortRTime;
ms_SortOrder = m_sortRTime;
}
ListOp.sort(sortlist, &__sortRTime);
}
else if( m_SortCol == m_colRDate ) {
if( !initSortOrder ) {
if(sort) m_sortRDate = !m_sortRDate;
ms_SortOrder = m_sortRDate;
}
ListOp.sort(sortlist, &__sortRDate);
}
else if( m_SortCol == m_colMTime ) {
if( !initSortOrder ) {
if(sort) m_sortMTime = !m_sortMTime;
ms_SortOrder = m_sortMTime;
}
ListOp.sort(sortlist, &__sortMTime);
}
else if( m_SortCol == m_colMDate ) {
if( !initSortOrder ) {
if(sort) m_sortMDate = !m_sortMDate;
ms_SortOrder = m_sortMDate;
}
ListOp.sort(sortlist, &__sortMDate);
}
else if( m_SortCol == m_colHome ) {
if( !initSortOrder ) {
if(sort) m_sortHome = !m_sortHome;
ms_SortOrder = m_sortHome;
}
ListOp.sort(sortlist, &__sortHome);
}
else if( m_SortCol == m_colSchedule ) {
if( !initSortOrder ) {
if(sort) m_sortSchedule = !m_sortSchedule;
ms_SortOrder = m_sortSchedule;
}
ListOp.sort(sortlist, &__sortSchedule);
}
else if( m_SortCol == m_colTour ) {
if( !initSortOrder ) {
if(sort) m_sortTour = !m_sortTour;
ms_SortOrder = m_sortTour;
}
ListOp.sort(sortlist, &__sortTour);
}
else if( m_SortCol == m_colFrom ) {
if( !initSortOrder ) {
if(sort) m_sortFrom = !m_sortFrom;
ms_SortOrder = m_sortFrom;
}
ListOp.sort(sortlist, &__sortFrom);
}
else if( m_SortCol == m_colTo ) {
if( !initSortOrder ) {
if(sort) m_sortTo = !m_sortTo;
ms_SortOrder = m_sortTo;
}
ListOp.sort(sortlist, &__sortTo);
}
else if( m_SortCol == m_colCrossing ) {
if( !initSortOrder ) {
if(sort) m_sortCrossing = !m_sortCrossing;
ms_SortOrder = m_sortCrossing;
}
ListOp.sort(sortlist, &__sortCrossing);
}
else if( m_SortCol == m_colState ) {
if( !initSortOrder ) {
if(sort) m_sortState = !m_sortState;
ms_SortOrder = m_sortState;
}
ListOp.sort(sortlist, &__sortState);
}
size = ListOp.size( sortlist );
for( int i = 0; i < size; i++ ) {
iONode Item = (iONode)ListOp.get( sortlist, i );
if( i + 1 == size )
appendItem(Item, true);
else
appendItem(Item, false);
}
m_ItemList->Thaw();
/* clean up the temp. list */
ListOp.base.del(sortlist);
}
void BaseDialog::appendItem( iONode Item, bool adjustColumnWidth) {
if(m_ItemList == NULL)
return;
m_ItemList->Freeze();
int index = m_ItemList->GetItemCount();
m_ItemList->InsertItem( index, wxString( wItem.getid(Item), wxConvUTF8));
bool isAutoGen = wItem.isautogen(Item) | wItem.isgenerated(Item);
if( !AddrOp.isIDvalid( wItem.getid(Item), TRCLEVEL_INFO ) ) {
//m_ItemList->SetItemBackgroundColour(index, Base::getRed2());
}
int genRGB = wGui.getgenRGB(wxGetApp().getIni());
if( isAutoGen && genRGB > 0 ) {
wxColour genColor( (unsigned long)genRGB );
//m_ItemList->SetItemBackgroundColour(index, Base::getDarkGrey2());
m_ItemList->SetItemTextColour(index, genColor );
isAutoGen = false;
}
if( m_ShowAddr ) {
m_ItemList->SetItem( index, m_colIID, wxString( wItem.getiid(Item), wxConvUTF8));
m_ItemList->SetItem( index, m_colAddr, __getAddrStr(Item, &m_longaddr));
m_ItemList->SetColumnWidth(m_colIID, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colAddr, wxLIST_AUTOSIZE);
}
bool isUsed = wItem.isused(Item);
if( StrOp.equals( NodeOp.getName(Item), wSwitch.name() ) )
m_ItemList->SetItem( index, m_colDesc, wxString( wItem.getdesc(Item), wxConvUTF8) + wxT("(") + wxString::Format( wxT("%d"), wSwitch.getswitched(Item)) + wxT(")") );
else if( StrOp.equals( NodeOp.getName(Item), wDec.name() ) )
m_ItemList->SetItem( index, m_colDesc, wxT("(") + wxString( wItem.getstate(Item), wxConvUTF8) + wxT(") ") + wxString( wItem.getdesc(Item), wxConvUTF8) );
else if( StrOp.equals( NodeOp.getName(Item), wAction.name() ) && StrOp.len(wItem.getdesc(Item)) == 0 )
m_ItemList->SetItem( index, m_colDesc, (isUsed?wxT("# "):wxT("")) + wxString( wAction.getcmd(Item), wxConvUTF8) + wxT("::") + wxString( wAction.getparam(Item), wxConvUTF8) );
else
m_ItemList->SetItem( index, m_colDesc, (isAutoGen?wxT(""):wxT("")) + wxString(isUsed?wxT("#"):wxT("")) + wxString( wItem.getdesc(Item), wxConvUTF8));
if( m_ShowLen ) {
if( StrOp.equals( NodeOp.getName(Item), wLoc.name() ) && wLoc.getwheelbase(Item) > 0 )
m_ItemList->SetItem( index, m_colLen, wxString::Format(_T("%d (%d)"), wItem.getlen(Item), wLoc.getwheelbase(Item)));
else
m_ItemList->SetItem( index, m_colLen, wxString::Format(_T("%d"), wItem.getlen(Item)));
if( adjustColumnWidth )
m_ItemList->SetColumnWidth(m_colLen, wxLIST_AUTOSIZE_USEHEADER);
}
if( m_ShowShow ) {
if( StrOp.equals( NodeOp.getName(Item), wLoc.name() ) ) {
char showactive = StrOp.fmt("%s%c", wItem.isshow(Item)?"true":"false", wLoc.isactive(Item)?'+':'-');
m_ItemList->SetItem( index, m_colShow, wxString( showactive, wxConvUTF8));
StrOp.free(showactive);
}
else
m_ItemList->SetItem( index, m_colShow, wxString( wItem.isshow(Item)?"true":"false", wxConvUTF8));
}
if( m_ShowPos ) {
if( StrOp.equals( NodeOp.getName(Item), wLocation.name() ) ) {
char* s = StrOp.fmt("%d", wLocation.getsectionpos(Item) );
m_ItemList->SetItem( index, m_colPos, wxString(s, wxConvUTF8) );
StrOp.free(s);
}
else {
m_ItemList->SetItem( index, m_colPos, wxString::Format(_T("%d: %d,%d"), wItem.getz(Item), wItem.getx(Item), wItem.gety(Item)) );
if( m_ShowOri )
m_ItemList->SetItem( index, m_colOri, wxString( wItem.getori(Item)!=NULL?wItem.getori(Item):wItem.west, wxConvUTF8));
}
if( adjustColumnWidth ) {
m_ItemList->SetColumnWidth(m_colPos, wxLIST_AUTOSIZE_USEHEADER);
if( m_ShowOri )
m_ItemList->SetColumnWidth(m_colOri, wxLIST_AUTOSIZE_USEHEADER);
}
}
m_ItemList->SetItemPtrData(index, (wxUIntPtr)Item);
if( adjustColumnWidth ) {
m_ItemList->SetColumnWidth(m_colID, wxLIST_AUTOSIZE);
m_ItemList->SetColumnWidth(m_colDesc, wxLIST_AUTOSIZE);
}
if( m_ShowShow && adjustColumnWidth )
m_ItemList->SetColumnWidth(m_colShow, wxLIST_AUTOSIZE_USEHEADER);
if( m_ItemList->GetColumnWidth(m_colDesc) < 60 && adjustColumnWidth )
m_ItemList->SetColumnWidth(m_colDesc, wxLIST_AUTOSIZE_USEHEADER);
if( m_ShowType ) {
m_ItemList->SetItem( index, m_colType, wxString( wItem.gettype(Item), wxConvUTF8));
if( adjustColumnWidth )
m_ItemList->SetColumnWidth(m_colType, wxLIST_AUTOSIZE);
}
if( m_ShowTime ) {
// Loco
long runtime = wLoc.getruntime(Item);
long mtime = wLoc.getmtime(Item);
long deltatime = runtime-mtime;
char mdate[32] = {'\0'};
if( wLoc.getmdate( Item ) > 0 ) {
time_t ltime = wLoc.getmdate( Item );
struct tm* ltm = localtime( (const time_t*)<ime );
StrOp.fmtb( mdate, "%02d-%02d-%d", ltm->tm_mday, ltm->tm_mon+1, ltm->tm_year + 1900);
}
char rdate[32] = {'\0'};
if( wLoc.getrdate( Item ) > 0 ) {
time_t ltime = wLoc.getrdate( Item );
struct tm* ltm = localtime( (const time_t*)<ime );
StrOp.fmtb( rdate, "%02d-%02d-%d", ltm->tm_mday, ltm->tm_mon+1, ltm->tm_year + 1900);
}
m_ItemList->SetItem( index, m_colRTime, wxString::Format(_T("%d:%02d.%02d"), (int)(runtime/3600), (int)((runtime%3600)/60), (int)((runtime%3600)%60)));
m_ItemList->SetItem( index, m_colRDate, wxString(rdate, wxConvUTF8) );
m_ItemList->SetItem( index, m_colMTime, wxString::Format(_T("%d:%02d.%02d (%d:%02d.%02d)"),
(int)(mtime/3600), (int)((mtime%3600)/60), (int)((mtime%3600)%60), (int)(deltatime/3600), (int)((deltatime%3600)/60), (int)((deltatime%3600)%60) ) );
m_ItemList->SetItem( index, m_colMDate, wxString(mdate, wxConvUTF8) );
m_ItemList->SetItem( index, m_colHome, wxString(wLoc.gethome(Item), wxConvUTF8) );
m_ItemList->SetItem( index, m_colSchedule, wxString(wLoc.getstartupscid(Item), wxConvUTF8) );
m_ItemList->SetItem( index, m_colTour, wxString(wLoc.getstartuptourid(Item), wxConvUTF8) );
if( adjustColumnWidth ) {
m_ItemList->SetColumnWidth(m_colRTime, wxLIST_AUTOSIZE_USEHEADER);
int autoheadersize = m_ItemList->GetColumnWidth(m_colRTime);
m_ItemList->SetColumnWidth(m_colRTime, wxLIST_AUTOSIZE);
int autosize = m_ItemList->GetColumnWidth(m_colRTime);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colRTime, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colRDate, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colRDate);
m_ItemList->SetColumnWidth(m_colRDate, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colRDate);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colRDate, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colMTime, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colMTime);
m_ItemList->SetColumnWidth(m_colMTime, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colMTime);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colMTime, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colMDate, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colMDate);
m_ItemList->SetColumnWidth(m_colMDate, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colMDate);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colMDate, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colHome, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colHome);
m_ItemList->SetColumnWidth(m_colHome, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colHome);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colHome, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colSchedule, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colSchedule);
m_ItemList->SetColumnWidth(m_colSchedule, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colSchedule);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colSchedule, wxLIST_AUTOSIZE_USEHEADER);
m_ItemList->SetColumnWidth(m_colTour, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colTour);
m_ItemList->SetColumnWidth(m_colTour, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colTour);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colTour, wxLIST_AUTOSIZE_USEHEADER);
}
}
if( m_ShowFromTo ) {
// Route
m_ItemList->SetItem( index, m_colFrom, wxString( wRoute.getbka(Item), wxConvUTF8));
m_ItemList->SetItem( index, m_colTo, wxString( wRoute.getbkb(Item), wxConvUTF8));
if( m_ShowCrossing ) {
m_ItemList->SetItem( index, m_colCrossing, wxString( wRoute.getbkc(Item), wxConvUTF8));
m_ItemList->SetItem( index, m_colState, wxString( __getRouteState(wRoute.getstatus(Item)), wxConvUTF8));
}
if( adjustColumnWidth ) {
int autoheadersize = m_ItemList->GetColumnWidth(m_colFrom);
m_ItemList->SetColumnWidth(m_colFrom, wxLIST_AUTOSIZE);
int autosize = m_ItemList->GetColumnWidth(m_colFrom);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colFrom, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colTo);
m_ItemList->SetColumnWidth(m_colTo, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colTo);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colTo, wxLIST_AUTOSIZE_USEHEADER);
if( m_ShowCrossing ) {
autoheadersize = m_ItemList->GetColumnWidth(m_colCrossing);
m_ItemList->SetColumnWidth(m_colCrossing, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colCrossing);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colCrossing, wxLIST_AUTOSIZE_USEHEADER);
autoheadersize = m_ItemList->GetColumnWidth(m_colState);
m_ItemList->SetColumnWidth(m_colState, wxLIST_AUTOSIZE);
autosize = m_ItemList->GetColumnWidth(m_colState);
if(autoheadersize > autosize )
m_ItemList->SetColumnWidth(m_colState, wxLIST_AUTOSIZE_USEHEADER);
}
}
}
m_ItemList->Thaw();
}
`
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
(How to add a code section at github???)
There is a "M" button in the lower right corner of the text box where you're writing comments which opens the full help, which includes the answer to this question.
Maybe more importantly, it's best to minimize the code as much as possible as it's really hard to know what is relevant and what isn't in the example you provide. The example provided by @PBfordev (thanks!) is much simpler, so I'm going to use it for debugging this issue, but please keep this in mind for the future bug reports. TIA!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
It's actually not adding the items which takes time, but setting the column widths using wxLIST_AUTOSIZE, as this results in 500 calls to our item drawing function for each of the columns.
It looks like we need to use wxListCtrlMaxWidthCalculator in native wxMSW wxListCtrl version too.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Oops, I am sorry for not realizing that setting the column width is the culprit (and the major difference between my first and second codes), perhaps because I could observe the items actually being drawn during adding. BTW, the control's size also plays a major role here (i.e., the larger the the slower).
FWIW, here is the patch to the minimal sample which can be used to reproduce the issue:
diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp index 5f32257c6b..2aff99c4b2 100644 --- a/samples/minimal/minimal.cpp +++ b/samples/minimal/minimal.cpp @@ -25,6 +25,9 @@ #ifndef WX_PRECOMP #include "wx/wx.h" #endif +#include "wx/listctrl.h" +#include "wx/stopwatch.h" +#include "wx/wupdlock.h" // ---------------------------------------------------------------------------- // resources @@ -65,6 +68,9 @@ public: void OnAbout(wxCommandEvent& event); private: + wxListCtrl* m_listCtrl; + + void AddListItems(); // any class wishing to process wxWidgets events must use this macro wxDECLARE_EVENT_TABLE(); }; @@ -175,8 +181,39 @@ MyFrame::MyFrame(const wxString& title) CreateStatusBar(2); SetStatusText("Welcome to wxWidgets!"); #endif // wxUSE_STATUSBAR + m_listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT); + Maximize(); + CallAfter(&MyFrame::AddListItems); } +void MyFrame::AddListItems() +{ + const long rowCount = 500; + const long columnCount = 10; + + wxStopWatch stopWatch; +#if 0 + wxWindowUpdateLocker lock(this); +#endif + + for ( long i = 0; i < columnCount; ++i ) + m_listCtrl->AppendColumn(wxString::Format("Column %ld", i)); + + SetTitle("Adding items..."); + stopWatch.Start(); + + for ( long row = 0; row < rowCount; ++row ) + { + m_listCtrl->InsertItem(row,""); + for ( long column = 0; column < columnCount; ++column ) + m_listCtrl->SetItem(row, column, wxString::Format("col %02ld row %04ld", column, row)); + } + + for ( long column = 0; column < columnCount; ++column ) + m_listCtrl->SetColumnWidth(column, wxLIST_AUTOSIZE); + + SetTitle(wxString::Format("Adding %ld items took %ld ms", rowCount, stopWatch.Time())); +} // event handlers
BTW, I think my #23846 should also have the "dark mode" label.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I corrected an unwanted wxLIST_AUTOSIZE in the insert loop and now its OK.
It remains a bit slower then the light mode.
Thanks for the helps and tips.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
This is arguably not 3.3.0-critical, although still would be nice to fix, of course.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()