Seite 1 von 1

Probleme mit QGraphicsPixmapItem

Verfasst: 19. Juli 2011 17:16
von hardi
Hallo Qt-Profis,
ich arbeite erst seit kurzem mit Qt und tüftele an einem Tool zur Anzeige und Manipulation von Bildern mit Qt Creator und Cpp.
Das zu editierende Bild positioniere ich als überladenes QGraphicsPixmapItem-Objekt (namentlich Klasse PixmapItem) auf der QGraphicsScene.
Mit Programmstart wird automatisch ein zufällig gewähltes Startbild auf der Szene dargestellt.

Nun zu meinen Fragen:
- Ich erhalte stets folgendes Build-Problem für pixmapitem.h und kenne den Grund hierfür nicht: "Warning: No relevant classes found. No output generated." Woran liegt das?
- WIESO stürzt mein Programm manchmal nach dem Laden eines neuen Bildes in PixmapItem::reset() mit einem Speicherzugriffsfehler ab? Liegt das am static_cast? Ich habe leider keine bessere Idee zur Initialisierung von Variable imageItem_ gefunden!
- WIE und WANN kann ich auf die Pixmap von PixmapItem aus zugreifen und diese aktualisieren? Soweit mir bekannt klappt es mit PixmapItem::pixmap() bzw. PixmapItem::setPixmap(QPixmap), allerdings bekomme ich dann folgenden Fehler: QPixmap::operator=: Cannot assign to pixmap during painting!!!
- WELCHE Rolle spielt PixmapItem::paint() in meiner Anwendung? Ich möchte später in paint() das aktuelle Bild gegebenfalls nach Manipulation neu zeichnen lassen ... gibt es noch einen alternativen Weg hierfür?

Ich hoffe ihr könnt mir helfen!!!

Hier mein Code:
imageviewer.h

Code: Alles auswählen

#ifndef IMAGEVIEWER_H_
#define IMAGEVIEWER_H_

#include <QtGui>
#include <QMainWindow>
#include <iostream>
#include <cstdlib>
#include "pixmapitem.h"

 class QAction;
 class QMenu;

 class ImageViewer : public QMainWindow
 {
     Q_OBJECT

 private:
    QGraphicsScene *scene_;
    QGraphicsView *view_;
    PixmapItem *imageItem_;
 
 public:
     ImageViewer(QWidget *parent = 0);
     ~ImageViewer() {};

 private slots:
     void open( QString fileName="" );
 }; 
 
imageviewer.cpp

Code: Alles auswählen

 #include "imageviewer.h"
 using namespace std;
 
ImageViewer::ImageViewer(QWidget *parent) : QMainWindow(parent)
 {
     scene_ = new QGraphicsScene();
     view_  = new QGraphicsView(scene_);
     open([i]filepath[/i]);
     view_->setRenderHint(QPainter::Antialiasing);
     view_->setBackgroundBrush(QColor(255, 255, 200));//*backgroundPixmap);
     view_->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
     view_->setDragMode(QGraphicsView::ScrollHandDrag);
     view_->show();
}

void ImageViewer::open(QString path) {

	 QPixmap pixmap;
	 if ((path.isEmpty()) || (path.indexOf('.') == -1)) // open dialog
	 {
          	 imageItem_->reset(); 
		 path = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath());
	         if (path.isEmpty()) return; // no image chosen
                 pixmap = QPixmap(path);
		 imageItem_->setPixmap(pixmap);
	 }
	 else  // initialization
	 {
		 pixmap = QPixmap(path);
		 imageItem_ = static_cast<PixmapItem *> (scene_->addPixmap(pixmap));
         }
         scene_->setSceneRect(0, 0, pixmap.width(), pixmap.height());
	 cout << "Opening " << path.toStdString() << endl;
}
...
pixmapitem.h

Code: Alles auswählen

#ifndef PIXMAPITEM_H_
#define PIXMAPITEM_H_

//#include <QGraphicsItem>
#include <QtGui>
#include <iostream>

 class PixmapItem : public QGraphicsPixmapItem {

 public:
     QString color_;
 private:
      size_t width_, height_;

 public:
      PixmapItem();
      void reset();
      size_t height() { return height_; }
      size_t width()  { return width_; }
      void savePixmap(QPixmap&); 
 protected:
      virtual QRectF boundingRect() const; ///< must be re-implemented in this class to provide the dimensions of the box to the QGraphicsView
      virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ///< must be re-implemented here to pain the box on the paint-event
 };
#endif /* PIXMAPITEM_H_ */
pixmapitem.cpp

Code: Alles auswählen

#include "pixmapitem.h"
using namespace std;

PixmapItem::PixmapItem() {
	reset();
}

void PixmapItem::reset() {
	cout << "PixmapItem::reset" << endl;
	color_ = "rgb";
	cout << "PixmapItem::reset2" << endl;
}

void PixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
}

QRectF PixmapItem::boundingRect() const {
    return QRectF(0,0,width_,height_);
}
Ich freue mich über alle Hinweise von Euch!!!

Viele Grüße
hardi

Re: Probleme mit QGraphicsPixmapItem

