Seite 1 von 1
Wahl der richtigen Klasse: 2D Matrizen plotten
Verfasst: 15. Juli 2007 17:18
von pospiech
Zuerst, ich kenne mich mit Qt noch fast gar nicht aus...
Ich habe Daten als 2D Arrays vorliegen die ich als Bild ausgeben möchte. Diese Werte liegen als double Werte vor und müssen noch in RGB Werte umgewandelt werden. Die Größen der Daten müssen exact in Pixel umgewandelt werden. Ein Array der Größe 256x256 soll daher auf dem Bildschirm auch 256x256 Pixel ausfüllen.
Meine wesentliche Frage hierzu ist welche Klasse dazu sinnvoll ist.
Gefunden habe ich unter anderem folgende:
- QPainter
- QPixmap
- QImage
- QGraphicsView
aber grundsätzlich interessiert mich am meisten welche geignet ist.
Zwei wesentlich Anforderungen gibt es dabei. Zum einen muss Double Buffering unterstützt werden und das zeichnen soll schnell gehen.
Die Geschwindigkeit bringt mich auch gleich zur nächsten Frage. Ist es sinnvoller in ein Image (welche klasse müsste ich dann nutzen?) zu zeichnen und das im ganzen auszugeben oder direkt über
Code: Alles auswählen
for(int x=0; x<N;x++)
for(int y=0; y<N;y++)
whateverclass.drawPoint (x,y );
zu zeichnen.
Eine OpenGl basierte zeichenmethode könnte ich auch nutzen allerdings kenne ich mich mit OpenGL nicht aus und wüsste auch gerne wie es ohne (also direkt mit Qt) geht.
Eine weitere Frage wäre welche Methoden Qt kennt um in RGB Farben umzurechnen?
Desweiteren habe ich Arrays die größer und kleiner sein werden als das widget. Wie kann ich dann hoch oder runterskalieren?
Und wenn ich nicht skalieren möchte wie kann ich dann ein 512x512 Bild in ein 256x256 Widget zeichnen und die Ansicht mit Scrollbars ändern?
Sehr viele Fragen, aber ich hoffe ihr könnt mir ein paar Anstöße geben
Vielen Dank,
Matthias
Verfasst: 15. Juli 2007 19:05
von Uwe
In Qwt
http://qwt.sf.net findest Du Unterstützung für die Darstellung von Daten als Spectrogram. Du mußt eigentlich nicht viel mehr tun als Deine Matrix über die Klasse QwtPlotRasterData anzuschliessen.
Schau Dir einfach mal das spectrogram Beispiel an.
Uwe
Verfasst: 15. Juli 2007 19:18
von pospiech
Danke, das hatte ich auch schon gefunden.
Allerdings muss ich die Ausgabe selber kontrollieren können.
Hintergrund ist, dass die Ausgabe auf den zweiten Bildschirm erfolgen soll und dieser nicht an einen Monitor, sondern an ein Gerät angeschlossen ist, so dass die Steuerung über das Bildschirm Signal erfolgt.
Zudem möchte ich einfach wissen wie man soetwas macht.
bislang scheitere ich schon daran dass im Qt Designer nur das Widget graphicsView zur Verfügung steht und ich kein Beispiel finde wie ich darein malen kann - da die Beispiele sich meist auf QPainter beziehen.
Matthias
Verfasst: 15. Juli 2007 19:28
von Christian81
pospiech hat geschrieben:
bislang scheitere ich schon daran dass im Qt Designer nur das Widget graphicsView zur Verfügung steht und ich kein Beispiel finde wie ich darein malen kann - da die Beispiele sich meist auf QPainter beziehen.
examples/graphicsview nicht ausreichend?
Verfasst: 15. Juli 2007 19:47
von pospiech
Christian81 hat geschrieben:
examples/graphicsview nicht ausreichend?
Natürlich kann ich versuchen die benutzung rückwärts zu lernen - also vom komplexen beispiel darauf zu schließen welche drei Bfehle ich brauche.
Was mir aber noch immer fehlt ist der Zusammenhang zwischen QGraphicsView und einer Klasse wie QPainter - und wie man dieses Problem sinnvollerweise angeht. Oder kurzgesagt, wie (in Stichpunkten) würde ein erfahrener Qt Programmier ein solches Problem angehen?
Was ich machen möchte wird darauf hinauslaufen, dass ich mir ein eigenes Widget erstelle. Die Frage ist aber wovon ich es ableite.
Und (wenn auch offtopic), wie füge ich im QtDesigner ein eigenes Widget hinzu?
Matthias
Verfasst: 15. Juli 2007 20:31
von Uwe
Wenn Du dein Bild auf einem QPaintDevice ( Bildschirm, Drucker ...) darstellen willst, mußt Du zunächst ein QImage rendern.
Ein QImage ist einfach eine Matrix von RGB Werten, deren Werte man direkt zuweisen kann. z.B für das Pixel [x, y]:
Du nimmst also einfach eine QImage(256, 256), iterierst über das Image und Deine Matrix und bildest jedes Datum auf einen RGB Wert ab.
Das QImage kannst Du dann am einfachsten auf einem QLabel darstellen ( IMHO ist in dem Fall QGraphicView unnötiger Overhead ).
Da Du aber schreibst, daß Deine Ausgabe ja auf gar keine QPaintDevice geht, warum willst Du überhaupt über irgendwelche Qt Klassen gehen ?
Uwe
Verfasst: 15. Juli 2007 21:00
von pospiech
Uwe hat geschrieben:
Ein QImage ist einfach eine Matrix von RGB Werten, deren Werte man direkt zuweisen kann. z.B für das Pixel [x, y]:
ich habe folgendes gefunden:
Code: Alles auswählen
value = qRgb(189, 149, 39); // 0xffbd9527
image.setPixel(1, 1, value);
hat dein Code gegenüber diesem Vor/Nachteile (schneller/langsamer) ?
Das QImage kannst Du dann am einfachsten auf einem QLabel darstellen ( IMHO ist in dem Fall QGraphicView unnötiger Overhead ).
Würde dann nicht auch QWidget reichen ?
Und welche zusätzlichen Funktionen bietet mir QGraphicView ? (Wenn ich weiß was es kann weiß ich auch warum ich es nicht brauche)
Da Du aber schreibst, daß Deine Ausgabe ja auf gar keine QPaintDevice geht, warum willst Du überhaupt über irgendwelche Qt Klassen gehen ?
Was hat QPaintDevice mit meiner Frage zu tun? Und wie sollte ich etwas auf den Bildschirm ausgeben wenn ich Qt benutze wenn nicht mit Funktionen von Qt ??
Wenn ich ein neues Widget erstelle (ableite), wo muss ich dann das Malen einfügen? In den meisten Beispielen habe ich die Funktion
paintEvent(QPaintEvent * /* event */) vorgefunden. Wann wird diese Aufgerufen, und wie erreiche ich gezielt das diese aufgerufen wird ?
Matthias
Verfasst: 16. Juli 2007 09:14
von Uwe
hat dein Code gegenüber diesem Vor/Nachteile (schneller/langsamer) ?
Das Rendern Deines Bildes schaut in etwa so aus:
Code: Alles auswählen
for ( int y = 0; y < 256; y++ ) {
QRgb *line = (QRgb *)image.scanLine(y) ;
for ( int x = 0; x < 256; x++ )
*line++ = ...;
Der Code ist natürlich sehr viel schneller, als wenn Du die Pixel durcheinander zuweist ( wie z.B mit setPixel ), weil die Navigation entfällt. Zudem entfällt der Unterprogrammsprung. (Bedenke Du bist in einer Schleife, in der fast nichts passiert, die aber sehr oft durchlaufen wird !)
Bei einer 256x256 Matrix spielt das eher keine Rolle, da das Vielfache von Nichts immer noch Nichts ist. Aber der Code hat quadratische Ordnung und bei einem Bild in Bildschirmauflösung (z.B 1280x1024) schaut das schon anders aus.
Würde dann nicht auch QWidget reichen ?
QLabel ist dafür gedacht ein Text oder Pixmap darzustellen. Natürlich kannst Du auch ein QWidget nehmen und paintEvent( + QPainter::drawImage) und resizeEvent nachzubauen - aber wozu ?
HTH,
Uwe
Verfasst: 16. Juli 2007 09:42
von pospiech
Uwe hat geschrieben:
Würde dann nicht auch QWidget reichen ?
QLabel ist dafür gedacht ein Text oder Pixmap darzustellen. Natürlich kannst Du auch ein QWidget nehmen und paintEvent( + QPainter::drawImage) und resizeEvent nachzubauen - aber wozu ?
Mit Qwidget und paintEvent( + QPainter::drawImage) habe ich es jetzt schon hinbekommen, aber Wie zeichne ich in ein QLabel, wenn nicht mit paintEvent( + QPainter::drawImage) ?
Matthias
Verfasst: 16. Juli 2007 09:46
von Christian81
pospiech hat geschrieben:
Mit Qwidget und paintEvent( + QPainter::drawImage) habe ich es jetzt schon hinbekommen, aber Wie zeichne ich in ein QLabel, wenn nicht mit paintEvent( + QPainter::drawImage) ?
Indem man ganz einfach mal in die
DOKU schaut!
Verfasst: 23. Juli 2007 12:34
von C_R
habe dazu auch noch eine Frage.
Ich habe auch Plots auf einer QPixmap. Beim Ausdruck (pdf) ist die Auflösung schlecht. Leider helfen die Printermodes, setResolution da auch nicht. Gibt es da noch etwas anderes zu beachten? (Pixmap ist auch nicht gescaled)..
version: Qt 4.1.1
Verfasst: 20. April 2008 10:56
von pospiech
Uwe hat geschrieben:hat dein Code gegenüber diesem Vor/Nachteile (schneller/langsamer) ?
Das Rendern Deines Bildes schaut in etwa so aus:
Code: Alles auswählen
for ( int y = 0; y < 256; y++ ) {
QRgb *line = (QRgb *)image.scanLine(y) ;
for ( int x = 0; x < 256; x++ )
*line++ = ...;
Ich habe das mal versucht zu implementieren:
Code: Alles auswählen
QRgb color;
int grayvalue;
for ( int y = 0; y < m_DataSize.height(); y++ )
{
QRgb *line = (QRgb *)m_image->scanLine(y) ;
for ( int x = 0; x < m_DataSize.width(); x++ )
{
grayvalue = digitize.greyLevel(m_Array[ArrPos(x,y)])
*line++ = color(grayvalue, grayvalue, grayvalue);
}
}
bekomme aber den Fehler
error C2297: '*': Ungültig, da der rechte Operand vom Typ 'QRgb *' ist
in der Zeile mit
EDIT:
Ich hatte nur ein Semikolon vergessen, es kompiliert jetzt mit
Code: Alles auswählen
grayvalue = digitize.greyLevel(m_Array[ArrPos(x,y)]);
*line++ = qRgb(grayvalue, grayvalue, grayvalue);
Matthias