добавление в программу QQueue сбоев - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь нарисовать множество Мандельброта в QT. Все сделано, и выглядит хорошо, но ему нужно некоторое время, чтобы рассчитать цвет пикселя, поэтому я хотел разделить изображение на 4 и дать расчеты для отдельных потоков. Потоки работают, и проблема в следующем: после математики я хочу создать объект (мою структуру Pixel) и передать его в очередь с помощью метода enqueue (), который из моего paintEvent получает x, y и цвет для рисования. Добавление в очередь создает:

18:09:15: The program has unexpectedly finished.
18:09:15: The process was ended forcefully.

без него, потоки работают нормально

метод Plot :: get_iterations_from_thread () в Plot.cpp

#include "plot.h"


QMutex Plot::mutex;

Plot::Plot(QWidget *parent) : QWidget(parent)
{ 
    connect(this,
            SIGNAL(get_iterations(unsigned int, unsigned int, int, int)),
            this,
            SLOT(get_iterations_from_thread(unsigned int, unsigned int, int, int)),
            Qt::ConnectionType::QueuedConnection);

    th1.set_values(0, (width/2)-1,
                   0, (height/2)-1,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH1");
    std::cout << th1.name + " values setted" << std::endl;

    th2.set_values((width/2)+1, width,
                   0, (height/2)-1,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH2");
    std::cout << th2.name + " values setted" << std::endl;

    th3.set_values(0, (width/2)-1,
                   (height/2)+1, height,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH3");
    std::cout << th3.name + " values setted" << std::endl;

    th4.set_values((width/2)+1, width,
                   (height/2)+1, height,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH4");
    std::cout << th4.name + " values setted" << std::endl;

    th1.start();
    th2.start();
    th3.start();
    th4.start();
}

void Plot::get_iterations_from_thread(unsigned int iterations, unsigned int max_check, int x,  int y)
{
    mutex.lock();
    std::cout << "generating pixel" << std::endl;
    Pixel pix(x, y, iterations, max_check);
    pixels.enqueue(pix);
    std::cout << "pixel generated!" << std::endl;
    mutex.unlock();
}

void Plot::paintEvent(QPaintEvent *e)
{
    std::cout << "paintEvent" << std::endl;
    mutex.lock();
    QPainter painter;
    painter.begin(this);
    QPen pen(Qt::white);
    pen.setWidth(1);
    pen.setCapStyle(Qt::SquareCap);
    if(!pixels.isEmpty()){
        foreach(Pixel pixel, pixels){
            std::cout << "painting " + std::to_string(pixel.get_x()) + "," + std::to_string(pixel.get_y()) << std::endl;
            pen.setColor(pixel.get_color());
            painter.setPen(pen);
            painter.drawPoint(pixel.get_x(), pixel.get_y());
            pixels.dequeue();
        }
    }
    painter.end();

    mutex.unlock();

}

используя его:

void CountingThread::run()
{
    Plot * window = dynamic_cast<Plot*>(parent());
    for(int x=x_start; x<x_stop; ++x){
        for(int y=y_start; y<y_stop; ++y){

            std::complex<double> c(cxmin + x/(width-1.5)*(cxmax-cxmin), cymin + y/(height-0.5)*(cymax-cymin));
            std::complex<double> z(0,0);
            unsigned int iterations;
            for (iterations = 0; iterations < max_check && std::abs(z) < 2.0; ++iterations) {
                z = z*z + c;
            }

            std::cout << name + " done for: " + std::to_string(x) + "," + std::to_string(y) + " " << std::endl;
            //emit(window->get_iterations(iterations, max_check, x, y));
            window->get_iterations_from_thread(iterations, max_check, x, y);
            std::cout << name + " emitted" << std::endl;
        }
    }

}

и сюжет.ч

#ifndef PLOT_H
#define PLOT_H

#include <QWidget>
#include <QPainter>

#include <iostream>

#include "countingthread.h"
#include "pixel.h"

class Plot : public QWidget
{
    Q_OBJECT
public:
    explicit Plot(QWidget *parent = nullptr);
    static QMutex mutex;
    QQueue<Pixel> pixels;

private:
    void Plot::paintEvent(QPaintEvent *e) override;
    CountingThread th1;
    CountingThread th2;
    CountingThread th3;
    CountingThread th4;

    int width = 820;
    int height = 640;
    double cxmin = -1.5;
    double cxmax = 0.5;
    double cymin = -1.0;
    double cymax = 1.0;
    unsigned int max_check = 100;

signals:
    void get_iterations(unsigned int iterations, unsigned int max_check, int x,  int y);

public slots:
    void get_iterations_from_thread(unsigned int iterations, unsigned int max_check, int x,  int y);
};

#endif // PLOT_H

кстати: функция emit комментируется, потому что она не работает, и я не знаю, почему, что меня очень расстраивает

...