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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Стандартные потоки C++ в Qt  (Прочитано 6716 раз)
SydoQQ
Гость
« : Апрель 26, 2017, 12:02 »

Доброго времени суток!
Столкнулся с одной проблемой, при использовании стандартных потоков в Qt, использую версию 5.7. Нашел строку, из-за которой происходит крах программы, это строка 49. При комментировании ее, естественно программа работает на ура. И самый интересный момент, если в функию
Код:
LineItem->setPos(0,returnLinePosition());
всегда передавать константу, например вот так
Код:
LineItem->setPos(0,0);
, или
Код:
 int n=100; LineItem->setPos(0,n);
, то программа тоже работает на ура. Испробовал много чего, но не могу понять, почему так происходит, надаеюсь кто то поможет мне решить данную проблему. Пробывал использовать таймер, но результат получается не такой, как хотелась бы.
Вот полный код .cpp
Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //setWindowFlags(Qt::FramelessWindowHint);

    Scene=new QGraphicsScene(this);
    View=new QGraphicsView(Scene);
    setGeometry(300,100,400,600);
    View->setParent(this);
    setMaximumSize(width(),height());
    View->setFixedSize(width(),height());
    View->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    View->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    LineItem=Scene->addRect(QRect(-(width()/2)+1,0,width()-2,0),QPen(Qt::blue,2));

    H=height();
    LinePosition=600;
    backGroundGradient=new QLinearGradient(QPoint(0,H),QPoint(0,0));
    for(int i=0;i<3;i++)
    {
        FC[i]=0;
        SC[i]=0;
        LC[i]=0;
    }
    std::thread BackGroundTH{&MainWindow::on_BACKgroundChange,this};
    BackGroundTH.detach();

    std::thread MoveLineTH{&MainWindow::Line_Move,this};
    MoveLineTH.detach();

//    timer=new QTimer(this);
//    connect(timer,SIGNAL(timeout()),this,SLOT(Line_Move()));
//    timer->start(100);

}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::newPosition_line()
{   
    linePositionMutex.lock();
    LineItem->setPos(0,returnLinePosition());
    linePositionMutex.unlock();

}
void MainWindow::Line_Move()
{
    //timer->stop();
    int newPosition=0;
    int C=1;
    linePositionMutex.lock();
    int n=1+qrand()%100;
    for(int i=0;i<n;i++)
    {
        newPosition+=qrand()%(H*2);
    }
    linePositionMutex.unlock();
    newPosition/=n;
    if(LinePosition<newPosition)
        C=1;
    else
        C=-1;
    for(int i=0;i<fabs(LinePosition-newPosition);i++)
    {
        LinePosition+=C*1;
        linePositionMutex.lock();
        QThread::msleep(10);
        linePositionMutex.unlock();
        newPosition_line();
    }
    //timer->start(100);
    Line_Move();
}

int MainWindow::returnLinePosition()
{
    return LinePosition-(H-1);
}

void MainWindow::on_backgroundColor_change()
{
    backGroundMutex.lock();
    Scene->setBackgroundBrush(returnGradient());
    backGroundMutex.unlock();
}

void MainWindow::on_BACKgroundChange()
{
    int masF[3]={0,0,0};
    int masS[3]={0,0,0};
    int C=1;
        srand(QTime::currentTime().toString("s").toInt());
        backGroundMutex.lock();
        for(int i=0;i<3;i++)
        {
            masF[i]=rand()%255;
            masS[i]=rand()%255;
        }
        backGroundMutex.unlock();
        for(int i=0;i<3;i++)
        {
            if(FC[i]<masF[i])
                C=1;
            else
                C=-1;
            for(int j=0;j<fabs(FC[i]-masF[i]);j++)
            {
                backGroundMutex.lock();
                QThread::usleep(100000);
                backGroundMutex.unlock();
                FC[i]+=C*1;
                backGroundGradient->setColorAt(0,QColor(SC[0],SC[1],SC[2]));
                backGroundGradient->setColorAt(0.9,QColor(FC[0],FC[1],FC[2]));
                on_backgroundColor_change();
            }
        }
        for(int i=0;i<3;i++)
        {
            if(SC[i]<masS[i])
                C=1;
            else
                C=-1;
            for(int j=0;j<fabs(SC[i]-masS[i]);j++)
            {
                backGroundMutex.lock();
                QThread::usleep(100000);
                backGroundMutex.unlock();
                SC[i]+=C*1;
                backGroundGradient->setColorAt(0,QColor(SC[0],SC[1],SC[2]));
                backGroundGradient->setColorAt(0.9,QColor(FC[0],FC[1],FC[2]));
                on_backgroundColor_change();
            }
        }
        on_BACKgroundChange();
}

