QGraphicsView in MDI-Dokument

Alles rund um die Programmierung mit Qt
Antworten
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

QGraphicsView in MDI-Dokument

Beitrag 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
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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;
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Beitrag 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
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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 );
}
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Beitrag 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!
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Google -> "QWidget keep aspect ratio" sollte einiges an Anschauungsmaterial liefern.
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Beitrag von Venni »

Habe alles so hinbekommen, wie ich es haben wollte. Noch Mal vielen Dank für Deine Hilfe!
Antworten