Seite 1 von 1

QThread implementieren

Verfasst: 25. Mai 2010 18:37
von marvel
hallo,
ich habe einen converter geschrieben, der aus einer xml datei daten filtert, diese zwischenspeichert und dann umkonvertiert. bisher lief alles ohne probleme, jedoch friert für den zeitraum der konvertierung die gesamte GUI ein. der benutzer soll aber weiterhin die möglichkeit haben die GUI zu benutzen. ich habe gelesen das qthread dort abhilfe schaffen soll. eine implementierung habe ich folgendermaßen bewerkstelligt :

Code: Alles auswählen

converter.cpp:

void Converter::startThread()
{
   qDebug() << "START";
   thread->start();	
}


converter_thread.h:

#ifndef CONVERTER_THREAD_H
#define CONVERTER_THREAD_H

#include <QThread>
#include <QDebug>

class Converter_Thread : public QThread
{
	Q_OBJECT

public:
	Converter_Thread();
	~Converter_Thread();

protected:
	void run();

private:
	
};

#endif // CONVERTER_THREAD_H


converter_thread.cpp:

#include "converter_thread.h"

Converter_Thread::Converter_Thread()
{	
	qDebug() << "THREAD";
}

Converter_Thread::~Converter_Thread()
{

}

void Converter_Thread::run()
{
	qDebug() << "RUN";
}
ich rufe also aus der klasse converter via button den slot startThread() auf. dieser greift auf das objekt thread zu und ruft den slot start() auf. folglich wird unter der funktion run() alles ausgeführt.

jetzt habe ich das problem das in meiner converterklasse einige berechnungen gemacht werden die aber für den thread relevant sind. diese müsste ich dann nicht in der converterklasse selber sondern in der run() funktion durchführen. die frage die ich mir nun stelle ist wie ich den thread und den converter richtig zusammenbringe.

hier mal die berechnungen die gemacht werden. es sind objekte dabei die der thread nicht kennen kann bzw nicht zugreifen kann. wie soll ich also den ablauf in die run() funktion bekommen ?

Code: Alles auswählen

void Converter::parse()
{    
	qDebug() << "PARSE";

    tags.append("motorway");
	tags.append("motorway_link");

	message = "Daten werden gelesen...";
	gui_converter->getTextEdit()->setText(message);							

	parser->readFile(fileName, &tags);

	numberOfNodes = 0;
	numberOfWays = 0;
	numberOfRelations = 0;

	tags.clear();
}

