Frage zum Scribble Example[gelöst]

Verschiedenes zu Qt
Antworten
Qt-nator
Beiträge: 153
Registriert: 18. Dezember 2007 10:31

Frage zum Scribble Example[gelöst]

Beitrag von Qt-nator »

Hi,

was ich versuche ist folgendes, dass wenn ich in einem Widget die Maus drücke und sie dann bewege soll der Mausbewegung nachgezeichnet werden. Des halb hab ich mich mal am Scribble Example probiert und so. Bei mir entsteht ist dann follgendes entstanden:

Code: Alles auswählen

void ParameterToolWidget::drawLineTo(const QPoint &endPoint)
{
	QPainter painter(XXX);
  painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::RoundCap,
                        Qt::RoundJoin));
  painter.drawLine(m_LastPoint, endPoint);

  m_LastPoint = endPoint;
}

void
ParameterToolWidget::mouseMoveEvent(QMouseEvent* event)
{
	QString sMouseInteraction;
   
	sMouseInteraction.sprintf("  Maus Position: X: %d, Y: %d ", event->pos().x(), event->pos().y());	

	emit si_mousePosition(sMouseInteraction);
		
	if ((event->buttons() & Qt::LeftButton) && m_Scribbling) drawLineTo(event->pos());
}

void
ParameterToolWidget::mousePressEvent(QMouseEvent* event)
{
	QString sMouseInteraction = "Maustaste wurde gedrückt.";

	emit si_mousePosition(sMouseInteraction);

	if (event->button() == Qt::LeftButton) 
	{
		m_LastPoint = event->pos();
   
		m_Scribbling = true;
  }

}

void 
ParameterToolWidget::mouseReleaseEvent(QMouseEvent* event)
{
	QString sMouseInteraction = "Maustaste wurde gedrückt/losgelassen.";

	emit si_mousePosition(sMouseInteraction);

	if (event->button() == Qt::LeftButton && m_Scribbling)
	{
		drawLineTo(event->pos());
    
		m_Scribbling = false;
  }
}


Bei drawLineTo ist im Example folgendes:

Code: Alles auswählen


 void ScribbleArea::drawLineTo(const QPoint &endPoint)
 {
     QPainter painter(&image);
     painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap,
                         Qt::RoundJoin));
     painter.drawLine(lastPoint, endPoint);
     modified = true;

     int rad = (myPenWidth / 2) + 2;
     update(QRect(lastPoint, endPoint).normalized()
                                      .adjusted(-rad, -rad, +rad, +rad));
     lastPoint = endPoint;
 }

Mein Problem stellt diese Zeile dar bei meiner Version mit XXX gekenzeichnet

// QPainter painter(&image); //

jedenfalls ist image ein erstelltes QImage... mein Problem ist jetzt ich muss mein Widget damit ansprechen das ich im Designer erstellt habe... nur wenn ich es so eintrage bekomme ich dann Meldung das ers nicht findet...

kann mir da jemand weiter helfen???
Zuletzt geändert von Qt-nator am 13. März 2008 09:20, insgesamt 1-mal geändert.
neuschi
Beiträge: 78
Registriert: 23. Mai 2007 10:59

Re: Frage zum Scribble Example

Beitrag von neuschi »

Qt-nator hat geschrieben:
mein Problem ist jetzt ich muss mein Widget damit ansprechen das ich im Designer erstellt habe... nur wenn ich es so eintrage bekomme ich dann Meldung das ers nicht findet...

kann mir da jemand weiter helfen???
Dazu müsste man wissen, wie du den Dialog aufgebaut hast, d.h. welchen der Ansätze aus http://doc.trolltech.com/4.3/designer-u ... processing
du verwendest.

Hast du im Konstruktor deines ParameterToolWidgets sowas wie

Code: Alles auswählen

setupUi(this)
oder

Code: Alles auswählen

 myUi.setupUi(this)
stehen?

Angenommen dein Widget aus dem Designer heisst "zeichenflaeche", dann müsstest du entweder

Code: Alles auswählen

QPainter painter(&zeichenflaeche);
oder

Code: Alles auswählen

 QPainter painter(& myUi.zeichenflaeche);
nehmen.

\Ralf
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Re: Frage zum Scribble Example[gelöst]

Beitrag von Saul »

Ist es möglich mithilfe des scribble beispiels auf ein label zu zeichnen, anstatt auf das komplette widget?

Beispielsweise:

Code: Alles auswählen

QPainter painter(ui.label);
Mein Ziel ist es auf ein Bild zu zeichen, welches ich vorher aus einer datei im entsprechenden label geladen habe.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Frage zum Scribble Example[gelöst]

Beitrag von franzf »

