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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Программа, отрисовывающая точки тремя потоками  (Прочитано 3153 раз)
libertas
Гость
« : Март 26, 2014, 22:32 »

Всем привет!

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

Должны в итоги получится 3 прерывистые линии, каждая идущая на своем уровне:

Вот что я сделал:

В хедере:

класс главного окна:

Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <windows.h>
#include <QPainter>
#include <QColor>

namespace Ui {
class MainWindow;
}

class MyPoint;
class MyData;

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    //bool res = SetProcessAffinityMask(GetCurrentProcess(), 1);
    void paintVector();
    static DWORD WINAPI ThreadFunction(LPVOID lpParam);
protected:
    void virtual paintEvent(QPaintEvent*);

private:
    Ui::MainWindow *ui;
    static QVector<MyPoint> vPoints;
    static int currentX;

    HANDLE handles[3];
    static CRITICAL_SECTION* crSecPtr;

    static MyData* th1Ptr;
    static MyData* th2Ptr;
    static MyData* th3Ptr;
private slots:
    void RepaintSlot();
    void on_NoSync_clicked();
};

создал вспомагательный класс для точки и данных, которые будут передаваться в потоковую функцию:

Код:
class MyPoint {
    QColor m_col;
    QPoint m_pt;
public:
    MyPoint(const QPoint& pt = QPoint(), QColor col = QColor(Qt::red));
    void paint(QPainter& pe);
    ~MyPoint(){}

friend class MainWindow;
};

class MyData : public QObject {
    Q_OBJECT
    int y;
    int maxX;
    QColor col;
    HANDLE hObject;
public:
    MyData(int, int, QColor, HANDLE);
    ~MyData(){}
    void SendNeedReDraw(MyPoint&);
signals:
    void needRedraw(MyPoint&);
};

А вот, что получилось написать в .срр:

Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"

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

}

QVector<MyPoint> MainWindow::vPoints;

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent* pe) {
    QPainter p(this);
    if (vPoints.isEmpty()) return;
    for (int i = 0; i < vPoints.size(); i++){
        vPoints[i].paint(p);
    }
}

DWORD WINAPI MainWindow::ThreadFunction(LPVOID myData){
      MyPoint newPoint(QPoint(currentX, myData->y), myData->col);
      vPoints.append(newPoint);
      myData->SendNeedReDraw(myData);
}

void MainWindow::RepaintSlot(){
    repaint();
}

MyPoint::MyPoint(const QPoint &pt, QColor col){
    m_pt = pt;
    m_col = col;
}

void MyPoint::paint(QPainter& p){
    QPen pen(m_col);
    pen.setWidth(5);
    p.setPen(pen);
    p.drawPoint(m_pt);
}

MyData::MyData(int y, int maxX, QColor col, HANDLE hObject){
    this->y = y;
    this->maxX = maxX;
    this->col = col;
    this->hObject = hObject;
}

void MyData::SendNeedReDraw(MyPoint& point){
    emit needRedraw(point);
}

void MainWindow::on_NoSync_clicked()
{
}

Я не знаю, что дальше ещё написать / исправить, что у меня запускались три потока и каждый рисовал свою линию на своем уровне и они рисовались попеременно.

Буду очень благодарен, если кто подскажет.

Спасибо.
Записан
vizir.vs
Гость
« Ответ #1 : Март 27, 2014, 10:46 »

Используй mutex, для того, чтобы каждый поток рисовал попеременно. В начале функции Paint он будет у тебя блокироваться, в конце разблокироваться. Судя по описанию это лаба, можно не заморачиваться с QThread и воспользоваться QtConcurrent::run. Туда ты будешь передавать ту функцию, которую надо выполнить в отдельном потоке.
Записан
libertas
Гость
« Ответ #2 : Март 27, 2014, 11:16 »

Спасибо.

Только я не понимаю, я объявил потоковую функцию:

 
Код:
static DWORD WINAPI ThreadFunction(LPVOID lpParam);

Где мне её вызывать, чтоб запустить поток и как? И что в ней должно быть реализовано?
То есть сейчас у меня такой код в ней:

Код:
DWORD WINAPI MainWindow::ThreadFunction(LPVOID myData){
      MyPoint newPoint(QPoint(currentX, myData->y), myData->col);
      vPoints.append(newPoint);
      myData->SendNeedReDraw(myData);
}