QGradient MainWindow::returnGradient()
{
    return *backGroundGradient;
}

.h файла
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <thread>
#include <mutex>
#include <QThread>
#include <QTime>
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void newPosition_line();
    void Line_Move();
    int returnLinePosition();
    void on_backgroundColor_change();
    void on_BACKgroundChange();
    QGradient returnGradient();
public slots:
    //void Line_Move();
signals:

private:
    Ui::MainWindow *ui;
    QGraphicsScene *Scene;
    QGraphicsView *View;
    QGraphicsItem *LineItem;
    int LinePosition;
    int H;
    int FC[3];
    int SC[3];
    int LC[3];
    QGradient *backGroundGradient;
    std::mutex backGroundMutex;
    std::mutex linePositionMutex;
    //QTimer *timer;

};

#endif // MAINWINDOW_H
Сообщения которое пишет отладчик
Код:
QObject::startTimer: Timers cannot be started from another thread
И я вижу что проблема с таймером, но я не понимаю откуда она возникает.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Апрель 26, 2017, 12:13 »

Ты неправильно работаешь с потоками.
1. Используй QThread
2. С GUI можно работать напрямую только из основного потока, другие потоки должны использовать сигнал/слоты.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
SydoQQ
Гость
« Ответ #2 : Апрель 26, 2017, 15:28 »

Ты неправильно работаешь с потоками.
1. Используй QThread
2. С GUI можно работать напрямую только из основного потока, другие потоки должны использовать сигнал/слоты.
Тогда возникает вопрос, почему QGraphicsScene работает нормально, хотя тоже изменяется в потоке. И я пробывал использовать QThread, однако у меня происходило зацикливание и крах программ, может я не правильно его использовал, но я прочитал достаточно статей, и на хабре и у шлея. Не могли бы вы скинуть рабочий пример?!
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #3 : Апрель 26, 2017, 22:20 »

QGraphicsScene это модель с данными, сама она не рисует в GUI, этим QGraphicsView занимается
Записан

SydoQQ
Гость
« Ответ #4 : Апрель 27, 2017, 06:45 »

QGraphicsScene это модель с данными, сама она не рисует в GUI, этим QGraphicsView занимается
Тогда не могли бы вы подсказать, в каком мне направлении копать, что бы все работало нормально?!
« Последнее редактирование: Апрель 27, 2017, 09:10 от SydoQQ » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #5 : Апрель 27, 2017, 09:08 »

Я просто ответил на вопрос Улыбающийся
Цитировать
Тогда возникает вопрос, почему QGraphicsScene работает нормально, хотя тоже изменяется в потоке.
Записан

Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Апрель 27, 2017, 09:44 »

Тогда возникает вопрос, почему QGraphicsScene работает нормально, хотя тоже изменяется в потоке.
Как говорят
Цитировать
Тестирование может показать наличие багов, но не их отсутствие.
Т.е. если какая-то ветка у Вас работает - это совсем не значит что проблем нет

Если исходники больше странички текста или их хотя бы 2, то прочитать/осмыслить их на форуме трудно, проще игнорировать этот топик. Выкладывайте в виде zip архива с компилируемым примером внутри

