← All posts tagged Qt

beardog-ukr

Говорят, что обьект (QObject) "живет" в потоке (QThread), если он был создан после того, как метод run() начал выполнятся.
Дополнительное условие для основного потока приложения: обьект считается живущим в потоке только если он был создан после
создания экземпляра QCoreApplication. Обьекты, созданные до этого момента, не живут ни в каком потоке (типа бомжи, хихи).

У каждого потока есть свой event loop, который запускается методом QThread::exec(). Event loop основного потока приложения
запускается QCoreApplication::exec().

особенности жизни:
— Дочерний обьект (child) должен жить в том же потоке, что и родительский (parent)
— Некоторые обьекты могут использоваться только в том потоке, в котором они живут. Например, запустить QTimer (start()),
можно только из его родного потока. Еще в качестве примера в документации упоминаются сокеты
— Документация требует, чтобы обьекты, которые живут в потоке, были удалены перед удалением потока
— Удалять (delete) обьект желательно только из того потока, в котором он живет. Иначе возможно, что вы удалите обьект в том
момент, когда он обрабатывает какой-нибудь слот или событие (event).
— обьект может обрабатывать слоты и посылать сигналы только когда в том потоке, где он живет, крутится event loop (т.е.
пока исполняется exec())

Важно: сам по себе обьект QThread живет в том потоке, где вы его создали; все обьекты, которые создаются в конструкторе
этого потока тоже живут в текущем потоке. Поэтому нельзя назначить поток родителем для обьектов, созданных в внутри run():
будет ошибка вроде
QObject: Cannot create children for a parent that is in a different thread.
(Parent is TimerThread(0xbfd66954), parent's thread is QThread(0x946e338), current thread is TimerThread(0xbfd66954)

Еще пример: обьект QTimer будет живет в одном потоке, а вы пытаетесь запустить его из другого. Получите
QObject::startTimer: timers cannot be started from another thread

Важно: для того, чтобы сигналы-слоты работали, совершенно не обязятельно запускать QCoreApplication::exec(); необходимо и
достаточно, чтобы выполнялся exec() того потока, в котором живут обьекты.

Обьект можно переместить (сменить прописку, хихи) из одного потока в другой, используя метод QObject::moveToThread().

Если обьекты, сигналы-слоты которых соединены, живут в разных потоках, при возникновении сигнала связь все равно сработает
(естественно, если event loop действует в обоих потоках). Пятый параметр функции connect() определяет только когда именно
произойдет это соединение и где оно будет выполнено (т.е. где будут жить обьекты, созданные в слоте).

Пруфлинк: doc.qt.nokia.com

beardog-ukr

Забавный глюк-фича.
Есть QTime::fromString(const QString & string, const QString & format) ; в строке формата можно указать "hh" если часы гарантированно двузначные, или "h" если ведущий ноль добавляться не будет. Так вот, если указать "hh:mm", но часы указать одной цифрой (например "2:52") то оно все равно сработает корректно, но только если время >= 3. Т.е. для "5:25" сработает, а для "2:35" — нет, будет invalid QTime object.

То же самое для "mm" и "m", но там начинает работать после цифры 5.

beardog-ukr
QT

QDomDocument тратит больше двух секунд на загрузку xml 2500 строк, макс уровень вложенности 3;
да, оно таки толстовато для скромных эмбеднутых процов

beardog-ukr

Вопрос: сконвертирует ли данное выражение градусы фаренгейта в кельвины?

result = qRound( (uiValue + 459.67)*(5/9) ) ;

Ответ: нет, нифига, т.к. 5/9 всегда равно 0 :)

beardog-ukr
QT

чтобы показать гифку, надо
QLabel label;
QMovie *movie = new QMovie("animations/fire.gif");

label.setMovie(movie);
movie->start();

но если посмотреть в документацию на QLabel, то окажется, что после setMovie "The label does NOT take ownership of the movie." Т.е. надо еще дополнительно

movie->setParent(label) ;

Ну, или еще чего-то придумать, типа соединить deleteLater с destroyed.