void Converter::convert()
{
	qDebug() << "CONVERT";

	message = message + "\nDaten werden konvertiert...";
	gui_converter->getTextEdit()->setText(message);

    QFile file("D:/Projects/data.oac");
    if (file.open(QFile::WriteOnly | QFile::Truncate))
    {
        QDataStream out(&file);

        out << QString("OpenAeroChart");

		QHashIterator<QString, OSM_Node*> iNode(*parser->getConvertableNodes());
		while (iNode.hasNext()) 
		{
			iNode.next();
			out << QString("node") << iNode.key();
			out << QString("pos") << iNode.value()->getLatitude() << iNode.value()->getLongitude();

			numberOfNodes++;
		}

		QHashIterator<QString, OSM_Way*> iWay(*parser->getConvertableWays());
		while (iWay.hasNext()) 
		{
			iWay.next();
			out << QString("way") << iWay.key();
	
			for(int k = 0; k < iWay.value()->getReferenceList()->size(); k++)
			{
				if(parser->getNodeContainer()->contains(iWay.value()->getReferenceList()->value(k)))
				{
					QList<QString> *tempList;

					tempList = math->convertCoordinates(parser->getNodeContainer()->value(iWay.value()->getReferenceList()->value(k))->getLatitude(),
														parser->getNodeContainer()->value(iWay.value()->getReferenceList()->value(k))->getLongitude());


					out << QString("pos") << tempList->at(0) << tempList->at(1);
 
					numberOfNodes++;
				}
			}
			numberOfWays++;
		}
		
		QHashIterator<QString, OSM_Relation*> iRelation(*parser->getConvertableRelations());
		while (iRelation.hasNext()) 
		{
			iRelation.next();

			for(int i = 0; i < iRelation.value()->getWayList()->size(); i++)
			{
				if(parser->getWayContainer()->contains(iRelation.value()->getWayList()->value(i)))
				{
					for(int k = 0; k < parser->getWayContainer()->value(iRelation.value()->getWayList()->value(i))->getReferenceList()->size(); k++)
					{
							out << QString("relation") << iRelation.key();
											
							QList<QString> *tempList;

							tempList = math->convertCoordinates(parser->getNodeContainer()->value(parser->getWayContainer()->value(iRelation.value()->getWayList()->value(i))
																	  ->getReferenceList()->value(k))->getLatitude(),
																parser->getNodeContainer()->value(parser->getWayContainer()->value(iRelation.value()->getWayList()->value(i))
																	  ->getReferenceList()->value(k))->getLongitude());
			
							out << QString("pos") << tempList->at(0) << tempList->at(1);
	
							numberOfNodes++;
				
					}
					numberOfWays++;
				}
			}
			numberOfRelations++;
		}
		
		//Die vom Parser ermittelten Koordinaten für den Grenzbereich werden für die Projektion umgerechnet
		if(!parser->getBoundBox().isNull())
		{
			QList<QString> tempList = parser->getBoundBox().split(",");
			QList<QString> *boundingList = math->convertBounding(tempList.at(0),tempList.at(1),tempList.at(2),tempList.at(3));
		    
			out << QString("minlat") << boundingList->at(0) << QString("minlon") << boundingList->at(1) 
			<< QString("maxlat") << boundingList->at(2) << QString("maxlon") << boundingList->at(3);
		}
		else
		{
			QList<QString> *boundingList = math->convertBounding("51.27","6.75","51.528","7.635");

			out << QString("minlat") << boundingList->at(0) << QString("minlon") << boundingList->at(1) 
			<< QString("maxlat") << boundingList->at(2) << QString("maxlon") << boundingList->at(3);
		}
    }

    file.close();

	message = message + "\n\ngefundene Nodes: " + QString::number(parser->getNodeContainer()->size()) + "\n" +
    "konvertierte Nodes: " + QString::number(numberOfNodes) + "\n" + "gefundene Ways: " + QString::number(parser->getWayContainer()->size()) + "\n" +
    "konvertierte Ways: " + QString::number(numberOfWays) + "\n" + "gefundene Relations: " + QString::number(parser->getRelationContainer()->size()) + "\n" +
    "konvertierte Relations: " + QString::number(numberOfRelations) + "\n" + "konvertierte Tags: " + QString::number(parser->getNumberOfTags()) +
	"\n\n" + "Konvertierung erfolgreich abgeschlossen";

	gui_converter->getTextEdit()->setText(message);
}

Verfasst: 25. Mai 2010 19:04
von Christian81
Dem Converter_Thread den Pointer von Converter übergeben und fertig. Oder Converter gleich von QThread ableiten...

Verfasst: 25. Mai 2010 21:35
von marvel
hallo,
beide varianten habe ich ausprobiert. den pointer zu übergeben bringt nur schwierigkeiten, denn man muss doppelte includen, also thred in converter und dann nochmal converter in thread. den converter direkt von qthread abzuleiten hat geholfen. jedoch habe ich jetzt noch das problem das ich in der gui das textedit nicht geändert bekomme bzw keinen neuen text reinschreiben kann, weil er mir dann sagt das wäre thread übergreifend.

Bild

Verfasst: 25. Mai 2010 21:40
von Christian81
1. C++ Grundlagen - Stichwort 'Vorwärtsdeklaration'
2. die GUI kann nur im MainThread modifiziert werden. Daten von anderen Threads können z.B. per Signals/Slots übertragen werden.