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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Обновление QLCDNumber в цикле?  (Прочитано 12791 раз)
Белый пони
Гость
« : Ноябрь 25, 2009, 23:53 »

Здравствуйте!
Есть программа, которая в консольном режиме считывает байты приходящие на com-порт() и выводить printf'ом на экран, при нажатии ESC программа завершается. Всё работает как надо.

Попытался сделать аналогичную штуку в Qt 4.5  (просто убрал принтфы и заменил на "ui->myLcd->display(int( R[0] ));", fp - file descriptor последовательного порта). Всё интересное в цикле while :

Код:
void myWid::on_myButton_clicked()
{
int i = 0;
char R[5] = {0};

struct termios tp1;
struct termios tp2;

tcgetattr( 0, &tp1);

tp2 = tp1;

  tp2.c_iflag&=~ICRNL;
  tp2.c_lflag&=~ICANON;
  tp2.c_lflag&=~ECHO;
  tp2.c_cc[VMIN ]=1;
  tp2.c_cc[VTIME]=0;
  tp2.c_cc[VINTR]=0xFF;
  tp2.c_cc[VSUSP]=0xFF;
  tp2.c_cc[VQUIT]=0xFF;

tcsetattr( 0, TCSANOW, &tp2);

fd_set set0, set;
FD_ZERO( &set);
FD_SET( fp, &set);
FD_SET(  0, &set);
set0 = set;

while(1)
        {
        if ( select( fp+1, &set, NULL, NULL, NULL ) > 0)
                {
                if( FD_ISSET( fp, &set))
                        {
                        i = read( fp, R, 1);
                        ui->myLcd->display(int( R[0] ));
                        //break;
                        }
                if( FD_ISSET( 0, &set) )
                        {
                        i = read( 0, R, 1);
                        if( R[0] == 27){ break;}
                        }
                }

        set = set0;
        }

tcflush( fp, TCIOFLUSH);
tcsetattr( 0, TCSANOW, &tp1);
}

Байты то считываются, но из них всех на LCDNumber отображается только последний, после выхода из цикла.
Как сделать так, чтобы показания QLCDNumber менялась сразу при получении байта, до завершения цикла?   Пытался добавлять "ui->myLcd->update();", не получилось Грустный

И ещё проблема:  с клавиатуры ничего не принимается с том числе и ESC Грустный
Можно ли вообще читать клавиатуру read'ом в Qt 4.5 ? Что я делаю не так? Грустный
Записан
niXman
Гость
« Ответ #1 : Ноябрь 26, 2009, 00:09 »

Цитировать
отображается только последний, после выхода из цикла.
Так и должно быть. Цикл сообщений заблокирован.

Твой цикл нужно вынести в поток. И все Подмигивающий
Записан
sLiva
Гость
« Ответ #2 : Ноябрь 26, 2009, 00:24 »

Можно в теле цикла вызвать qApp->processEvents()

http://qt.nokia.com/doc/4.5/qcoreapplication.html#processEvents

Но это замедлит скорость работы цикла
Записан
Белый пони
Гость
« Ответ #3 : Ноябрь 26, 2009, 00:57 »

Твой цикл нужно вынести в поток. И все Подмигивающий
Я совсем новичок Улыбающийся Я правильно понял, нужно создать экземпляр QThread и поместить мой цикл в функцию run() ?


Можно в теле цикла вызвать qApp->processEvents()
http://qt.nokia.com/doc/4.5/qcoreapplication.html#processEvents
Но это замедлит скорость работы цикла
Спасибо! Так тоже попробую!
« Последнее редактирование: Ноябрь 26, 2009, 00:59 от Белый пони » Записан
niXman
Гость
« Ответ #4 : Ноябрь 26, 2009, 01:21 »

Цитировать
Можно в теле цикла вызвать qApp->processEvents()
Логически не правильное решение.