Verfasst: 19. Juli 2011 17:50
von franzf
hardi hat geschrieben:- Ich erhalte stets folgendes Build-Problem für pixmapitem.h und kenne den Grund hierfür nicht: "Warning: No relevant classes found. No output generated." Woran liegt das?
Schaut so aus, als würdest du den Header dem moc zum moccen geben. Deine Klasse ist aber nicht von QObject abgeleitet.
- WIESO stürzt mein Programm manchmal nach dem Laden eines neuen Bildes in PixmapItem::reset() mit einem Speicherzugriffsfehler ab? Liegt das am static_cast? Ich habe leider keine bessere Idee zur Initialisierung von Variable imageItem_ gefunden!

Code: Alles auswählen

imageItem_ = static_cast<PixmapItem *> (scene_->addPixmap(pixmap));
Das tut ehrlich gesagt so richtig weh...
QGraphicsScene::addPixmap ist eine Vereinfachung zum Hinzufügen von QGraphicsPixmapItems. Entsprechend ist der return ein QGraphicsPixmapItem*. Dein cast kann nur schief gehen, da addPixmap rein gar nix von deiner PixmapItem-Klasse weiß und auch nie eines instanziiert!.
Du musst also selber eine Instanz deiner Klasse erstellen und diese per addItem der scene nizufügen.
- WIE und WANN kann ich auf die Pixmap von PixmapItem aus zugreifen und diese aktualisieren? Soweit mir bekannt klappt es mit PixmapItem::pixmap() bzw. PixmapItem::setPixmap(QPixmap), allerdings bekomme ich dann folgenden Fehler: QPixmap::operator=: Cannot assign to pixmap during painting!!!
Das ist nicht dein ganzer Code.
Ich nehme an, du hast einen QPainter auf dem Pixmap offen, und bevor der mit end() beendet wurde, wolltest du dem was zuweisen.
Ich hab aber diese Meldung noch nie gesehen, drum kann ich nichts damit anfangen. Und dein Code gibt dazu eigentlich auch nichts her.
- WELCHE Rolle spielt PixmapItem::paint() in meiner Anwendung? Ich möchte später in paint() das aktuelle Bild gegebenfalls nach Manipulation neu zeichnen lassen ... gibt es noch einen alternativen Weg hierfür?
paint() zeichnet. Wenn du es nicht verstehst, wäre die Doku zum Qt Graphics View Framework nicht schlecht (sollte von den ganzen GraphicsView-Klassen verlinkt sein).

Re: Probleme mit QGraphicsPixmapItem

Verfasst: 20. Juli 2011 10:36
von hardi
Hallo franzf,
zunächst mal vielen Dank für deine Hinweise. Mein Programm läuft nun ohne Warnungen und zeigt mir die gewünschten Bilder .
Meine Updates habe ich mal kommentiert.
franzf hat geschrieben:
hardi hat geschrieben:- Ich erhalte stets folgendes Build-Problem für pixmapitem.h und kenne den Grund hierfür nicht: "Warning: No relevant classes found. No output generated." Woran liegt das?
Schaut so aus, als würdest du den Header dem moc zum moccen geben. Deine Klasse ist aber nicht von QObject abgeleitet.
Ich habe nicht Q_OBJECT im Header eingefügt! Die Warnung verschwand nachdem paint() seine Funktion bekam.
franzf hat geschrieben:
hardi hat geschrieben:- WIESO stürzt mein Programm manchmal nach dem Laden eines neuen Bildes in PixmapItem::reset() mit einem Speicherzugriffsfehler ab? Liegt das am static_cast? Ich habe leider keine bessere Idee zur Initialisierung von Variable imageItem_ gefunden!

Code: Alles auswählen

imageItem_ = static_cast<PixmapItem *> (scene_->addPixmap(pixmap));
Das tut ehrlich gesagt so richtig weh...
QGraphicsScene::addPixmap ist eine Vereinfachung zum Hinzufügen von QGraphicsPixmapItems. Entsprechend ist der return ein QGraphicsPixmapItem*. Dein cast kann nur schief gehen, da addPixmap rein gar nix von deiner PixmapItem-Klasse weiß und auch nie eines instanziiert!.
Du musst also selber eine Instanz deiner Klasse erstellen und diese per addItem der scene nizufügen.
Ich hoffe, die Schmerzen waren nicht zu schlimm ... die Umsetzung von deinem Tipp hat sofort funktioniert.
franzf hat geschrieben:
hardi hat geschrieben:- WIE und WANN kann ich auf die Pixmap von PixmapItem aus zugreifen und diese aktualisieren? Soweit mir bekannt klappt es mit PixmapItem::pixmap() bzw. PixmapItem::setPixmap(QPixmap), allerdings bekomme ich dann folgenden Fehler: QPixmap::operator=: Cannot assign to pixmap during painting!!!
Das ist nicht dein ganzer Code.
Ich nehme an, du hast einen QPainter auf dem Pixmap offen, und bevor der mit end() beendet wurde, wolltest du dem was zuweisen.
Ich hab aber diese Meldung noch nie gesehen, drum kann ich nichts damit anfangen. Und dein Code gibt dazu eigentlich auch nichts her.
Dieser Fehler entstand nachdem ich folgendes nach Aufruf von (schmerzhaftem) static_cast in einer neuen Memberfunktion von PixmapItem getestet habe:

Code: Alles auswählen

QPixmap pmap = pixmap().copy();
setPixmap(pmap);  
Ich verstehe nun, dass dies sinnlos war nach static_cast.

Vielen Dank nochmals.
hardi