Thread: wxWidgets ListCtrl lag

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    50

    wxWidgets ListCtrl lag

    Hi,

    I am using a wxWidgets ListCtrl component in report view. I'm adding some items to it (between 10 and 50) at certain time intervals, intervals that depend on the work being done between two adds. My problem is that I would like to see what has just been added immediately. For example, I might add 10 items very fast and then add a new one every 5 seconds until I have added 20. The problem is, these 10 won't display as they're added. All 20 will be displayed at once. I've tried adding Sleep() in certain parts of the code, but it doesn't seem to help. I'm using windows and the gnu gcc compiler.

    Any idea how to fix this?

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Take a look at wxListCtrl::Refre........em() and wxListCtrl::Refre........ems() if you passed wxLC_VIRTUAL to the constructor. I'd suggest the first one if you happen to have a large number of items on the list (hundreds or more). You should call one of these functions after each wxListCtrl::InsertItem().

    If instead you are not using a virtual wxListCtrl, I'll need code: your list declaration, and the code surrounding the insert.

    EDIT: Hmm... the bad words check on the forums is perhaps a little too aggressive. The function names are (without the underscore):

    wxListCtrl::Refresh_Item() and wxListCtrl::Refresh_Items()
    Last edited by Mario F.; 05-18-2008 at 01:49 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    50
    I'm not using a virtual listctrl. And about my list declaration, I'm not sure what you mean. I used the IDE to create it. Do you mean this?

    Code:
    ListCtrl1 = new wxListCtrl(Panel1, ID_LISTCTRL1, wxDefaultPosition, wxSize(562,242), wxLC_REPORT, wxDefaultValidator, _T("ID_LISTCTRL1"));
    And here's my insert function:

    Code:
    void Win_EvalFrame::print(long testnr, double time, long memory, char *message, long points)
    {
        ListCtrl1->Hide();
    
        wxListItem t;
        wxString w;
        t.SetId(testnr-1);
        t.SetColumn(0);
        w.Printf(_("%ld"), testnr);
        t.SetText(w);
        ListCtrl1->InsertItem(t);
        w.Printf(_("%.2lf"), time);
        ListCtrl1->SetItem(t, 1, w);
        w.Printf(_("%ld"), memory);
        ListCtrl1->SetItem(t, 2, w);
        ListCtrl1->SetItem(t, 3, wxString::FromAscii(message));
        w.Printf(_("%ld"), points);
        ListCtrl1->SetItem(t, 4, w);
    
        ListCtrl1->Show();
    }
    My program launches a process and waits for it to finish a few seconds. The problem is, it can wait quite some time, up to 10 seconds. And it's annoying to have to wait until everything finishes to display everything in the list. I would rather see everything as it's added.

    And another thing, not really related to wxlistctrl but related to wxwidgets: During this waiting, how can I make my main window ignore every windows message? Because if it waits a lot, it freezes, and it messes up some of the stuff I do. Is there any way to make it ignore all windows messages so that it can do what it needs to without problems?

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Before anything else, I'd probably suggest that first, you don't need to hide the wxListCtrl instance. You are just wasting cpu cycles with that. A second issue is you are better of first completely building your wxListItem object and only in the end insert it.

    As for the process issue, I take it you are using wxExecute(). If your current process has to wait for the other to finish before you regain control that means you are executing it in synchronous mode. You need to run it in asynchronous mode instead. Check the documentation on wxExecute(). I can't recall the flag name, but it's the default one.

    EDIT: Just now noticed you last question... you are definitely running the process in synchronous mode. Otherwise you wouldn't be asking this. To answer you however I need to know what form of the wxExecute() function you are using
    Last edited by Mario F.; 05-18-2008 at 04:45 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    50
    Actually, I'm using CreateProcess and WaitForSingleObject. Anyway this is not that much of a problem right now as I changed some functions and it seems to do its work even if it looks like it froze.

    As for wxExecute - heh, I didn't even know about it. From what I just read it looks like I can't get it to wait a certain amount of time before returning control to the application? I use WaitForSingleObject to make my program wait a certain amount of time then resumes control. I could probably avoid this by using timers, but right now that seems too complicated.

    Anyway, for my main problem, I read somewhere that hiding makes insertion faster, but it didn't change anything. I removed it now.

    What do you mean by completely building my wxListItem object? From what I understand, I'm only inserting it once, and modifying the needed columns after that. How could I completely build it with all the column information and only then insert it?

  6. #6
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by Sfel View Post
    As for wxExecute - heh, I didn't even know about it. From what I just read it looks like I can't get it to wait a certain amount of time before returning control to the application? I use WaitForSingleObject to make my program wait a certain amount of time then resumes control. I could probably avoid this by using timers, but right now that seems too complicated.
    I'd advise against the use of Win32 functions with wxWidgets. Always look for a replacement within the framework you are using before bypassing it. Two reasons spur to mind; the fact you are defeating cross-compatibility and the fact you may affect normal operation of certain controls and operations which rely on wxWidgets own object model. Naturally, if you know they don't and migrating your code to other systems is not in your plans, you are safe to use these functions.

    I'm somewhat confused with your requirements... you say you want your listCtrl to update while the process you launched is running, but then say you want to wait until after the process you launched is finished. Please be more precise. wxWidgets can handle that and more, but I'm unsure as to what exactly you want.

    Anyway, for my main problem, I read somewhere that hiding makes insertion faster, but it didn't change anything. I removed it now.
    Hmm... only reason I can think of was if you were inserting a very large amount of items in quick succession. And then, only if you hid the control before the first insert and shown it after the last (meanwhile this has the potential to produce a very ugly effect in your application). Hiding and closing with every insert, as you are doing, will actually make the whole insertion process slower.

    What do you mean by completely building my wxListItem object? From what I understand, I'm only inserting it once, and modifying the needed columns after that. How could I completely build it with all the column information and only then insert it?
    A wxListCtrl is essentially a container of wxListItem objects. Check this class in the documentation for an idea of what I'm talking about.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    50
    My listCtrl updates after the process has finished. But, after it updates, another process is launched, it finishes, then it updates again. This is done a few times, but not more than 50 or so (worst case). The problem is, they all appear at the end of the whole process spawning routine, not at the time of the actual update, and I would like them to appear at the time of the actual update.

    I read about wxListItem here: http://docs.wxwidgets.org/stable/wx_wxlistitem.html and from what I understand, one item can only be put in one column. So I can't put all my information in one item then just add that one. After I add it, I have to modify the information that goes in the other columns as well, don't I? In fact, this is what the wxListCtrl sample does as well. I'm not sure what you mean by building the entire item first. Could you give an example please?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. WxWidgets in C?
    By Jake.c in forum C Programming
    Replies: 8
    Last Post: 10-05-2008, 02:40 AM
  2. wxWidgets Reduce Rilesize
    By parad0x13 in forum C++ Programming
    Replies: 4
    Last Post: 07-25-2008, 08:15 PM
  3. wxWidgets DLL Help
    By Matt3000 in forum C++ Programming
    Replies: 0
    Last Post: 08-19-2006, 05:56 PM
  4. Borland & wxWidgets!!! Help!!!
    By Matt3000 in forum C++ Programming
    Replies: 5
    Last Post: 07-31-2006, 09:17 PM
  5. wxWidgets cross platform GUI problem
    By BobS0327 in forum Linux Programming
    Replies: 2
    Last Post: 05-31-2006, 06:34 AM