Zeichnen auf ein Widget geht nur im dessen paintEvent. Einen painter auf einem fremden Widget aufmachen geht nicht.
Um nur auf das Bild zu zeichnen:

Code: Alles auswählen

QPixmap pix = label->pixmap();
{
    QPainter p(&pix);
    // Mit dem painter malen
}
label->setPixmap(pix);
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Re: Frage zum Scribble Example[gelöst]

Beitrag von Saul »

Hi franzf,
danke für deine Hilfe.

Ich hab nur ein kleines Problem, das ich nicht weiß, wie ich die const Pixmap von ui.label in die neue Pixmap pix convertiere. Da meckert nämlich der compiler =(

Code: Alles auswählen

 QPixmap pix = ui.label->pixmap();
 {
	 QPainter p(&pix);
	 // Mit dem painter malen
 }
 ui.label->setPixmap(pix);
Ansonsten sollte das zeichen dann mit folgender Funktion aus der Qt Reference Documentation funktionieren.

Code: Alles auswählen

void QPaintEngine::drawImage ( const QRectF & rectangle, const QImage & image, const QRectF & sr, Qt::ImageConversionFlags flags = Qt::AutoColor ) [virtual]

// Reimplement this function to draw the part of the image specified by the sr rectangle in 
// the given rectangle using the given conversion flags flags, to convert it to a pixmap.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Frage zum Scribble Example[gelöst]

Beitrag von franzf »

Sry, QLabel::pixmap() gibt natürlich einen Zeiger zurück.

Code: Alles auswählen

QPixmap pix = *ui.label->pixmap();
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Re: Frage zum Scribble Example[gelöst]

Beitrag von Saul »

Jap, das mit dem Zeiger hatte ich gestern schon ausprobiert.
Aber leider ohne erfolg, denn dann bekomm ich eine Zugriffsverletzung =(
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Frage zum Scribble Example[gelöst]

Beitrag von franzf »

Ich hatte angenommen, das Label hat unter allen Umständen bereits ein Pixmap gesetzt. Wenn dem nicht so ist, musst du halt mit einem Zeiger arbeiten:

Code: Alles auswählen

QPixmap const *pix = ui.label->pixmap();
if(pix) {
  QPixmap painterPix(*p);
  QPainter p(&painterPix);
  // malen
  ui.label->setPixmap(painterPix);
}
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Re: Frage zum Scribble Example[gelöst]

Beitrag von Saul »

Hi franzf

Wenn ich es jetzt wie folgt löse, kann ich gar nicht malen

Code: Alles auswählen

void FoSe::paintEvent(QPaintEvent *event)
{
	//QPainter painter(this);
	//QRect dirtyRect = event->rect();
	//painter.drawImage(dirtyRect, image, dirtyRect);

	QRectF target(0.0, 0.0, 800.0, 600.0);
	QRectF source(0.0, 0.0, 800.0, 600.0);
	QImage image("bild.png");
	ui.label->setPixmap(QPixmap::fromImage(image));
	QPixmap pix = *ui.label->pixmap();
	{
		QPainter p(&pix);
		p.drawImage(target, image, source);
	}
	ui.label->setPixmap(pix);
 }
Wenn ich die Kommentare beim painter wegnehme, malt man wieder aufs komplette widget und nicht aufs bild =(
(siehe Anhang)
Dateianhänge
prog.jpg
prog.jpg (162.16 KiB) 11246 mal betrachtet
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Frage zum Scribble Example[gelöst]

Beitrag von franzf »

Warum bist du jetzt plötzlich im paintEvent? Wenn du auf ein Pixmap drauf zeichnen willst, leg dir eine eigene Funktion an (ein SLOT bietet sich an), in der du das tust und das neue Bild ins Label setzt.
Willst du direkt auf ein Widget malen, geht das nur in dessen paintEvent, du müsstest also Ableiten.
Und wenn du den painter da so auf this aufmachst, malt der auch auf "this" (also FoSe-Instanz) und nicht ins Label. Das Label ist ein child und liegt über dem FoSe-Objekt, malt seine Inhalte (das Bild) also auch darüber.
Und was bitte bringt es, ein Bild nochmal auf sich selbst zu zeichnen? Natürlich sieht man dann nichts.
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Re: Frage zum Scribble Example[gelöst]

Beitrag von Saul »

Hi franzf,
also irgendwie versteh ich die ganze Sache noch nicht =(
Ich erhalte jetzt mittels mousePressEvent() und mouseMoveEvent() die entsprechenden Koordinaten für die zu zeichnende Linie.
Die Funktion drawLineTo() zeichnet dann die Linie zwischen den von der Maus erhaltenen Koordinaten auf das Bild, welches mittels bildLaden() geöffnet wird.

Code: Alles auswählen

void ProgNeu::bildLaden()
{
	 QImage image("bild.png");
	 ui.label->setPixmap(QPixmap::fromImage(image));
}

Code: Alles auswählen

void ProgNeu::drawLineTo(const QPoint &endPoint)
{
	//QPainter painter(&image);
	QPixmap pix = *ui.label->pixmap();
	{
		QPainter painter(&pix);
		painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
		painter.drawLine(lastPoint, endPoint);
		modified = true;
		
		int rad = (myPenWidth / 2) + 2;
		update(QRect(lastPoint, endPoint).normalized().adjusted(-rad, -rad, +rad, +rad));
		lastPoint = endPoint;
	}
	ui.label->setPixmap(pix);
}

void ProgNeu::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton)
	{
		lastPoint = event->pos();
		scribbling = true;
	}
}

void ProgNeu::mouseMoveEvent(QMouseEvent *event)
{
	if ((event->buttons() & Qt::LeftButton) && scribbling)
		drawLineTo(event->pos());
}
Jetzt habe ich noch zwei Probleme:
Zum einen erhalte ich die Maus-Koordinaten vom Widget und nicht vom Label. D.h. das ich mit einem Versatz zum Mauszeiger male (siehe rotes Rechteck im Anhang) und auch gemalt wird, wenn sich der Mauszeiger außerhalb des Labels befindet.

Und zum anderen versucht mein Prog von Anfang an auf das Label zu zeichnen, anstatt wie gewollt erst zu zeichnen wenn das Bild mittel Button geladen wurde ( connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(bildLaden())); ). Logischerweise stürtzt das Programm ab, wenn das Bild noch nicht geladen wurde.

Es muss doch auch möglich sein, den MouseEvent erst in meiner bildLaden() Funktion aufzurufen oder?
Dateianhänge
neu.jpg
neu.jpg (137.88 KiB) 11224 mal betrachtet
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Frage zum Scribble Example[gelöst]

Beitrag von franzf »

Saul hat geschrieben:Zum einen erhalte ich die Maus-Koordinaten vom Widget und nicht vom Label. D.h. das ich mit einem Versatz zum Mauszeiger male (siehe rotes Rechteck im Anhang) und auch gemalt wird, wenn sich der Mauszeiger außerhalb des Labels befindet.
Die QWidget::map...-Funktionen anschauen und raten (oder verstehen ;)) welche du brauchst.
Und zum anderen versucht mein Prog von Anfang an auf das Label zu zeichnen,
Klar - es empfängt halt paintEvents
anstatt wie gewollt erst zu zeichnen wenn das Bild mittel Button geladen wurde ( connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(bildLaden())); ). Logischerweise stürtzt das Programm ab, wenn das Bild noch nicht geladen wurde.
Hast du denn noch immer irgendwo ein eigenes paintEvent stehen?
Da ich wenig Lust auf Raten habe bitte mal den kompletten Code in ein zip packen und anhängen (Code sagt mehr als tausend Bildchen).
Es muss doch auch möglich sein, den MouseEvent erst in meiner bildLaden() Funktion aufzurufen oder?
Nö - wie denn? Die MausEvents werden VERTEILT - irgend jemand (nicht du!) schickt dem Widget ein Event. Dahinter steht in den allermeisten Fällen das Windowing System, das dir dankenswerterweise Qt einfach wegkapselt.
Deine Aufgabe besteht jetzt eigentlich nur darin, dafür zu sorgen dass nichts doofes/unvorhergesehenes passiert und die Corner-Cases (oops, noch kein Bild geladen) abgefangen werden bzw. erst gar nicht auftreten.
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Re: Frage zum Scribble Example[gelöst]

Beitrag von Saul »

Hi franzf,
hm also eine QWidget::map...-Funktionen besitze ich nicht =(

Du gibts mir Rätels auf, die ich leider nicht verstehe =)
Also in meinem Projekt ist kein paintEvent mehr vorhanden. Nur noch die mouseEvents um die Aktionen der Mouse abzufangen. Der oben gepostete Code entspricht eigentlich dem gesamten Code meines Projekts, aber ich hänge meine Projektdateien mal als Anhang dazu.
Wäre wirklich sehr nett wenn du mal reinschnuppern könntest.
Zuletzt geändert von Saul am 25. Juli 2012 09:29, insgesamt 1-mal geändert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Frage zum Scribble Example[gelöst]

Beitrag von franzf »

Assistant aufmachen, Doku zu QWidget öffnen und einfach mal nach "map" suchen lassen. Es gibt DREI Funktionen die mit map anfangen, eine davon wird dir helfen...
Antworten