Qlabel wird nicht angezeigt

Verschiedenes zu Qt
Antworten
Ryu1991
Beiträge: 27
Registriert: 11. Mai 2009 09:29

Qlabel wird nicht angezeigt

Beitrag von Ryu1991 »

Hey,
ich arbeite gerade an einer Klasse zur Darstellung von Bild-Histogrammen.
Dazu habe ich erst mal eine Klasse von QWidget abgeleitet, und erstelle dann ein Qlabel und ein QImage. Wenn es neue Daten gibt, die angezeigt werden sollen, rufe ich setBins auf.
Da setBins nicht aus dem Hauptthread des Programms aufgerufen wird, habe ich außerdem die Methode repaintDisplay() implementiert. Und an der Codestelle wo ich setBins aufrufe, emite ich ein Signal, dass an einen Slot gekettet ist, der dann auf dem Richtigen Histogram repaintDisplay() aufruft.
Mein Problem ist jetzt allerdings, dass mein Histogram nicht angezeigt wird.
Nach Studen langem googlen bin ich zu dem Ergebnis gekommen, dass ich mir vermutlich bei der Berechnung des Images irgendwie das Image-Objekt invalidiere, und das Label deshalb nicht angezeigt wird.
Die Methode, in der ich den Fehler vermute wäre dann calculateHistogramMono()
Ach ja, mir ist klar, dass das Histogram auf dem Kopf stehen wird. Aber das zu ändern stellt dann auch kein Problem mehr da, wenn dann endlich mal eins angezeigt wird.
Ich verwende VisualStudio 2010 und QT 4.8

Hier mein Code:

ImageHistogram.h:

Code: Alles auswählen

#ifndef IMAGEHISTOGRAM_H
#define IMAGEHISTOGRAM_H

#include <qwidget.h>
#include <qlabel.h>

class ImageHistogram : public QWidget
{
	public:
		ImageHistogram(QWidget *Parent);
		~ImageHistogram();

		void setBins(int *bins, int numBins);
		void repaintDisplay();


	private:
		void initImage();
		void calculateHistogramMono(int *bins);	
		void calculateHistogramRGB(int *bins);

		int getArrayMaximum(int *Array, int length);
		int getArrayMinimum(int *Array, int length);


		QLabel *Display;
		QImage *Data;

};

#endif
ImageHistogram.cpp

Code: Alles auswählen

#include "ImageHistogram.h"

#include <qboxlayout.h>

#include <limits>

ImageHistogram::ImageHistogram(QWidget *Parent):QWidget(Parent)
{
	QHBoxLayout *TopLvlLayout = new QHBoxLayout(this);
	Display = new QLabel(this);
	TopLvlLayout->addWidget(Display);
	setLayout(TopLvlLayout);

	initImage();
}

ImageHistogram::~ImageHistogram()
{

}

void ImageHistogram::initImage()
{
	Data = new QImage(255, 100, QImage::Format_Indexed8);

	auto value = qRgb(255, 255, 255); 
	Data->setColor(0, value);

	value = qRgb(255, 0, 0); 
	Data->setColor(1, value);

	value = qRgb(0, 255, 0); 
	Data->setColor(2, value);

	value = qRgb(0, 0, 255); 
	Data->setColor(3, value);

	value = qRgb(30, 30, 30); 
	Data->setColor(4, value);

	Data->fill(qRgb(255, 255, 255));
	Display->setPixmap(QPixmap::fromImage(*Data));
	//Display->update();
}

void ImageHistogram::setBins(int *bins, int numBins)
{
	if(numBins < 3 * 255)
		calculateHistogramMono(bins);
	else
		calculateHistogramRGB(bins);
}

void ImageHistogram::calculateHistogramMono(int *bins)
{	
	int maxVal = getArrayMaximum(bins, 255);
	float mult = 100.0 / maxVal;//zum normalisieren auf 100

	for(int i = 0;i < 255; i++)
	{
		int y = bins[i] * mult;
		for(int k = 0; k < y; k++)
			Data->setPixel(i, k, 4);

		for(int k = y; k < 100; k++)
			Data->setPixel(i, k, 0);
	}

	Display->setPixmap(QPixmap::fromImage(*Data));
}

void ImageHistogram::calculateHistogramRGB(int *bins)
{

}