Цитировать
нужно создать экземпляр QThread и поместить мой цикл в функцию run() ?
Именно.

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

Что-то типа:
Код
C++ (Qt)
signals:
  void update_signal(int);
 

в run()
Код
C++ (Qt)
while ( true ) {
  ...
  emit update_signal(int( R[0] ));
}
 

и в myWid::myWid()
Код
C++ (Qt)
mythread = new MyThread(this);
connect(mythread, SIGNAL(update_signal(int)), ui->myLcd, SLOT(display(int)));
mythread->start();
 

ничего не упустил?
« Последнее редактирование: Ноябрь 26, 2009, 01:28 от niXman » Записан
Белый пони
Гость
« Ответ #5 : Ноябрь 26, 2009, 02:38 »

Цитировать
Так же нужно декларировать сигнал, который будет испускаться когда хочешь отобразить данные.

Что-то типа:

Спасибо огромное! Смеющийся

Но пока не получилось Грустный

Вот такой mythread.h:
Код:
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class MyThread : public QThread
 {
 public:
     void run();

 signals:
   void update_signal(int);

 };

#endif // MYTHREAD_H
Вот такой mythread.cpp:
Код:
#include "mythread.h"

void MyThread::run()
 {
 int i = 0;
 while( i < 100)
     {
     i++;
     msleep(10);
     emit update_signal( i );
     }
 }

И вот myWid::myWid()
Код:
4    myWid::myWid(QWidget *parent)
5        : QWidget(parent), ui(new Ui::myWidClass)
6    {
7        ui->setupUi(this);
8        mythread = new MyThread(this);
9        connect(mythread, SIGNAL(update_signal(int)), ui->myNum, SLOT(display(int)));
10       mythread->start();
11   }

В последнем на 8-ой строчке находятся 2 ошибки:
/qtest/zikl/blinkwidget.cpp:8: error: ‘mythread’ was not declared in this scope
и
/qtest/zikl/blinkwidget.cpp:8: error: no matching function for call to ‘MyThread::MyThread(blinkWidget* const)’  Грустный

Все инклуды вроде на месте.
Записан
niXman
Гость
« Ответ #6 : Ноябрь 26, 2009, 03:21 »

MyThread должен выглядеть так:
Код
C++ (Qt)
class MyThread : public QThread
{
Q_OBJECT
public:
    MyThread(QObject* o):QThread(o) {
        /** other initialization's are needed put here */
    }
    void run();
 
signals:
  void update_signal(int);
 
};
 
 

В приватную секцию класса myWid
добавь:
Код
C++ (Qt)
MyThread* mythread;
 

Цитировать
8-ой строчке находятся 2 ошибки:
Замени ее на:
Код
C++ (Qt)
mythread = new MyThread(parent);
 
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Ноябрь 26, 2009, 08:35 »

И мои 5 копеек ! Улыбающийся

Если не лень, (как вариант) - то можешь использовать библиотеку QSerialDevice (это не PR Подмигивающий ) : http://fireforge.net/snapshots.php?group_id=199

там смотри пример /examples/sreader

используя этот пример ты можешь просто приконнектиться к сигналу readyRead()
т.е что то типа:
Код:
connect(mySerialDevice, SIGNAL(readyRead()), myLCD, SLOT(updateLCD()));

при этом слот updateLCD()  может выглядеть так:
Код:
void myLCD::updateLCD()
 {
    QByteArray ba = mySerialDevice->read(1);
    myLCD->data = (тут преобразование/приведение типа) ba;
 }


При этом можно потоки вообще не использовать. (вообще это в реале уже нужно смотреть по тому факту - тормозит ли GUI или нет)
« Последнее редактирование: Ноябрь 26, 2009, 08:42 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
spectre71
Гость
« Ответ #8 : Ноябрь 26, 2009, 11:35 »

Конечно выносить длительные расчеты в отдельный Thread лучше всего! Но если скорость отклика GUI во время вычисления не важна, а важна только индикация процесса, то можно сделать проще.

