Wie erstelle ich MDI Kinder Dialoge

Alles rund um die Programmierung mit Qt
Antworten
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Wie erstelle ich MDI Kinder Dialoge

Beitrag von pospiech »

Ich have in MainWindow eine MdiArea in der einige Dialoge als MDI-Dialgoe dargestellt werden sollen.

Aus dem MDI Beispiel und der Doku konnte ich aber nicht entnehmen wie das gehen soll.

Wie macht man sowas dann ?

Matthias
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Auch ein QDialog ist ein QWidget und dafür gibt es passende Beispiele unter QMdiArea::addSubWindow()

edit: Wobei sich natürlich die Frage stellt, warum dann ein QDialog verwendet werden soll, da ein QDialog::exec() in diesem Fall keinen Sinn macht...
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

Ich habe jetzt eine mit QDialog überladene MdiChild Klassse geschreiben mit der ich dann die eigentlichen Dialoge überladen kann:

Code: Alles auswählen

#ifndef MDICHILD_H_
#define MDICHILD_H_

#include <QtGui/QMdiArea>
#include <QtCore/QString>
#include <QtGui/QDialog>

class MdiChild : public QDialog
{
	Q_OBJECT
public:
	MdiChild(QWidget* parent = 0, QMdiArea * area = 0, Qt::WFlags flags = 0);
	virtual ~MdiChild();

	void setDescription(const QString & str);
	QString Description();
	void makeMDIChild(QWidget * widget);

private:
	QString m_description;
	QMdiArea * m_parent_mdiArea;

};
#endif

Code: Alles auswählen

#include "MdiChild.h"

MdiChild::MdiChild(QWidget* parent, QMdiArea * area, Qt::WFlags flags /*= 0*/) 
	: QDialog(parent , Qt::Dialog | Qt::WindowMinMaxButtonsHint ), m_parent_mdiArea(area)
{		
}

MdiChild::~MdiChild()
{
}

void MdiChild::setDescription(const QString & str)
{
	m_description = str;
}

QString MdiChild::Description()
{
	return m_description;
}

void MdiChild::makeMDIChild(QWidget * widget)
{
	m_parent_mdiArea->addSubWindow(widget);
}

Code: Alles auswählen

#ifndef DialogBeamView_H_
#define DialogBeamView_H_

#include "Ui_DialogBeamView.h"
#include "GlobalClasses.h"
#include "MdiChild.h"

class DialogBeamView : public MdiChild, protected Ui_DialogBeamView
{
	//Q_OBJECT
public:
	DialogBeamView(QWidget* parent = 0,  QMdiArea * area = 0, Qt::WFlags flags = 0);
	virtual ~DialogBeamView();

...
};
#endif

Code: Alles auswählen

#include "DialogBeamView.h"

DialogBeamView::DialogBeamView(QWidget* parent /*= 0*/, QMdiArea * area, Qt::WFlags flags /*= 0*/) 
: MdiChild(parent, area, flags) 
{
	setupUi(this);
	makeMDIChild(this);
	setDescription("Complex Beam View");
}

DialogBeamView::~DialogBeamView()
{
}

Code: Alles auswählen

void MainWindow::OnButtonViewShape()
{
	int preview = ListPhaseObjects()->currentRow();	
	if (preview >= 0 )
	{	
		DialogBeamView * otherdlgBeamView = new DialogBeamView(this, mdiArea);
		updateMenuView();
		otherdlgBeamView->show();
		otherdlgBeamView->activateWindow();	
	}
}
Ob das jetzt ein besonders gelungenes Design ist kann ich nicht sagen, aber es funktioniert.

Matthias
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

Im Nachhinein konnte ich jetzt feststellen, das dieser Ansatz dazu führt, dass bei einem CloseEvent nur das Widget innerhalb des Dialogs gelöscht wird, aber nicht der Dialog selbst - wenn ich ein close() auslöse.

Wenn ich hingegen auf X klicke dann wird der Dialog komplett zerstört. Was ist denn der Unterschied zwischen 'X' klicken und close() aufrufen?
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Midi childs sollten keine dialoge sein

QMdiArea kenn ich noch ned .... scheint aber maechtig zu sein.

Ich hab immer QWorkspace + einfache von QWidget abgeleitete Fenster verwendet. funktionierte wunderbar.

bei QMdiArea sollten alle deine MDI childs von QMdiSubWindow abgeleitet sein, ned von QDialog

Ciao ...
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

RHBaum hat geschrieben: bei QMdiArea sollten alle deine MDI childs von QMdiSubWindow abgeleitet sein, ned von QDialog
Das geht aber nicht.

Denn ich kann im Designer gar keine QMdiSubWindow Sachen erstellen und habe natürlich alle Dialoge auch als QDialog definiert.

