Russian Qt Forum
Октябрь 04, 2024, 14:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [4.2.*] Проблема при работе с QTableWidget  (Прочитано 7242 раз)
Mindtraveller
Гость
« : Июнь 19, 2007, 19:00 »

Приветствую.

В простой ситуации, почему-то, не могу разобраться с созданием/удалением элементов в QTableWidget.

Ситуация следующая: есть QTableWidget, в нём два столбца. При клике на один из элементов другого контрола, в QTableWidget отображаются соответствующие ему свойства.
Казалось бы, всё элементарно: удалить предыдущие ячейки, создать новые. Вот код:
Код:
void ObjUI::EnlistObjectProperties(const Properties &props, QTableWidget *widget)
{
while (widget->rowCount())
widget->removeRow(widget->rowCount()-1);

for (int i=0; i<props.size(); ++i)
{
widget->insertRow(i);

const Property &p = props[i];

QTableWidgetItem *newItem = new QTableWidgetItem (QString::fromLocal8Bit(p.name.c_str()));
newItem->setFlags(Qt::ItemIsEnabled);
widget->setItem(i, 0, newItem);

newItem = new QTableWidgetItem (QString::fromLocal8Bit(p.Value2String().c_str()));
newItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled);
widget->setItem(i, 1, newItem);
}
}


Так вот, на первой же попытке удалить существующие строки, в строке
      widget->removeRow(widget->rowCount()-1);
выбрасывается исключение.

Подскажите пожалуйста, как правильно пересоздать ячейки в QTableWidget?
Спасибо.
Записан
Emc
Гость
« Ответ #1 : Июнь 19, 2007, 20:17 »

Код:

widget->clear();

несколько проще
Записан
Mindtraveller
Гость
« Ответ #2 : Июнь 19, 2007, 23:43 »

Всё равно исключение... не помогло...
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #3 : Июнь 20, 2007, 00:50 »

widget у тебя инициализирован нормально?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Mindtraveller
Гость
« Ответ #4 : Июнь 20, 2007, 01:11 »

Да, он создаётся автоматом QT-Дизайнером, после чего uic генерит хедэр, где всё это инициализируется.

Кстати, забавно, на VCL затыков на таких простых вещах не было.
А здесь, простейшие вещи не работают...  :?

Кто работал с QTableWidget, подскажите всё-таки, что я делаю не так?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #5 : Июнь 20, 2007, 10:07 »

Я использовал (и спользую) QTableWidget::clear () и QTableWidget::clearContents(), никаких исключений небыло. имхо, что-то не так у тебя в логике работы программы. Приведи код вызова  clear(), что пишет после падения  и стек вызавов после падения.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Mindtraveller
Гость
« Ответ #6 : Июнь 20, 2007, 11:46 »

Да, что-то действительно не так... Выдаёт исключение даже вот такой вот простой код:
Код:

dialog->objProps->setRowCount(100);
//в одном из методов идёт вызов
EnlistObjectProperties(..., dialog->objProps);
//...
void ObjUI::EnlistObjectProperties(const Properties &props, QTableWidget *widget)
{
widget->clearContents();
QTableWidgetItem *newItem = new QTableWidgetItem (QString::fromLocal8Bit("***"));
widget->setItem(0, 0, newItem);
}


Так вот, при первом вызове EnlistObjectProperties всё нормально.
При втором вызове, исключение выбрасывается из строки
widget->clearContents();

В режиме отладки сообщение об исключение такое:
Цитировать
User breakpoint called from code at ******

P.S. Версия QT 4.2.2, линковка динамическая; компилятор Intel 8.04; сборка Win32 Debug
P.P.S. При выходе из приложения появляется такое же исключение (user breakpoint) откуда-то изнутри QT. Но это уже другая история, тут бы с этим для начала разобраться.
Записан
Emc
Гость
« Ответ #7 : Июнь 20, 2007, 11:54 »

поставь после widget->clearContents();
проверку rowCount();
похоже чистится всё и ты добавляешь item в пустую таблицу (без строк/столбцов)
Записан
Mindtraveller
Гость
« Ответ #8 : Июнь 20, 2007, 12:43 »

проверка показала rowCount() == 100

добавлено спустя 42 минуты:

 Я тут подумал над ситуацией, и нашёл некую странность. Поясню.

Есть правило, касающееся разработки программ, состоящих из основного модуля и DLL. Оно состоит в том, что класс должен удаляться в том же модуле, в котором и был создан. Т.е. пары new/delete должны принадлежать либо основному модулю, либо DLL.

А QT мы подключаем как раз при помощи DLL. То есть, получается что QT из своего DLL пытается при очистке таблицы удалить класс элемента таблицы, который я создал в основном коде.
Такое поведение действительно вызывает исключения.
Решается данная проблема путём введения абстрактных классов, как вы знаете.

Я посмотрел исходники реализации QTableWidget. И абстрактные классы там для работы с ячейками не используются:
Код:
class QTableWidget { ... QVector<QTableWidgetItem*> tableItems; ...}
...
void QTableModel::clearContents()
{
    for (int i = 0; i < tableItems.count(); ++i) {
        if (tableItems.at(i)) {
            tableItems.at(i)->model = 0;
            delete tableItems.at(i);
            tableItems[i] = 0;
        }
    }
    reset();
}


Как видите, всё делается напрямую.
Теперь я удивляюсь почему оно вообще работает Улыбающийся

Вот, например, у меня стоит Win32 Debug и соответствующий memory manager, а QT скомпилирован в Release, да ещё и, например, VC++6 компилятором, а не моим Интеловским.
Значит, когда я у себя делаю new QTableWidgetItem (...) - он регистрируется в одном менеджере памяти (CRT), а внутри кода QT они делают delete его же, но своим менеджером. И всё. Всё грохнулось.
Наверное здесь не поможет даже если выставить Multithreaded Runtime Library
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #9 : Июнь 20, 2007, 14:50 »

Наваял тестовый примерчик. Все работает. Ничего не падает. Вот основной код:

Код:
Test::Test(QWidget *parent)
: QMainWindow(parent)
{
setupUi(this);
tableWidget->setColumnCount(2);

connect(pushButton, SIGNAL(clicked()), this, SLOT(slot_1()));
}

void Test::slot_1()
{
tableWidget->clearContents();
tableWidget->setRowCount(0);

for (int i=0; i<100; ++i)
   {
      tableWidget->insertRow(i);

 QTableWidgetItem *newItem = new QTableWidgetItem (QString("Cell (%1:0)").arg(i));
      newItem->setFlags(Qt::ItemIsEnabled);
      tableWidget->setItem(i, 0, newItem);

 newItem = new QTableWidgetItem (QString("Cell (%1:1)").arg(i));
      newItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled);
      tableWidget->setItem(i, 1, newItem);
   }
}


При нажатии на кнопку pushButton вызываеться слот slot_1. При неоднократном нажатии на эту кнопку, все работает корректно.
Qt 4.2.3, VS2005

ЗЫ: имхо, что-то не так в логике работы программы.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.07 секунд. Запросов: 22.