Система такая:
Вкладка унаследована от QWidget. НА ней размещены элементы, как показано на рисунке.
После открытия порта, становятся доступны кнопки "Start Vertical", "Start Horizontal" При нажатии на каждую из кнопок запускается соответствующий поток выполнения вращения. Вот некоторое описание использующихся классов:
/// Класс потока - вращение вокруг горизонтальной оси заданное количество раз
class VerticalRotation: public QThread
{
Q_OBJECT
private:
INFO_TO_EXTERN_DEVICE inf_to_ed_packet; ///< пакет данных внешнему устройству в режиме авто управления
INFO_FROM_EXTERN_DEVICE inf_from_ed_packet; ///< пакет данных от внешнего устройства в режиме авто управления
const int MAXBYTES; ///< константа максимального количества байт
int number_rotate; ///< количество вращений
ImitatorTSL* imitTsl; ///< указатель на класс главного окна
bool terminated; ///< флаг сигнализации о том, что функцию run надо прервать
bool checked_pause; ///< флаг нажатия на кнопку паузы
private:
void readAngleElevation(int& geted_angle_elev, double limit);
void cycleRotate();
protected:
virtual void run();
signals:
void valueDecrement(int);
void timeout(int);
private slots:
void terminateCycle(int index) { terminated = true; }
public:
VerticalRotation(QObject *parent);
~VerticalRotation() {}
void tsl(ImitatorTSL* im) { imitTsl = im; }
ImitatorTSL* tsl() const { return imitTsl; }
int rotNumber() const { return number_rotate; }
void setRotNumber(const int num) { number_rotate = num; }
INFO_TO_EXTERN_DEVICE autoControl();
void fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp);
void setToEDInfo(const INFO_TO_EXTERN_DEVICE& ed) { inf_to_ed_packet = ed; }
void setFromEDInfo(const INFO_FROM_EXTERN_DEVICE& ed) { inf_from_ed_packet = ed; }
INFO_TO_EXTERN_DEVICE toEDInfo() { return inf_to_ed_packet; }
INFO_FROM_EXTERN_DEVICE fromEDInfo() { return inf_from_ed_packet; }
void setTerminate(bool bf) { terminated = bf; }
bool isTeminated() const { return terminated; }
void setChecked(bool value) { checked_pause = value; }
};
/// Класс потока - вращение вокруг вертикальной оси заданное количество раз
class HorizontalRotation: public QThread
{
Q_OBJECT
private:
INFO_TO_EXTERN_DEVICE inf_to_ed_packet; ///< пакет данных внешнему устройству в режиме авто управления
INFO_FROM_EXTERN_DEVICE inf_from_ed_packet; ///< пакет данных от внешнего устройства в режиме авто управления
const int MAXBYTES; ///< константа максимального количества байт
int number_rotate; ///< количество вращений
ImitatorTSL* imitTsl; ///< указатель на класс главного окна
bool terminated; ///< флаг сигнализации о том, что функцию run надо прервать
bool checked_pause; ///< флаг нажатия на кнопку паузы
private:
void readAzimuth(int& geted_azimuth, double limit);
void cycleRotate();
protected:
virtual void run();
signals:
void valueDecrement(int);
void timeout(int);
private slots:
void terminateCycle(int index) { terminated = true; }
public:
HorizontalRotation(QObject *parent);
~HorizontalRotation() {}
void tsl(ImitatorTSL* im) { imitTsl = im; }
ImitatorTSL* tsl() const { return imitTsl; }
int rotNumber() const { return number_rotate; }
void setRotNumber(const int num) { number_rotate = num; }
INFO_TO_EXTERN_DEVICE autoControl();
void fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp);
void setToEDInfo(const INFO_TO_EXTERN_DEVICE& ed) { inf_to_ed_packet = ed; }
void setFromEDInfo(const INFO_FROM_EXTERN_DEVICE& ed) { inf_from_ed_packet = ed; }
INFO_TO_EXTERN_DEVICE toEDInfo() { return inf_to_ed_packet; }
INFO_FROM_EXTERN_DEVICE fromEDInfo() { return inf_from_ed_packet; }
void setTerminate(bool bf) { terminated = bf; }
bool isTeminated() const { return terminated; }
void setChecked(bool value) { checked_pause = value; }
};
Вот класс, где есть слоты выполнения нажатия на кнопки и сами потоки:
/// Класс отображения параметров внешних устройств управления в автоматическом режиме
class AutoControl: public QWidget, public AutoControlClass
{
Q_OBJECT
private:
INFO_TO_EXTERN_DEVICE inf_to_ed_packet; ///< пакет данных внешнему устройству в режиме авто управления
const int MAXBYTES; ///< константа максимального количества байт
ImitatorTSL* imitTsl; ///< указатель на класс главного окна
HorizontalRotation* horizontal; ///< вращение в горизонтальной плоскости (дополнительный поток)
VerticalRotation* vertical; ///< вращение в вертикальной плоскости (дополнительный поток)
time_t started_time_horiz; ///< начальное время при перемещении по горизонтали
time_t started_time_vert; ///< начальное время при перемещении по вертикали
time_t mean_time_horiz; ///< среднее время при перемещении по горизонтали
time_t mean_time_vert; ///< среднее время при перемещении по вертикали
bool is_working_horizontal; ///< флаг, сигнализирующий о работе в горизонтальной проекции
bool is_working_vertical; ///< флаг, сигнализирующий о работе в вертикальной проекции
private:
void readAzimuth(int& geted_azimuth, double limit);
void readAngleElevation(int& geted_angle_elev, double limit);
private slots:
void startHorizontalCycles();
void startVerticalCycles();
void pauseHorizontalCycles();
void pauseVerticalCycles();
void horizCountChange(int value);
void vertCountChange(int value);
public:
AutoControl(QWidget *parent = 0);
~AutoControl();
INFO_TO_EXTERN_DEVICE autoControl();
void fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp);
void checkPacket();
void tsl(ImitatorTSL* im)
{ imitTsl = im; if(horizontal) horizontal -> tsl(im); if(vertical) vertical -> tsl(im); }
ImitatorTSL* tsl() const { return imitTsl; }
};
Функции запуска потоков:
/// Запуск циклического перемещения по горизонтальной плоскости
void AutoControl::startHorizontalCycles()
{
horizontal -> setRotNumber(spinHorizCycles -> value());
mean_time_horiz = 0;
time(&started_time_horiz);
horizontal -> start();
horizTimer -> setText(QString("00"));
if(spinHorizCycles -> value() > 1) btnPauseHorizontal -> setEnabled(true);
}
/// Запуск циклического перемещения по вертикальной плоскости
void AutoControl::startVerticalCycles()
{
vertical -> setRotNumber(spinVertCycles -> value());
mean_time_vert = 0;
time(&started_time_vert);
vertical -> start();
vertTimer -> setText(QString("00"));
if(spinVertCycles -> value() > 1) btnPauseVertical -> setEnabled(true);
}