Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ QTreeWidget

Автор: flankerr 19.2.2008, 15:45

Qt 4.1.2
Есть дерево в узлах установлено чекбокс, так вот не получается выловить сигнал измения состояния этого чек бокса... (когда пользователь щёлкает по чекбоксу)

connect(this,SIGNAL(itemClicked( QTreeWidgetItem * item, int column )),this,SLOT(OnChangedItem( QTreeWidgetItem * item, int column ) ));
сonnect(this,SIGNAL(itemChanged( QTreeWidgetItem * item, int column ) ),this,SLOT(OnChangedItem( QTreeWidgetItem * item, int column ) ));

разумеется слот OnChangedItem( QTreeWidgetItem * item, int column ) создан.
но не отрабатывает а где грабли не вижу...

Автор: ViGOur 19.2.2008, 16:25

А как ты выставляешь чекбокс? Я просто не совсе понял, что за чекбокс... :blush:

Автор: Litkevich Yuriy 19.2.2008, 16:44

чето я про чек бокс тоже не въехал, если юзер именно чек бокс кликает дак и сигнал чекбокса ловить надо

void stateChanged ( int state )

или
void clicked ( bool checked = false )


если, конечно, я картину правильно представил.

Автор: flankerr 19.2.2008, 17:05

Есть класс унаследованный от QTreeWidget

внутри класса

создал узел
QTreeWidgetItem* pItem = new QTreeWidgetItem(this);

вставил чекбокс
pItem->setCheckState(0,Qt::Checked);

Автор: ViGOur 19.2.2008, 17:40

У меня все отрабатывает, я сделал вот так:

class CTest: public QObject
{
    Q_OBJECT

public:
    CTest(QWidget *parent = 0, Qt::WFlags flags = 0){}
    ~CTest(){}

public slots:
    void OnCheckState( QTreeWidgetItem *item, int column);
};

void CTest::OnCheckState( QTreeWidgetItem *item, int column)
{
    QMessageBox::information( 0, "info", QObject::tr( "%1- column %2").arg( item->isExpanded()).arg( column));
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTreeWidget *pTreeWidget = new QTreeWidget( 0);
    pTreeWidget->setColumnCount(2);
    QStringList headers;
    headers << QObject::tr("Subject") << QObject::tr("Default");
    pTreeWidget->setHeaderLabels( headers);

    QTreeWidgetItem *pRoot = new QTreeWidgetItem( pTreeWidget);
    pRoot->setText( 0, QObject::tr("Root"));
    
    for( int n = 0; n < 100; n++)
    {
        QTreeWidgetItem *pChild = new QTreeWidgetItem( pRoot);
        pChild->setFlags( pChild->flags() | Qt::ItemIsEditable);
        
        QString sz0 = QObject::tr( "Item %1").arg( n);
        QString sz1 = QObject::tr( "Sub item %1").arg( n);
        pChild->setText(0, sz0);
        pChild->setText(1, sz1);

        pChild->setCheckState(0,Qt::Checked);
    }

    pTreeWidget->expandItem( pRoot);
    //pTreeWidget->collapseItem( pRoot);

    CTest test;
    QObject::connect( pTreeWidget, SIGNAL(  itemChanged( QTreeWidgetItem *, int)), &test, SLOT( OnCheckState( QTreeWidgetItem *, int)));
    pTreeWidget->show();

    return a.exec();
}

Автор: Litkevich Yuriy 19.2.2008, 18:31

Я по пробывал твой пример скомпилить, линкер ругается:

build/main.o(.text+0x1c):main.cpp: undefined reference to `vtable for CTest'
build/main.o(.text+0x4c):main.cpp: undefined reference to `vtable for CTest'
build/main.o(.text+0xb33):main.cpp: undefined reference to `vtable for CTest'
build/main.o(.text+0xc4c):main.cpp: undefined reference to `vtable for CTest'
collect2: ld returned 1 exit status


хотя в файл сунул
#include <QtGui>

может че забыл, не пойму

Автор: ViGOur 19.2.2008, 18:36

Класс CTest нужно перенести в .h файл. ;)

Автор: Litkevich Yuriy 19.2.2008, 18:37

хм, а вчем принципиальная разница?

Автор: ViGOur 19.2.2008, 18:40

в moc'е. :)

Автор: Litkevich Yuriy 19.2.2008, 18:42

