Seite 1 von 1

QGraphicsView in MDI-Dokument

Verfasst: 27. März 2011 10:36
von Venni
Hallo,

in meiner Anwendung habe ich einen QWorkspace, in dem verschiedene Diagramme und eine "Karte des Himmels" (sog. Skyplot) dargestellt werden sollen. Die Diagramme funktionieren, aber mit dem Skyplot gibt es noch Schwierigkeiten.

Der Skyplot soll ein QWidget sein, das lediglich ein QGraphicsView beinhaltet (und ganz ausfüllt). Wenn die Grösse des Widgets verändert wird, soll auch der Inhalt angepaßt werden.

Hier mein erster Versuch:

Header-File:
------------

Code: Alles auswählen

#ifndef ARANEAGUI_SKYPLOT_CLASS_H
#define ARANEAGUI_SKYPLOT_CLASS_H

#include <QWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
//#include <QGridLayout>

class araneagui_skyplot_class : public QWidget {

  public:
  araneagui_skyplot_class(QWidget *parent);

//  protected:
//  void resizeEvent(QResizeEvent event);

  private:
  void paint();

};

#endif

Implementierung:
----------------

Code: Alles auswählen

#include "araneagui_skyplot_class.h"

araneagui_skyplot_class::araneagui_skyplot_class(QWidget* parent = 0) : QWidget(parent) {

  resize(200, 200);
  paint();

}

//void araneagui_skyplot_class::resizeEvent(QResizeEvent event) {
//  qDebug( "RESIZE" ); 
//}

void araneagui_skyplot_class::paint() {

 QGraphicsScene* scene = new QGraphicsScene;
 scene->setSceneRect( -100.0, -100.0, 200.0, 200.0 );

 QGraphicsEllipseItem *item = new QGraphicsEllipseItem( 0, scene );
 item->setRect( -50.0, -50.0, 100.0, 100.0 );

 QGraphicsEllipseItem *item2 = new QGraphicsEllipseItem( 0, scene );
 item2->setRect( -20.0, -50.0, 10.0, 10.0 );

 QGraphicsView* view = new QGraphicsView(scene, this);
 view->setRenderHints( QPainter::Antialiasing );
 view->show();

}

Muß ich resizeEvent anpassen, mit Layouts und mit QGraphicsView::fitInView arbeiten? Bin für jede Hilfe sehr dankbar!

Gruß,
Markus

Verfasst: 27. März 2011 10:47
von franzf
Was soll das Aufsetzen von View und Scene in einer paint()?!?
Der SkyPlot enthält eine view, ich seh aber keinen Member. Damit kommst du nur über Umwege (find Children()) an die view.

Die Lösung: setze ein Layout in dein Widget (this), und packe da einfach die view rein. resizeEvent wäre auch eine Option, aber eher die schlechtere, weil du alles selber schreiben musst, was das Layout von schon kann - außerdem müsstest du Zugriff auf die view haben (s.O.)

Ansonsten: Was sind das für Klassennamen?!?
C++ kennt namespaces, auch verschachtelte. Und warum das "class" hinten raus? Steht dann da auch überall "typedef" und "struct" usw.?
M.M.n. reicht das vollkommen:

Code: Alles auswählen

namespace aranea {
namespace gui {
class skyplot : public QWidget {
    // usw.
};
}
}

// Zugriff:
aranea::gui::skyplot plot;

Verfasst: 27. März 2011 12:50
von Venni
Danke für die schnelle Antwort!

Das mit der paint-Funktion war nur ein Test. Ich habe es jetzt folgendermaßen geändert:

Code: Alles auswählen

#ifndef ARANEAGUI_SKYPLOT_H
#define ARANEAGUI_SKYPLOT_H

#include <QWidget>
// Einbinden von QGraphicsScene etc. erzeugt Fehler!

class araneagui_skyplot : public QWidget {

  public:
  araneagui_skyplot(QWidget *parent);

  private:
//  QGraphicsScene* scene;
//  QGraphicsView*  view;

};

#endif

Code: Alles auswählen

#include <QGridLayout>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>

#include "araneagui_skyplot.h"