Example(не запускать в конструкторе Улыбающийся):
Код
C++ (Qt)
void MyMainWindow::longStandingCalculation(void) {
 for(int i=0; i<1024*1024*1024; i++) {
   if(i%1000 == 0) {
     updateValue(i);
   }
 }
}
 
void MyMainWindow::updateValue(int value) {
 static QTime CurTime = QTime::currentTime();
 if(CurTime.msecsTo(QTime::currentTime()) >= 100) {
   CurTime = QTime::currentTime();
   ui.label->setText(QString::number(value));
   QApplication::processEvents();
 }
}
« Последнее редактирование: Ноябрь 26, 2009, 11:39 от Spectre » Записан
Белый пони
Гость
« Ответ #9 : Ноябрь 26, 2009, 11:39 »

MyThread должен выглядеть так:

Всё подправил, теперь выдаётся одна ошибка в mythread.cpp:

/qtest/zikl/mythread.cpp:10: undefined reference to `MyThread::update_signal(int)'
 error: collect2: ld returned 1 exit status

Код:
1   #include "mythread.h"
2   
3   void MyThread::run()
4   {
5    int i = 0;
6    while( i < 100)
7        {
8        i++;
9        msleep(10);
10       emit update_signal( i );
11       }
12   }

Пытался гуглить, пишут надо подключать библиотеки,но я не понял какие и как ( использую Qt Creator).


Цитировать
И мои 5 копеек !

Если не лень, (как вариант) - то можешь использовать библиотеку QSerialDevice (это не PR Подмигивающий ) : http://fireforge.net/snapshots.php?group_id=199

там смотри пример /examples/sreader

Спасибо!
Пока запас быстродействия есть.

Но самый быстрый вариант это с использованием потока?
« Последнее редактирование: Ноябрь 26, 2009, 11:43 от Белый пони » Записан
niXman
Гость
« Ответ #10 : Ноябрь 26, 2009, 11:44 »

Тот файл в котором декларирован MyThread, добавь к целям moc
Записан
Белый пони
Гость
« Ответ #11 : Ноябрь 26, 2009, 11:53 »

Тот файл в котором декларирован MyThread, добавь к целям moc
А как? Улыбающийся Добавить его в файл .pro ? Он уже там есть:
Код:
TARGET = zikl
TEMPLATE = app
SOURCES += main.cpp \
    myWid.cpp \
    mythread.cpp
HEADERS += myWid.h \
    mythread.h
FORMS += myWid.ui
Записан
niXman
Гость
« Ответ #12 : Ноябрь 26, 2009, 11:59 »

Кстати, Q_OBJECT у тебя вписан сразу за открывающейся фигурной скобкой?
Записан
Белый пони
Гость
« Ответ #13 : Ноябрь 26, 2009, 12:07 »

Кстати, Q_OBJECT у тебя вписан сразу за открывающейся фигурной скобкой?

Ай. нет. Сейчас добавил. получилось так:

Код:
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class MyThread : public QThread
 {

    Q_OBJECT

 public:
    MyThread(QObject* o):QThread(o) {     }
     void run();

 signals:
   void update_signal(int);

 };

#endif // MYTHREAD_H

Теперь добавилась ещё одна строчка в сообщении об ошибке:
Цитировать
/qtest/zikl/mythread.h:12: undefined reference to `vtable for MyThread'
/qtest/zikl/mythread.cpp:10: undefined reference to `MyThread::update_signal(int)'
error: collect2: ld returned 1 exit status
Грустный
Записан
niXman
Гость
« Ответ #14 : Ноябрь 26, 2009, 12:21 »

Цитировать
Теперь добавилась ещё одна строчка в сообщении об ошибке:
О!, Это уже хорошо!

Почисть от "продуктов" компиляции. Потом qmake и make.
И усё.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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