Brauche dringend Hilfe mit QPixmap!
Brauche dringend Hilfe mit QPixmap!
Hallo!
Ich habe heute schon einen Beitrag geschrieben: http://qtforum.de/forum/viewtopic.php?t=798
Ich stecke immer noch an diesem Problem fest, allerdings habe ich jetzt schon gelesen, dass man kein QLabel benutzen sollte, um Bilder darzustellen, weshalb ich schon wieder umdenken muss.
Ich brauche folgendes:
Ein Widget, dass in einem QFrame eingebettet ist und mir als leeres Blatt für mein Bild dient. Vergrößert sich mein Dialog, vergrößert sich auch mein Frame. D.h. es soll sich auch mein leeres Blatt vergrößern. Jedoch soll der neu entstandene Platz nicht bloß rechts und links drangeklatscht werden, sondern das zugrundeliegende Koordinatensystem muss sich anpassen!
Wie lässt sich diese Idee realisieren?
Ciao
Ich habe heute schon einen Beitrag geschrieben: http://qtforum.de/forum/viewtopic.php?t=798
Ich stecke immer noch an diesem Problem fest, allerdings habe ich jetzt schon gelesen, dass man kein QLabel benutzen sollte, um Bilder darzustellen, weshalb ich schon wieder umdenken muss.
Ich brauche folgendes:
Ein Widget, dass in einem QFrame eingebettet ist und mir als leeres Blatt für mein Bild dient. Vergrößert sich mein Dialog, vergrößert sich auch mein Frame. D.h. es soll sich auch mein leeres Blatt vergrößern. Jedoch soll der neu entstandene Platz nicht bloß rechts und links drangeklatscht werden, sondern das zugrundeliegende Koordinatensystem muss sich anpassen!
Wie lässt sich diese Idee realisieren?
Ciao
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
Hallo!
Also, wenn ich das richtig verstehe, was ich hier verbreche, dann erzeuge ich ja eine QPixmap, die mein PaintDevice darstellt. Über ein QPainter Objekt schreibe ich auf diese QPixmap (z.B. mit drawPoint()).
Ich weiß bloß nicht, wann ich wo den QPainter oder die QPixmap skalieren muss. Schreibe ich eine von QWidget abgeleitete Klasse und reimplementiere einige Event Methoden? Womit stelle ich mein Bild dar? Über ein QLabel soll man's ja nicht machen.
Kurz: Was muss ich wie ableiten, damit mein Bild in einem QFrame dargestellt und immer automatisch mit vergrößert/verkleinert wird? Ich habe gerade die totale Blockade, weil es vorher mit einem QGLWidget alles anders lief.
Ich hoffe, das Problem ist nicht noch komplizierter geworden.
Ciao
Also, wenn ich das richtig verstehe, was ich hier verbreche, dann erzeuge ich ja eine QPixmap, die mein PaintDevice darstellt. Über ein QPainter Objekt schreibe ich auf diese QPixmap (z.B. mit drawPoint()).
Ich weiß bloß nicht, wann ich wo den QPainter oder die QPixmap skalieren muss. Schreibe ich eine von QWidget abgeleitete Klasse und reimplementiere einige Event Methoden? Womit stelle ich mein Bild dar? Über ein QLabel soll man's ja nicht machen.
Kurz: Was muss ich wie ableiten, damit mein Bild in einem QFrame dargestellt und immer automatisch mit vergrößert/verkleinert wird? Ich habe gerade die totale Blockade, weil es vorher mit einem QGLWidget alles anders lief.
Ich hoffe, das Problem ist nicht noch komplizierter geworden.
Ciao
Zunächst einmal Danke!lepsai hat geschrieben:Wenn etwas in einem QFrame dargestellt werden soll, dann sollte man die eigene Klasse von QFrame ableiten. Skalieren sollte man den Painter.
überladen sollten in deinem Fall:
paintEvent()
resizeEvent()
Nach einer kleinen Klausurphase und einer Erkältung mache ich mich wieder ans Werk...
Lepsai: Ich arbeite mit dem Designer, d.h. ich müsste den Frame in dem ich zeichnen will direkt hier einbauen, stimmt's?
Wenn nicht, dann würde ich Dich gerne fragen wie ich den Frame nachträglich, d.h. mit ein paar Codezeilen hinzufügen kann. Obwohl, aha, schneide ich hier zufällig das Thema "Custom Widgets" an?
Dann müsste ich also quasi im Designer einen Frame erstellen, mit der rechten Maustaste draufklicken und "Promote to custom widget" auswählen, oder?
Ciao
Also ich bin jetzt wie folgt vorgegangen:
Ich habe allerdings eine Frage zu der QPainter Funktion scale():
Vergrößert sie den tatsächlich sichtbaren Bereich, oder skaliert sie "nur" den Painter, indem sie vorgibt, dass die entsprechenden Ecken (unten links, oben rechts) dem Wert ihrer Funktionsargumente entsprechen?
- Im Designer einen Frame eingefügt (siehe Bild promoting.gif)
- Danach habe ich die beiden Dateien "PainterFrame.h" und "PainterFrame.cpp" erstellt (siehe unten) und in meine Projekt-Datei eingefügt.
- Jetzt noch qmake und make ausgeführt und es läuft.
Ich habe allerdings eine Frage zu der QPainter Funktion scale():
Vergrößert sie den tatsächlich sichtbaren Bereich, oder skaliert sie "nur" den Painter, indem sie vorgibt, dass die entsprechenden Ecken (unten links, oben rechts) dem Wert ihrer Funktionsargumente entsprechen?
Code: Alles auswählen
#ifndef PAINTERFRAME_H
#define PAINTERFRAME_H
#include <QtGui>
#include <QFrame>
class QPainter;
class QPixmap;
class PainterFrame : public QFrame
{
Q_OBJECT
public:
PainterFrame ( QWidget *parent = 0 );
~PainterFrame ();
void paintEvent ( QPaintEvent * event );
void resizeEvent ( QResizeEvent * event );
private:
QPainter *painter;
QPixmap *pixmap;
};
#endifCode: Alles auswählen
#include "PainterFrame.h"
#include <QPainter>
#include <QPixmap>
/**
* This is the PainterFrames's constructor
* @param QWidget * parent
* @see QFrame
*/
PainterFrame::PainterFrame ( QWidget *parent ) : QFrame( parent )
{
painter = new QPainter();
}
/**
* This is the PainterFrames's destructor
*/
PainterFrame::~PainterFrame()
{
delete painter;
delete pixmap;
}
/**
* This function is called whenever the window system sends a paint
* signal.
* @param QPaintEvent * event;
* @return void
*/
void PainterFrame::paintEvent( QPaintEvent * event )
{
painter.drawPixmap( 0, 0, *pixmap );
}
/**
* This function is called whenever the window system sends a resize
* signal.
* @param QResizeEvent * event;
* @return void
*/
void PainterFrame::resizeEvent( QResizeEvent * event )
{
QSize oldSize = event->oldSize();
QSize newSize = event->size();
// Only scale the painter's coordinate system if necessary
if ( oldSize != newSize )
{
painter->scale( newSize->width(), newSize->height() );
}
}- Dateianhänge
-
- So sieht die Ansicht im Designer aus, wenn ich meinen QFrame als Custom Widget promote.
- promoting.gif (68.74 KiB) 7584 mal betrachtet
in 2-3 Tagen werde ich www.ku-soft.de ein Widget für die Bildanzeige zum Download anbieten, vielleicht wird es was für dich...
in resizeEvent() berechnest du den Zoomfaktor, aber angewendet wird dieser in paintEvent()...
Wie es in Qt 4 mit setWorldMatrix aussieht, weiss ich nicht, aber auch da wird ei eine Möglichkeit geben, painter zu skalieren... Meine Vorschläge beziehen sich immer auf Qt3... Bis Ende dieses Jahres jedenfalls
Wie es in Qt 4 mit setWorldMatrix aussieht, weiss ich nicht, aber auch da wird ei eine Möglichkeit geben, painter zu skalieren... Meine Vorschläge beziehen sich immer auf Qt3... Bis Ende dieses Jahres jedenfalls
So, ich bekomme mein Pixmap jetzt angezeigt, wenn und skaliert, wenn ich meinen QPainter in der paintEvent Methode erzeuge und zwar nicht als Zeiger.
Wenn ich jetzt aber nur den Teil meines Feldes neuzeichnen lassen will, der sich verändert hat (das wären dann zwei Punkte), wie kann ich denn dann auf meinen QPainter einwirken und z.B. "void drawPoint ( int x, int y )" aufrufen?
Immerhin kann ich von außen nicht auf den QPainter zugreifen?
Die einzige Möglichkeit besteht für mich darin, dem QFrame, in dem gezeichnet wird, ein Signal zu schicken, dass er eine bestimmte Region neuzeichnen soll.
Sehe ich das richtig?
Ciao
Wenn ich jetzt aber nur den Teil meines Feldes neuzeichnen lassen will, der sich verändert hat (das wären dann zwei Punkte), wie kann ich denn dann auf meinen QPainter einwirken und z.B. "void drawPoint ( int x, int y )" aufrufen?
Immerhin kann ich von außen nicht auf den QPainter zugreifen?
Die einzige Möglichkeit besteht für mich darin, dem QFrame, in dem gezeichnet wird, ein Signal zu schicken, dass er eine bestimmte Region neuzeichnen soll.
Sehe ich das richtig?
Ciao
Also gut!
Ich habe ein Array mit Zufallswerten, von denen ich den kleinsten, den größten und die Anzahl der Werte kenne. In einem Sortieralgorithmus soll das Array sortiert werden und bei jedem Vertauschen von zwei Werten muss ein Signal gesendet werden. Es kann auch sein, dass erst nach mehreren Vertauschungen ein Signal gesendet wird, das hängt ganz von der gewählten Aktualisierungsrate ab.
Zum Signal: Jedes Signal, welches über eine Änderung im Feld informiert, übermittelt die beiden X- und Y-Werte, die sich verändert haben. Mein Frame, in dem gezeichnet wird, soll dieses Signal entgegennehmen und die beiden entsprechenden Bereiche neuzeichnen.
Mein vorherige Lösung sah vor, dass einfach nur über eine Änderung im Feld informiert wurde, aber nicht gesagt wurde wo sich diese Änderung befindet. Das bedeutet, dass immer wieder alles neu gezeichnet werden musste. Es sei hier angemerkt, dass diese Lösung noch OpenGL verwendete, womit man sowie so nur alles neu zeichnen kann (glaube ich).
Zurück zum Problem.
Ich muss also, sobald ich meine Werte vom Zufallsarray bekomme einmal alles zeichnen und sobald etwas geändert wurde, nur noch den entsprechenden Bereich aktualisieren. Ich vermute mal, dass diese Lösung schneller ist, als immer c.a. 100.000.000 Elemente neuzuzeichnen.
Wenn alles soweit implementiert ist, dann werden allerdings noch folgende Probleme auftreten:
Ich hoffe, mein Problem ist jetzt etwas klarer geworden.
Ciao
Ich habe ein Array mit Zufallswerten, von denen ich den kleinsten, den größten und die Anzahl der Werte kenne. In einem Sortieralgorithmus soll das Array sortiert werden und bei jedem Vertauschen von zwei Werten muss ein Signal gesendet werden. Es kann auch sein, dass erst nach mehreren Vertauschungen ein Signal gesendet wird, das hängt ganz von der gewählten Aktualisierungsrate ab.
Zum Signal: Jedes Signal, welches über eine Änderung im Feld informiert, übermittelt die beiden X- und Y-Werte, die sich verändert haben. Mein Frame, in dem gezeichnet wird, soll dieses Signal entgegennehmen und die beiden entsprechenden Bereiche neuzeichnen.
Mein vorherige Lösung sah vor, dass einfach nur über eine Änderung im Feld informiert wurde, aber nicht gesagt wurde wo sich diese Änderung befindet. Das bedeutet, dass immer wieder alles neu gezeichnet werden musste. Es sei hier angemerkt, dass diese Lösung noch OpenGL verwendete, womit man sowie so nur alles neu zeichnen kann (glaube ich).
Zurück zum Problem.
Ich muss also, sobald ich meine Werte vom Zufallsarray bekomme einmal alles zeichnen und sobald etwas geändert wurde, nur noch den entsprechenden Bereich aktualisieren. Ich vermute mal, dass diese Lösung schneller ist, als immer c.a. 100.000.000 Elemente neuzuzeichnen.
Wenn alles soweit implementiert ist, dann werden allerdings noch folgende Probleme auftreten:
- Wenn aufgrund der Aktualisierungsrate nicht immer jede Veränderung im Feld signalisiert wird, dann muss ich mir diese Aktualisierungen aber trotzdem merken und sie später zeichnen lassen. Das dürfte aber kein Problem sein.
- Wie rechne ich die einfachen Indices und Werte in meinem Zufallsarray in die zu zeichnenden Koordinaten um?
Ich hoffe, mein Problem ist jetzt etwas klarer geworden.
Ciao
Nun, du musst natürlich nur Regionen zeichnen, die aktualisiert wurden. Da dir zu einem Zeitpunkt die neuen Koordinaten vorliegen, ist es auch kein Problem. Definiere in deiner Klasse eine zusätzliche Variable, die das Update steuern würde. Und frag diese in paintEvent() ab. So kannst du steuern, ob ein komplettes oder ein partielles Update stattfinden soll. Für das partielle Update musst du in deiner Klasse die entpsrechende Punkte festhalten. z.B. in einem QPoint Objekt.