Russian Qt Forum

Qt => Общие вопросы => Тема начата: QCasper от Декабрь 14, 2005, 01:51



Название: QTimer
Отправлено: QCasper от Декабрь 14, 2005, 01:51
запускаю таймер, например так: timer->start(1000); где timer это указатель на объект класса QTimer, как вы впрочем догадались. Значит на событие timeout() таймера, я увеличиваю некую переменную, и ее в лэйбле рисую. Т.е визуально мы видим как тикают секунды. Как только я хватаюсь за окошко, чтобы его потаскать, всякая анимация прекращается. Так вот как сделать, чтобы часы шли, а окошко можно было двигать?


Название: QTimer
Отправлено: DenKor от Декабрь 14, 2005, 11:25
Запускать QTimer в отдельной нити


Название: QTimer
Отправлено: Hellenna от Декабрь 14, 2005, 14:40
Вызывать в том же цикле, где обновляется лейбл:
Код:

qApp->processEvents();


Название: QTimer
Отправлено: QCasper от Декабрь 14, 2005, 20:22
Цитата: "Hellenna"
Вызывать в том же цикле, где обновляется лейбл:
Код:

qApp->processEvents();


у меня не в цикле обновляется, а при сигнале timeout()


Название: QTimer
Отправлено: Hellenna от Декабрь 15, 2005, 11:31
Цитата: "QCasper"


у меня не в цикле обновляется, а при сигнале timeout()

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


Название: QTimer
Отправлено: QCasper от Декабрь 15, 2005, 15:16
Цитата: "Hellenna"
Цитата: "QCasper"


у меня не в цикле обновляется, а при сигнале timeout()

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


вот смотри, в конструкторе своего виджета, я соединяю кнопку старт, вернее ее сигнал кликед, с неким this слотом, пусть будет slot1(), в котором происходит timer->start(10); где timer, как я уже говорил, QTimer *timer; вот, в конструкторе, буквально строчкой ниже, я соединяю сигнал timer'a timeout(), со слотом, пусть будет slot2(), в котором я увеличиваю некую переменную, и в лэбле ее показвыаю.
Теперь, будьте любезны, объясните мне где и что я должен поправить?
В том числе, если проблема будет решаться с помощью отдельного потока.


Название: QTimer
Отправлено: Dendy от Декабрь 15, 2005, 19:29
QTimer тебе здесь не помощник. Его сигнал timeout() емитится не чаще чем указанньlй интервал таймера. Если на 5 секунд потягать окошко - главньlй поток приостановится, после чего тьl примешь один-единственньlй сигнал, а не столько, сколько их прошло пока не вьlполнялась очередная итерация главного цикла. Как альтернатива QTimer::singleShot( 0, slot ) вьlзовется на следующей итерации главного цикла, то-есть не реже, чем через 0 мс.

Второй поток тоже не помощник. Неглавньlй цикл второго потока точно также может приостанавливаться, в результате чего получишь задержку и не-реальньlй интервал вьlполнения слота.

Единственньl способ посчитать реальное время - заюзать QTime:

Код:
MyWidget::startTimer()
{
  time.start(); // QTime time in declaration
  timer->start( 1000 );
}

void MyWidget::timerSlot()
{
  label->setNum( time.elapsed() );
}


:D


Название: QTimer
Отправлено: QCasper от Декабрь 16, 2005, 00:30
Dendy, а как сделать чтобы не зимарало обновление при движении окна? Мне грубо говоря секундомер сделать надо.


Название: QTimer
Отправлено: Dendy от Декабрь 16, 2005, 10:30
А никак, ьопт... если под виндой...

Драть М$, драть долго кверху задом (с)

Главньlй цикел мрёт пока окно тягается. А так как окна можна создавать ТОЛЬКО в главном цикле, то никакого оповещения работьl сделать не получится. Таймер же при ентом может прекрастно работать в другом потоке.

Если кто знает как избавиться от етого - кричите. Для примера попробуйте потягать окошко копирования файла в проводнике - там всё прекрастно работает.


Название: QTimer
Отправлено: ElderOrb от Декабрь 16, 2005, 10:46
Я не проверял, но мне кажется должно работать если сделать так:
Делаем два потока, гуи и воркер. Воркер занимается тем что по прохождению нужных промежутков времени (как это реализовано, через таймер или через тайм или ещё как - не важно) посылает кастом ивент с данными о времени главному потоку. Причем посылает не post-ом, а send-ом. А главный поток по приходу кастом ивента берёт оттуда время и обновляет нужный контрол.


Название: QTimer
Отправлено: DenKor от Декабрь 16, 2005, 11:14
Я так и реализую в своих программах работу между потоками.
Обновление окон нормальное


Название: QTimer
Отправлено: QCasper от Декабрь 16, 2005, 11:53
Друзья, будьте любезны простейший примерчик, а то ваши слова касты, инвенты, меня как-то немножко напугали, я не знаю что это такое, поэтому, если не трудно, простейший с гуи и ворк потоками примерчик.