int ImageHistogram::getArrayMaximum(int *Array, int length)
{
	int max = 0;

	for(int i = 0; i < length; i++)
		if(Array[i] > max)
			max = Array[i];

	return max;
}

int ImageHistogram::getArrayMinimum(int *Array, int length)
{
	int min = std::numeric_limits<int>::max();

	for(int i = 0; i < length; Array++)
		if(*Array < min)
			min = *Array;

	return min;
}

void ImageHistogram::repaintDisplay()
{
	Display->setPixmap(QPixmap::fromImage(*Data)); 
	Display->repaint();
}
Vielen Dank schonmal im Vorraus
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Qlabel wird nicht angezeigt

Beitrag von Christian81 »

Zugriff auf GUI-Elemente von einen Thread heraus der nicht der Main-Thread ist, ist nicht erlaubt. Ob Dein Problem daran liegt weiß ich allerdings nicht.
Ich würde erstmal in das Label einen Text schreiben und schauen ob dieser angezeigt wird.
Das QImage als Pointer abzuspeichern ist auch nicht wirklich nötig.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ryu1991
Beiträge: 27
Registriert: 11. Mai 2009 09:29

Re: Qlabel wird nicht angezeigt

Beitrag von Ryu1991 »

Hey,
das Label wird angezeigt, einfach weiß, solange bis das erste mal SetBins aufgerufen wird. Dann ist es weg.
Und weil es eben nicht erlaubt ist, Gui elemente in einem Nebenthread zu modifizieren, habe ich den slot eingefügt. Dann passiert es auf jeden Fall im Main-Thread (zumindest laut einem Post auf Stackoverflow)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Qlabel wird nicht angezeigt

Beitrag von Christian81 »

Erstens sehe ich keinen Slot und zweitens nur weil es ein Slot ist heißt es nicht, dass es im Hauptthread ausgeführt wird ... warum überhaupt das mit den Threads?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ryu1991
Beiträge: 27
Registriert: 11. Mai 2009 09:29

Re: Qlabel wird nicht angezeigt

Beitrag von Ryu1991 »

Eine Andere klasse hat den Slot, und in dem Slot wird dann setBins aufgerufen. Deshalb siehst du ihn hier nicht. Und es gibt mehrere Threads, weil ich einen Extrathread brauche um Bilder aus einer Kammera auszulesen.
Muss ich einen Timer benutzen, um sicherzustellen, dass das ganze im Hauptthread repaintede wird? Oder gibt es einen Etwas performancesparenderen Weg? Immerhin soll das ein Live-histogramm werden, also brauche ich mind. 20FPS
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Qlabel wird nicht angezeigt

Beitrag von Christian81 »

Ich würde nicht darauf wetten dass setBins() im Hauptthread ausgeführt wird. Thread-Programmierung ist nicht gerade einfach und Du scheinst damit ja auch noch keine Erfahrungen zu haben...
Am Einfachsten siehst Du es indem Du QThread::currentThreadId() per qDebug() ausgibst und schaust wo welcher Thread etwas macht. In setBins() kannst Du auch erst einmal nur dem Label einen anderen Text geben um zu schauen ob es prinzipiell funktioniert.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ryu1991
Beiträge: 27
Registriert: 11. Mai 2009 09:29

Re: Qlabel wird nicht angezeigt

Beitrag von Ryu1991 »

Hey,
danke für den Hinweis, du hattest recht. Das ganze wird trotz des Slots nich im Hauptthread ausgeführt. Ich habe jetzt einen Timer genommen, und lasse ihn alle 50ms nen repaint Triggern, jetzt funktioniert es :)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Qlabel wird nicht angezeigt

Beitrag von Christian81 »

Ist aber absolut nicht threadsafe und kann zu crashes führen wenn der Thread gerade Daten abliefert und repaint im selben Moment auf die Daten zugreifen will. Da musst Du Dich wohl oder übel intensiver mit Thread-Programmierung beschäftigen. In dem Fall mit QMutex.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ryu1991
Beiträge: 27
Registriert: 11. Mai 2009 09:29

Re: Qlabel wird nicht angezeigt

Beitrag von Ryu1991 »

Stimmt, jetzt wo dus sagst ^^
Ich bin kein absoluter Anfgänger in Sachen Threadprogrammierung, aber Routine hab ich da auch noch nicht wirklich :oops:
Hab ne Mutex eingebaut, nochmals: danke für den Hinweis :D
Antworten