ХМ, НЮАНЕЦ однако, это видимо во всех случаях где макрос Q_OBJECT,
т.к. без него я делал все в одном файле.

Автор: ViGOur 20.2.2008, 9:11

Цитата(Litkevich Yuriy @ 19.2.2008, 18:42) *
однако, это видимо во всех случаях где макрос Q_OBJECT,
Угу, именно так :)

Автор: flankerr 20.2.2008, 11:37

понял почему у меня не получалось. :rolleyes:
надо было так
itemChanged ( QTreeWidgetItem *,int )
а у меня было так
itemChanged ( QTreeWidgetItem * item, int column)

Автор: flankerr 20.2.2008, 12:08

Возник другой вопрос.
Как сделать чтобы событие отрабатывало только по действию пользователя но не работало при программном изменение значения ?
ну можно конечно делать дисконект слота перед прграмным изменением а после снова делать конектЮ но может есть что более "красивое"...

Автор: Litkevich Yuriy 21.2.2008, 0:25

не все сигналы посылаются при програмном изменении состояния, плюс некоторые функции попадаются перегруженые, в которых можно флажек выставить, "не сигналить". надо справку почитать вдруг для твоего случая такая комбинация сигнала и функции setFoo() попадется.

Автор: Tonal 21.2.2008, 11:11

Зачем же дисконнект/коннект?
Есть же QObject::blockSignals

Автор: flankerr 21.2.2008, 11:33

Цитата(Tonal @ 21.2.2008, 11:11) *
Зачем же дисконнект/коннект?
Есть же QObject::blockSignals


Насколько я понимаю в этом случае блокируються все сигналы...
В этом смысле, мне думается, конект\дисконет более правильное решение т.к. изолирует только нужную часть сигналов.

Автор: flankerr 21.2.2008, 11:37

Цитата(Litkevich Yuriy @ 21.2.2008, 0:25) *
не все сигналы посылаются при програмном изменении состояния, плюс некоторые функции попадаются перегруженые, в которых можно флажек выставить, "не сигналить". надо справку почитать вдруг для твоего случая такая комбинация сигнала и функции setFoo() попадется.

На будущие учту спаисбо
но возможность выставить флаг сигналить\несигналить я не нашёл впрочем как и функции setFoo
возможно это есть начиная с 4.2

Автор: Litkevich Yuriy 21.2.2008, 17:55

Цитата(flankerr @ 21.2.2008, 14:37) *
как и функции setFoo

Foo в переводе с английского: что-то, что-нибудь и т.д.
т.е. я имел в видукакую-нибудь функцию которая устанавливает состояние чего либо, некоторые функции не приводеть к посылке сигналаов, как
например, для класса абстрактной кнопки:
Цитата
void QAbstractButton::clicked ( bool checked = false ) [signal]
Данный сигнал посылается при активизации кнопки (т.е. когда нажатая кнопка отпускается при находении указателя мыши внутри кнопки), при нажатии горячего сочетания клавиш или при вызове click() либо animateClick(). Обратите внимание: данный сигнал не посылается при вызове setDown(), setChecked() или toggle().
У тригерной кнопки свойство checked равно true если кнопка включена, или false если кнопка выключена.
См. также pressed(), released(), и toggled().


А насчет флага, похоже это моя мечта, а не действительность :)

Автор: Tonal 22.2.2008, 8:33

Цитата(flankerr @ 21.2.2008, 14:33) *
Цитата(Tonal @ 21.2.2008, 11:11) *
Зачем же дисконнект/коннект?
Есть же QObject::blockSignals

Насколько я понимаю в этом случае блокируються все сигналы...
В этом смысле, мне думается, конект\дисконет более правильное решение т.к. изолирует только нужную часть сигналов.

Если тебе действительно нужно выборочно блокировать сигналы, тогда действительно blockSignals не подходит.
Тогда либо конект\дисконет, либо выставлять какой-нибудь флажёк перед действием, а в обработчике его проверять и ничего не делать если он выставлен.

blockSignals очень хорошо подходит при первоначальном заполнении диалога данными например. Когда к событиям привязаны проверки и/или корректировки состояний других виджетов.

Автор: flankerr 26.2.2008, 17:58

кстати чего-то сразу ступил...
blockSignal можно же выборочно использовать к любому объекту в том числе к любому объкту диалога а не кдиалогу целиком.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)