Название: QTimer
Отправлено: Dendy от Декабрь 16, 2005, 12:16
Всё круто, мужики! :D  Теперь покажите мне код. Дело как раз в том, что кастом евент возьмётся когда главньlй поток оживёт (после отпускания мьlши с заголовка окна). Знаю, что ето можно сделать, вопрос как ето сделать в Qt?


Название: QTimer
Отправлено: ElderOrb от Декабрь 16, 2005, 15:30
Только что попробовал сделать как я сам написал и обнаружил две любопытных вещи: 1. из одного потока в другой сделать sendEvent не даёт Qt. 2. Если делать postEvent, а в главном потоке при получении любого Event-а делать sendPostedEvents то вроде кастом ивент из другого потока доходит нормально. Проблема в том, что захват заголовка окна мышью не является Event-ом (или я не нашёл каким), а следовательно отфильтровать его и вставить перед его обработкой sendPostedEvents не представляется возможным. Как бы то ни были, в результате я получил хотя бы возможность обновления виджэта при его перемещении ж)))

Код:

#include <QtGui/QApplication>
#include <QLCDNumber>
#include <QThread>
#include <QEvent>
#include <QTime>
#include <QMouseEvent>

enum EventType {
EVENT_UPDATE = QEvent::User + 1
};

class UpdateEvent : public QEvent
{
public:
UpdateEvent(int num) : QEvent((QEvent::Type) EVENT_UPDATE),
number(num) {;}

int number;
};

class UpdateThread : public QThread
{
public:
UpdateThread(QObject* o) : QThread(o), receiver(o) {;}

virtual void run() {

time.start();
while(true) {
UpdateEvent* event = new UpdateEvent(time.elapsed());
QApplication::postEvent(receiver, event);
msleep(1);
}
}

private:
QTime time;
QObject* receiver;
};

class QTestWidget : public QLCDNumber
{
public:
QTestWidget(QLCDNumber* w = NULL) : QLCDNumber(w) {;}
protected:
void mousePressEvent(QMouseEvent* e) {
QApplication::sendPostedEvents(this, EVENT_UPDATE);
}

bool event(QEvent* e) {
if(e->type() == EVENT_UPDATE) {

UpdateEvent* event = (UpdateEvent*) e;
display(event->number);
return true;
} else {
QApplication::sendPostedEvents(this, EVENT_UPDATE);
}

return QLCDNumber::event(e);
}
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTestWidget w;
    w.show();

UpdateThread t(&w);
t.start();

    return a.exec();
}


p.s. Если кто-нибудь сможет отловить событие захвата кэпшена - проблема будет решена полностью.


Название: QTimer
Отправлено: QCasper от Декабрь 16, 2005, 15:52
мда, а более универсальных способов не существует? Потому как, если я например в одном приложении управляю другими контролами, слайдер к примеру таскаю туда сюда, то таймер опять же замирает.

DenKor, не мог ты показать кусок какого-нить своего кода, где ты реализуешь взаимодействие между нитями?


Название: QTimer
Отправлено: L.Marvell от Декабрь 16, 2005, 19:22
Я тут часики ваяю, дабы немного разобраться с Qt. Так вот, сделал так: в конструкторе виджета на котором отображаются часы
Код:

...
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(repaint()));
timer->start(1000);

а в paintEvent того же виджета собственно вся прорисовка. Часы таскаются по десктопу и мирно себе тикают.

З.Ы. Или может я чего неправильно понял...


Название: QTimer
Отправлено: QCasper от Декабрь 17, 2005, 01:13
Цитата: "L.Marvell"
Я тут часики ваяю, дабы немного разобраться с Qt. Так вот, сделал так: в конструкторе виджета на котором отображаются часы
Код:

...
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(repaint()));
timer->start(1000);

а в paintEvent того же виджета собственно вся прорисовка. Часы таскаются по десктопу и мирно себе тикают.

З.Ы. Или может я чего неправильно понял...


У меня так не прокатило, можно весь исходник?


Название: QTimer
Отправлено: L.Marvell от Декабрь 20, 2005, 16:07
Код:
ClockWindow::ClockWindow()
{
...
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(repaint()));
timer->start(1000);
}

void ClockWindow::paintEvent(QPaintEvent *event)
{
setPalette(QPalette(clockSettings.bgColor));

QDateTime currentDatetime = QDateTime::currentDateTime();

QPainter painter(this);
painter.setFont(clockSettings.font);
QFontMetrics fontMetrics(clockSettings.font);

QString textToDisplay = currentDatetime.toString(clockSettings.currentDatetimeFormat);
QRect endRect = painter.boundingRect(x(), y(), width(), height(), 0, "  "+textToDisplay+"  ");

if (endRect != startRect) {
setGeometry(endRect);
}

if (clockSettings.border) {
painter.setPen(clockSettings.borderColor);
painter.drawRect(0, 0, width() - 1, height() - 1);
}

painter.setPen(clockSettings.fontColor);
painter.drawText((width() - fontMetrics.width(textToDisplay)) / 2, fontMetrics.ascent(), textToDisplay);
}

Некоторые вещи нужно переделать правда, а то ширина сиволов в некоторых шрифтах не совпадает и видно, как окошко меняет размер при разных цифрах, что не есть гут. Но пока не знаю, как сие организовать мудро.