Skocz do zawartości

[c++,qt4] Qtreewidget I Czyszczenie Listy


przemal

Rekomendowane odpowiedzi

Witam,

 

Może zacznę od pokazania fragmentu kodu a potem opiszę co i jak:

 

//PLIK: UserInterface/UI/ui_TreeWidget.h
...
class Ui_TreeWidget
{
public:
   QTreeWidget *treeWidgetList;
   ...
}
...
//PLIK: UserInterface/TreeWidget.h

#include "UI/ui_TreeWidget.h"

class TreeWidget : public QWidget, public Ui::TreeWidget
 {
   Q_OBJECT

 public:
   TreeWidget(QWidget* parent = 0);
   ~TreeWidget();

   void update(QList<QTreeWidgetItem*> newList);
 };

//PLIK: UserInterface/TreeWidget.cpp

#include "TreeWidget.h"

void TreeWidget::update(QList<QTreeWidgetItem*> newList)
 {
   treeWidgetList->setUpdatesEnabled(false);
   treeWidgetList->setSortingEnabled(false);
   treeWidgetList->clear();//czyści listę ale nie zwalnia pamięci
   treeWidgetList->addTopLevelItems(newList);
   treeWidgetList->setSortingEnabled(true);
   treeWidgetList->setUpdatesEnabled(true);
 }

//PLIK: UserInterface/MainWindow.h

class MainWindow : public QMainWindow, public Ui::MainWindow
 {
   Q_OBJECT

 public:
   MainWindow(QWidget* parent = 0);
   ~MainWindow();

   TreeWidget* treeWidget;
 };

//PLIK: Main/Application.h

#include "../UserInterface/MainWindow.h"

class Application : public QWidget
 {
   Q_OBJECT

 public:
   Application();
   ~Application();

   MainWindow mw;
   QList<QTreeWidgetItem*> list;

   void doSomething();
 };

//PLIK: Application.cpp

void Application::doSomething()
 {
   QTime time;
   time.start();

    list.clear();
   mw.treeWidget->treeWidgetList->clear();//wywołanie clear() tutaj czyści listę i zwalnia pamięć

   for(int i=0;i<10000;i++)
     {
       QTreeWidgetItem* item = new QTreeWidgetItem;
       item->setText(0, "some text");
       item->setText(1, "some text");
       item->setText(2, "some text");
       item->setText(3, "some text");
       list << item;
     }

   //mw.treeWidget->treeWidgetList->addTopLevelItems(list);
   mw.treeWidget->update(list);

   qDebug() << "ApplicationCore::doSomething() -> ??? in:" << time.elapsed() << "msec.";
 }

 

I teraz tak, wywołanie metody clear() (metoda zdefioniowana w klasie QtreeWidget) wewnątrz klasy TreeWidget czyści listę ale nie zwalnia pamięci po tej liście, dopiero wywołanie clean() na obiekcie wyczyści listę i zwolni pamięć z tym że to też nie zawsze bo na początku program zajmuje około 9MB po stworzeniu pierwszej listy 19MB, po wyczyszczeniu przez obiekt i stworzeniu znowu listy (i tak kilka razy) (program zajmuje dalej 19MB zamiast tych 9 początkowych.

 

Czy to ja coś źle tworzę, że czyszczenie listy z wnętrza klasy TreeWidget nie czyści pamięci po liście, czy jest to błąd w bibliotece QT ?

Odnośnik do komentarza
Udostępnij na innych stronach

Twój kod jest raczej niestandardowy. Spróbuj to napisać tak jak opisują w dokumentacji, może zadziała zgodnie z oczekiwaniem. W QT4 nie ma metody clean()! Trudno zrozumieć dokładnie o co pytasz.

Być może chodzi Ci o to, że jeżeli tworzysz QList i dodajesz ją do QTreeWiget poprzez metodę QTreeWidget::addTopLevelItems ( const QList<QTreeWidgetItem *> & items ) to jak widać QList jest pobierane przez stałą referencję wiec po wywołaniu clear() na QTreeWidget nie może zwolić QList bo to musisz zrobić samodzielnie.

Jeżeli chcesz zminiejszyć zużycie pamięci to skonstruuj program tak aby bezpośrednio dodawać QTreeWidgetItem do QTreeWidget, wtedy clear() zwolni pamięć.

 

Odnośnik do komentarza
Udostępnij na innych stronach

dzięki za odpowiedz, tzn tak z tym clean to oczywiście literówka miało tam być clear() a nie dodaje bezpośrednio do QtreeWidget bo przez Qlist jest dużo szybciej.

W kodzie oczywiście czyszczę także tą listę QList ale wyczyszczenie jej nie ma wpływu na pozycje w QtreeWidget które sobie dalej istnieją. Teraz trochę zmieniłem i lista QList jest czyszczona od razu po wrzuceniu elementów do QtreeWidget tak jest czytelniej.

 

Nowa metoda doSomething():

//PLIK: Application.cpp

void Application::doSomething()
 {
   QTime time;
   time.start();

   //mw.treeWidget->treeWidgetList->clear();

   for(int i=0;i<10000;i++)
     {
       QTreeWidgetItem* item = new QTreeWidgetItem;
       item->setText(0, "some text");
       item->setText(1, "some text");
       item->setText(2, "some text");
       item->setText(3, "some text");
       list << item;
     }
   mw.treeWidget->update(list);
   list.clear();

   qDebug() << "ApplicationCore::doSomething():" << time.elapsed() << "msec.";
 }

 

A teraz zamieszam jeszcze bardziej, bo wykonałem troszkę więcej tych cykli dodawania i usuwania przez tą moją metodę TreeWidget::update(QList<QTreeWidgetItem*> newList) z czyszczeniem listy QList i okazało się że pamięć jednak jest zwalniana tylko po 3 cyklach i po mimo wykonania 40 cykli dodawania, usuwania program zajmuje w pamięci coś około 29MB (zamiast tak jak przewidywałem ~410MB) - co mnie bardzo cieszy.

 

A pytałem o to czemu czyszczenie listy (wywołanie treeWidgetList->clear()) z wnętrza klasy w pliku UserInterface/TreeWidget.cpp nie czyści pamięci (czyści tylko listę) a wyczyszczenie (wywołanie mw.treeWidget->treeWidgetList->clear()) listy dostając się do niej przez obiekt zwalnia pamięć.

 

Teraz już wiem że pamięć jest jednak zwalniana tylko trochę później, więc w sumie problem rozwiązany.

Jedyne co mnie jeszcze ciekawi to czemu po wyczyszczeniu obu list QList i QTreeWidget program w pamięci zajmuje 19MB zamiast 9 tak jak na początku, jeżeli ktoś wie czemu się tak dzieje i chciałby podzielić się tą informacją byłbym bardzo wdzięczny.

 

Pozdrawiam, przemal

Odnośnik do komentarza
Udostępnij na innych stronach

Przecież zaraz po wyczyszczeniu listy (w metodzie update) tworzysz nową więc pamięć od razu jest wypełniana. Poza tym możliwe, że sama lista wewnątrz QTreeWigdetList jest implementowana za pomocą puli pamięci (rezerwowana jest ilość pamięci partiami, większa ilość niż w danej chwili się używa, aby po dodaniu nowego obiektu na liście nie od razu rezerowować nową pamięć, a dopiero po przekroczeniu dostępnej ilości pamięci rezerwuje się nową pulę [tak robi to np std::string]) Być może ta pula ma jakieś 20MB spróbuj stworzyć listy z inną ilością QTreeWidgetItem aby to sprawdzić.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
×
×
  • Dodaj nową pozycję...