Wenn ich nun statt von QDialog von QMdiSubWindow ableite dann bekomme ich die Fehler
.\src\DialogBeamView.cpp(6) : error C2664: 'Ui_DialogBeamView::setupUi': Konvertierung des Parameters 1 von 'DialogBeamView *const ' in 'QDialog *' nicht möglich

1>.\src\DialogFiberSensor.cpp(279) : error C2039: 'exec': Ist kein Element von 'DialogPIMove'
Ersteres weil die Klassen nicht mehr stimmen und zweites vermutlich weil keine eventhandler mehr exisitert.

Da ich im Designer solche QMdiSubWindow nicht erstellen kann und auch nicht sehe wie ich einen QDialog Dialog in einen QWidget Dialog im Designer ändern könnte ist mir unklar wie ich die Dialoge nun zu Mdi Kindern machen soll.
[/code]
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

RHBaum hat geschrieben: bei QMdiArea sollten alle deine MDI childs von QMdiSubWindow abgeleitet sein, ned von QDialog
Ich habe jetzt die Dialoge zu QWidgets umgewandelt und lasse sie von MdiChild ableiten, was selber von QMdiSubWindow ableitet.

Ergebnis: Es kompiliert - ABER es wird nur Unsinn angezeitg (Widget sonstwo außerhalb des Fensters und kein X zum Beenden).

Fazit: Mir ist noch immer vollkommen unklar wie es funktionieren sollte. Und die Doku und die Beispiele helfen mir auch nicht weiter, weil sie zu simpel sind.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

du hasst aber schon nen QMdiArea an deinem Mainwindow und fuegst die MDI childs da ein ?

Ciao ...
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

RHBaum hat geschrieben:du hasst aber schon nen QMdiArea an deinem Mainwindow und fuegst die MDI childs da ein ?
klar.

Jeder Dialog wird konstruiert über

Code: Alles auswählen

DialogBeamView * otherdlgBeamView = new DialogBeamView(this, mdiArea);
wobei der Dialog selber von MdiChild abgeleitet ist was selber von QDialog oder eben QMdiSubWindow ableitet. In den Konstruktoren wird dabei die
mdiArea immer weitergereicht, so dass MdiChild die QMdiArea von MainWindow kennt.

Wenn ich jetzt im Dialog (hier also DialogBeamView )

Code: Alles auswählen

makeMDIChild(this);
aufrufen, dann wird folgendes ausgeführt:

Code: Alles auswählen

void MdiChild::makeMDIChild(QWidget * widget)
{
   m_parent_mdiArea->addSubWindow(widget);
} 
also das Widget des Dialogs als SubWindow zur QMdiArea von MainWindow hinzugefügt.

Wenn ich diese Zeile nicht ausführe bleibt es ein normaler Dialog.

Erklärt das was ich mache?
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

klingt irgendwie bissi umstaendlich ....
m_parent_mdiArea->addSubWindow(widget);
wann wird das ausgefuehrt ... ist dann das widget schon sichtbar ?

Ciao ...
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

RHBaum hat geschrieben:
m_parent_mdiArea->addSubWindow(widget);
wann wird das ausgefuehrt ... ist dann das widget schon sichtbar ?
Im Konstruktor des Dialogs (hier DialogBeamView)

Matthias
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

hmmm, dann isses komisch ....
das dein QMdiArea das centralwidget ist von deinem mainwindow, davon geh ich mal aus ...

Die widget flags manipulierst du (nachtraeglich) nicht ?

Laut doku sollt es zumindest so funktionieren ... ich kenns nur mit QWorkspace, und da geht es deifnitiv so ... und die fenster kriegt man ned mehr aus dem MDI bereich raus ...

Ciao ...
pospiech
Beiträge: 232
Registriert: 1. September 2006 17:20
Wohnort: Hannover

Beitrag von pospiech »

In Qt-Interest habe ich inzwischen die Antwort bekommen.
The problem with QMdiArea is that it draws its own window and then places the widget inside the window. If your widget closes the window still remains open. I tried calling the slot "closeActiveSubWindow()" but there were situations when even after calling this slot the subwindow remained open. For the time being this the workaround that I use,

Code: Alles auswählen

    widget = new QWidget(this);
    QMdiSubWindow *win = mdiarea->addSubWindow(widget);
    widget->show();
    connect(widget, SIGNAL(destroyed()), win, SLOT(close()));
Meine Lösung sieht daher jetzt so aus:

Code: Alles auswählen

void MdiChild::makeMDIChild(QWidget * widget)
{
	QMdiSubWindow * win = m_parent_mdiArea->addSubWindow(widget);
	InternalWidget = widget;
	connect(widget, SIGNAL(destroyed()), win, SLOT(close()));    
}
Antworten