araneagui_skyplot::araneagui_skyplot(QWidget* parent) : QWidget(parent) {

 QGraphicsScene* scene = new QGraphicsScene;
 scene->setSceneRect( -100.0, -100.0, 200.0, 200.0 );

 QGraphicsEllipseItem *item = new QGraphicsEllipseItem( 0, scene );
 item->setRect( -50.0, -50.0, 100.0, 100.0 );

 QGraphicsEllipseItem *item2 = new QGraphicsEllipseItem( 0, scene );
 item2->setRect( -20.0, -50.0, 10.0, 10.0 );

 QGridLayout* layout = new QGridLayout;
 this->setLayout( layout );

 QGraphicsView* view = new QGraphicsView(scene, this);
 view->setRenderHints( QPainter::Antialiasing );
 view->show();

 layout->addWidget( view );

}
Natürlich wäre es viel besser, "scene" und "view" als members zu deklarieren, aber wenn ich

Code: Alles auswählen

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
im Header-File einbinde, kommen Fehlermeldungen:

Code: Alles auswählen

// In file included from /usr/include/QtGui/QGraphicsScene:1:0,
//                  from src/araneagui_skyplot.h:6,
//                  from src/araneagui_mainwindow.h:17,
//                  from src/araneagui_main.cpp:2:
// /usr/include/QtGui/qgraphicsscene.h:318:1: error: expected ‘,’ or ‘...’ before numeric constant
// /usr/include/QtGui/qgraphicsscene.h:318:1: error: ‘QFlags<QGraphicsScene::SceneLayer> operator|(QFlags<QGraphicsScene::SceneLa
// [...]
Woran liegt das?

Das Einbinden in ein Layout funktioniert, aber jetzt würde ich gerne auch den INHALT des views skalieren. Wie geht das?


Vielen Dank,
Markus

// franzf: code-tags eingefügt, bitte zukünftig gleich selber machen, danke

Verfasst: 27. März 2011 13:15
von franzf
Dein Compile-error kommt recht sicher daher, dass du vor den Qt-Headern eigene Header einbindest, in denen ein Fehler ist. Z.B. (recht beliebt) fehlt ein ";" nach einer KLassendefinition.

Dein scene->setSceneRect() ist gefährlich, da du garantiert NICHT weißt, was das macht ;) (du willst es nicht setzen).
Für das Anpassen an die view implementierst du resizeEvent() in deinem Widget, da drin musst du dann nur view->fitInView() mit einem passenden Parameter aufrufen (das Spielen überlass ich dir, sollte nicht so schwer sein :)).

Deinen QGraphicsEllipseItem-Konstruktor gibt es nicht (mehr).
Das geht alles VIEL einfacher:

Code: Alles auswählen

araneagui_skyplot::araneagui_skyplot(QWidget* parent) : QWidget(parent) {
 QGraphicsScene* scene = new QGraphicsScene;
 scene->addEllipse( -50.0, -50.0, 100.0, 100.0 );
 scene->addEllipse( -20.0, -50.0, 10.0, 10.0 );

 QVBoxLayout* layout = new QVBoxLayout(this); // box ist das einfachere Layout

 QGraphicsView* view = new QGraphicsView(scene);
 view->setRenderHints( QPainter::Antialiasing );
 // view->show(); brauchts nicht, wird eh angezeigt, sobald das parent-widget sichbar wird.

 layout->addWidget( view );
}

Verfasst: 27. März 2011 14:24
von Venni
Super, vielen Dank für die Hinweise! Ich habe es jetzt hinbekommen. Der (Pre-)Compiler-Fehler lag daran, dass ich irgendwo ein "#define f1" stehen hatte, das offenbar in Qt auch verwendet wurde...

Das fitInView funktioniert auch. Jetzt würde ich nur noch gerne wissen, ob ich einstellen kann, dass die Grössenänderung des Widgets nur mit festen Verhältnis erfolgen soll. Also: Die Höhe des Widgets soll immer 2xBreite sein; und das soll auch beim Vergrößern/Verkleinern so bleiben.

Danke schön!

Verfasst: 27. März 2011 17:20
von franzf
Google -> "QWidget keep aspect ratio" sollte einiges an Anschauungsmaterial liefern.

Verfasst: 27. März 2011 19:06
von Venni
Habe alles so hinbekommen, wie ich es haben wollte. Noch Mal vielen Dank für Deine Hilfe!