но я не понимаю во-первых, что передавать ей в качестве параметра. У неё тип lpvoid, а во-вторых  как работает вызов метода:

myData->SendNeedReDraw(myData);

то есть как она будет рисовать.
Записан
vizir.vs
Гость
« Ответ #3 : Март 27, 2014, 11:36 »

у тебя будет функция типа
Код:
void DrawPoint(QWidget* widget, const QVector<QPoint>& point)
{
 for (size_t i = 0; i < point.size(); i++)
{
блокируешь мьютекс
рисуешь точку на виджете
разблокировал мьютекс
}
}

Дальше ты через
Код:
qtconcurrent::run(DrawPoint, myWidget, myPoint); 
запускаешь выполнение функции DrawPoint в отдельном потоке.
Записан
libertas
Гость
« Ответ #4 : Март 27, 2014, 14:09 »

У меня  в главном окне приложения:
 перегружен метод перерисовки:

Код:
void MainWindow::paintEvent(QPaintEvent* pe) {
    QPainter p(this);
    if (vPoints.isEmpty()) return;
    for (int i = 0; i < vPoints.size(); i++){
        vPoints[i].paint(p);
    }
}

Сам метод paint реализован вот так( точка рисуется):

Код:
void MyPoint::paint(QPainter& p){
    QPen pen(m_col);
    pen.setWidth(5);
    p.setPen(pen);
    p.drawPoint(m_pt);
}

У меня есть кнопка No_sync:

Код:
void MainWindow::on_NoSync_clicked()
{
}

Здесь я так понимаю мне нужно прописать запуск потоков.

Нужно запустить через функцию CreateThread. Мне для начала нужно просто их запустить без мьютексов. Посмотреть как потоки будут распределять процессорное время и рисоваться.

Для этого мне нужно в эту функцию передать потоковую функцию.

Спасибо, стало понятней, буду разбираться дальше!



Записан
Bepec
Гость
« Ответ #5 : Март 27, 2014, 14:21 »

Ну и если ты хочешь использовать Qt, тогда лучше тебе бы использовать QThread или moveToThread. А то сейчас ты используешь winApi Улыбающийся
Записан
libertas
Гость
« Ответ #6 : Март 27, 2014, 14:46 »

Согласен. Просто у нас лабы по winapi, а делать их нужно в qt. Поэтому использую функции winapi  и классы qt для графики.
Записан
libertas
Гость
« Ответ #7 : Март 27, 2014, 14:56 »

Запускать потоки стал так:

может кому - когда пригодится:

Код:
QColor arColor[3] = {Qt::red, Qt::green, Qt::blue};
void MainWindow::on_NoSync_clicked()

{
         // 1)подготовка к новому рисованию,почистить вектор, установиться в начало рисования, перерисовать область
        vPoints.clear();
        currentX = 0;
        repaint();

        const int n = 3; // задаем количество потоков
        int  y = 200;      //  задаем начальную координату y
        int npoints = geometry().width()/4; //  задаем количество точек для рисования, например так или задаем значение
        // объект синхронизации создан ранее в конструкторе
        //создаем массив динамических объектов (уничтожать будем при завершении потока), которые будем передавать в поток



        for (int i=0; i<n; i++)
        {

            //создаются три динамических объекта MyData    (y,maxX,HANDLE hObject)
           
            pdata[i]= new MyData(y, npoints, arColor[i], 0);
            y+=50;
            //потоки для рисования создаем в заснувшем состоянии
            // потоковой функции передается своя структура данных
            handles[i] = ::CreateThread(0,0,ThreadFunction, pdata[i],CREATE_SUSPENDED,0);

            // связываем сигнал от  объекта   pdata[i]   со слотом  в  MainWindow, который добавляет точку в вектор и перерисовывает окно
            QObject::connect(pdata[i], SIGNAL(needRedraw(MyPoint)), this, SLOT(addPoint(MyPoint)), Qt::BlockingQueuedConnection);
         }
         for (int i=0; i<n; i++)
         {
         //пробуждаются потоки
            ResumeThread(handles[i]);

          //закрываем дескрипторы потоков
            CloseHandle(handles[i]);
         }
}

Единственное не очень понял, что значит параметр Qt::BlockingQueuedConnection.
Может, кто знает?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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