Чего искать приключений со "стандартными потоками"? С QThread возможно ответят 10 человек т.к. знают и работают с этим, а с std::thread - ну может один. И что там хорошего в std::thread?
Код:
std::thread BackGroundTH{&MainWindow::on_BACKgroundChange,this};
BackGroundTH.detach();

std::thread MoveLineTH{&MainWindow::Line_Move,this};
MoveLineTH.detach();
Так Вы запустили нитки для одноразовой работы - и теперь должны сами возюкаться как организовать их ожидание. Зачем если QThread это делает по дефаулту ?

И в любом случае святая правда что хватать UI из НЕ главной нитки - НИЗЗЯ!

Тогда не могли бы вы подсказать, в каком мне направлении копать, что бы все работало нормально?!
Перейти на QThread и задействовать слот/сигнал
Записан
SydoQQ
Гость
« Ответ #7 : Апрель 27, 2017, 16:40 »

Тогда возникает вопрос, почему QGraphicsScene работает нормально, хотя тоже изменяется в потоке.
Как говорят
Цитировать
Тестирование может показать наличие багов, но не их отсутствие.
Т.е. если какая-то ветка у Вас работает - это совсем не значит что проблем нет

Если исходники больше странички текста или их хотя бы 2, то прочитать/осмыслить их на форуме трудно, проще игнорировать этот топик. Выкладывайте в виде zip архива с компилируемым примером внутри

Чего искать приключений со "стандартными потоками"? С QThread возможно ответят 10 человек т.к. знают и работают с этим, а с std::thread - ну может один. И что там хорошего в std::thread?
Код:
std::thread BackGroundTH{&MainWindow::on_BACKgroundChange,this};
BackGroundTH.detach();

std::thread MoveLineTH{&MainWindow::Line_Move,this};
MoveLineTH.detach();
Так Вы запустили нитки для одноразовой работы - и теперь должны сами возюкаться как организовать их ожидание. Зачем если QThread это делает по дефаулту ?

И в любом случае святая правда что хватать UI из НЕ главной нитки - НИЗЗЯ!

Тогда не могли бы вы подсказать, в каком мне направлении копать, что бы все работало нормально?!
Перейти на QThread и задействовать слот/сигнал
Пробывал сделать как вы рекомендовали, но я не как не могу добится бесконечного цикла с использованием QThread, то ли я не правильно что то делаю, то ли у меня создается новый поток, а главный просто виснет, это первое. А второе если использовать сигнал/слоты приложение то работает, но у него нету того быстродействия которое нужно, явно видно, что приложение подвисает. Как мне решить эту проблему без потери производительности?! Возможно есть еще какие то средства которые помогу решить эту задачу?!
« Последнее редактирование: Апрель 27, 2017, 16:45 от SydoQQ » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Апрель 28, 2017, 12:12 »

Цитированием не злоупотребляйте, отвечаете на последнюю строку - ее и цитируйте, или вообще ничего если и так ясно о чем речь. Давайте форум не захламлять
Пробывал сделать как вы рекомендовали, но я не как не могу добится бесконечного цикла с использованием QThread, то ли я не правильно что то делаю, то ли у меня создается новый поток, а главный просто виснет, это первое. А второе если использовать сигнал/слоты приложение то работает, но у него нету того быстродействия которое нужно, явно видно, что приложение подвисает. Как мне решить эту проблему без потери производительности?! Возможно есть еще какие то средства которые помогу решить эту задачу?!
Здесь однозначно: плохо пробОвали. Напр как там можно НЕ добиться бесконечного цикла - хз. Выкладывайте Ваши попытки с QThread (с учетом сказанного выше), думаю тогда Вам быстро помогут
Записан
SydoQQ
Гость
« Ответ #9 : Май 02, 2017, 10:46 »

Всем спасибо, кто принимал участие в обсуждении этой темы. Добился требуемого результат с использованием контекста рисования, без потери производительности, кому будет интересен код, могу скинуть. Считаю что тема может быть закрыта.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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