QPainter Problem

Alles rund um die Programmierung mit Qt
Antworten
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

QPainter Problem

Beitrag von joebar »

Hallo,

ich habe folgendes was funktioniert

Code: Alles auswählen


void RenderArea::paintEvent(QPaintEvent * /* event */){

	int blockSize = width() / 31;	
	QRectF bounds(0,0,blockSize,blockSize);
	QPainter painter(this);

	QFile myFile("/path/1.txt");
	if (!myFile.open(QIODevice::ReadOnly | QIODevice::Text)) return;

	QTextStream in(&myFile);
	while (!in.atEnd()){
		QString line = in.readLine();

		for(int i=0; i < 31; i++){	
			int squareType = line.section(',',i,i).toInt();
			if (squareType == 0){ 
				painter.translate(blockSize,0);
				continue;
			}
			QString squarePath = "/path/"+fieldItemMap.value(squareType)+".svg";
			renderer = new QSvgRenderer(squarePath);
			renderer -> render(&painter,bounds);
			painter.translate(blockSize,0);
		}
	painter.translate(-blockSize*31,blockSize);	
	}
}
Ich lege QPainter in jedem paint Event neu an, ich moechte QPainter nun als Klassenvariable anlegen damit ich QPainter nicht immer wieder neu erzeugen muss. Das obige auslesen kostet zuviel Zeit und ist nur einmal am Anfang und bei Aenderung der Fenstergroesse notwendig.

Ich habe also ganz naiv im .h file QPainter* background; deklariert, und im Konstruktor meiner Klasse RenderArea background = new QPainter(this);

Das Paint Event habe ich entsprechend so geaendert:

Code: Alles auswählen

void RenderArea::paintEvent(QPaintEvent * /* event */){
	int blockSize = width() / 31;
	// QPainter nicht mehr angelegt da Klassenvariable

	QFile myFile("/path/1.txt");
	if (!myFile.open(QIODevice::ReadOnly | QIODevice::Text)) return;

	QTextStream in(&myFile);
	while (!in.atEnd()){
		QString line = in.readLine();

		for(int i=0; i < 31; i++){	
			int squareType = line.section(',',i,i).toInt();
			if (squareType == 0){ 
				background -> translate(blockSize,0); // aus . ein -> gemacht da jetzt pointer
				continue;
			}
			QString squarePath = "/path/"+fieldItemMap.value(squareType)+".svg";
			renderer = new QSvgRenderer(squarePath);
			renderer -> render(background,bounds);
			background ->translate(blockSize,0); // aus . ein -> gemacht da jetzt pointer
		}
	background -> translate(-blockSize*31,blockSize); // aus . ein -> gemacht da jetzt pointer
		
	}
}

Beim ausfuehren bekomme ich

Code: Alles auswählen

QPainter::restore: Unbalanced save/restore
QPainter::setMatrix: Painter not active
QPainter::save: Painter not active
QPainter::setMatrix: Painter not active
QPainter::setMatrix: Painter not active
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setMatrix: Painter not active
QPainter::setMatrix: Painter not active
QPainter::restore: Unbalanced save/restore
QPainter::setMatrix: Painter not active
QPainter::save: Painter not active
QPainter::setMatrix: Painter not active
QPainter::setMatrix: Painter not active
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::restore: Unbalanced save/restore
QPainter::setMatrix: Painter not active
QPainter::setMatrix: Painter not active
Was will mir das sagen? Wo ist der Denkfehler?

Danke!
J.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Erstens vergisste Du QPainter::begin() und QPainter::end() und zweitens kannst Du nicht sicher sein dass die PaintDevice sich nicht doch geändert hat.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

Die Frage mag doof klingen, aber aus der Doku geht m.E. nicht hervor was die Entscheidungskriterien sind wann ich background -> begin(this) und background -> end() aufrufen muss. Ich habe versucht begin und end als "Klammer" um das angegebene Coding zu setzen und auch beides direkt am Ende aufzurufen wenn ich mein Painter fertig habe. Beides lieferte das gleiche Ergebnis wie zuvor.

Was meinst du mit ich kann mir nicht sicher sein, dass sich PaintDevice nicht geaendert hat? Beziehst du dich darauf dass ich noch resize events abfangen muss, das ist klar, oder beziehst du dich woanders drauf?

Danke,
J.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Leg den Painter wie jeder normale Programmierer im paintEvent an und fertig.

/edit: Wann begin() und end() aufgerufen werden muss ist doch wohl ersichtlich, oder?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

Sorry, aber wenns fuer mich ersichtlich waere haette ich nicht gefragt.

Nochmal sorry, aber wenn du mir sagst was ein "normaler" Programmierer macht dann werde ich das mal probieren. Ich habe im ersten Code-Teil den QPainter im event angelegt aber dann muss ich die angelegte Schleife immer wieder neu durchlaufen, was ich aus Performancegruenden nicht moechte. Das Neuanlegen des Hintergrunds ist ja nicht noetig wenn sich die Fenstergroesse nicht geaendert hat. Also was meinst du mit dem Anlegen im Event?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Code: Alles auswählen

bool QPainter::begin ( QPaintDevice * device )

Begins painting the paint device and returns true if successful; otherwise returns false.

bool QPainter::end ()

Ends painting. Any resources used while painting are released.
Ist wirklich sehr schwer zu verstehen...

/edit:

Code: Alles auswählen

#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
#include <QtGui/QPainter>

class QPaintEvent;
class Widget : public QMainWindow
{
  public:
    Widget() : mPainter(new QPainter()) {}
    virtual ~Widget() { delete mPainter; }
    virtual void paintEvent(QPaintEvent *e);
  protected:
    QPainter *mPainter;
};

void Widget::paintEvent(QPaintEvent *)
{
  mPainter->begin(this);
  mPainter->drawEllipse(20,20,40,40);
  mPainter->end();
}

int main(int argc, char**argv)
{
  QApplication app(argc, argv);

  Widget *main = new Widget();
  main->show();
  return app.exec();
}
funktioniert bei mir prima.
Allerdings macht es nicht wirklich viel Sinn - erstens kann man so leicht QPainter::end() vergessen und zweitens macht die Konstruktion eines QPainters nicht wirklich viel Overhead im Vergleich zu QPainter::begin() und den ganzen Zeichenfunktionen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten