alle Formularwerte speichern und laden

Alles rund um die Programmierung mit Qt
Antworten
GoaSkin
Beiträge: 103
Registriert: 13. Juni 2007 00:14
Wohnort: Darmstadt

alle Formularwerte speichern und laden

Beitrag von GoaSkin »

Für ein Programm benötige ich eine Funktion, die die Inhalte von Formularfeldern (hauptsächlich Textfelder, Slider und Spinboxen) in irgend einer Form in eine Datei speichert.

Da es aber eine mühsame Arbeit wäre, Variable für Variable durchzugehen und in eine Datei abzulegen (bei ca. 200 Eingabe-Widgets) würde es mich einmal interessieren, ob QT vielleicht eine Funktion bietet, die alle Werte eines Fensters als XML-Datei exportiert und anhand einer solchen Datei auch die Werte wieder neu setzen. Naja, fündig wurde ich in der Referenz nicht. Wenn QT das nicht kann, weiss jemand ggf. ob es wo eine solche Funktion zum Download gibt?
Whitefurrows
Beiträge: 138
Registriert: 1. Mai 2006 19:50

Beitrag von Whitefurrows »

Hallo,

schaue dir mal folgende funktionen von QWidget an:
http://doc.trolltech.com/4.2/qobject.html#findChildren
http://doc.trolltech.com/4.2/qobject.ht ... Children-2

so solltest du alle Werte recht einfach auslesen können, wie du sie dann abspeicherst bleibt dir überlassen.

Gruß,

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

Beitrag von upsala »

Und das hier:

Code: Alles auswählen

QMetaProperty QMetaObject::userProperty () const
GoaSkin
Beiträge: 103
Registriert: 13. Juni 2007 00:14
Wohnort: Darmstadt

Beitrag von GoaSkin »

danke für die Tipps erstmal...

ich versuche gerade, eine Funktion zum Speichern zu erzeugen, wobei er hier im Array die Objekt-Eigenschaften (hier: objectName und textFromValue) nicht mehr erkennt....

Code: Alles auswählen

// save XML file of all the needed form values into the user directory
bool SC4C::save() 
	{ 
	// find out what necessary values do exist... if you want to use new widgets in the UI, you need to modify this function
	QList<QDoubleSpinBox *> allDoubleSpinBoxes = qFindChildren<QDoubleSpinBox *>(this);
	QList<QSpinBox *> allSpinBoxes = qFindChildren<QSpinBox *>(this);
	QList<QSlider *> allSliders = qFindChildren<QSlider *>(this);
	
	// create template XML file (actually static, may be dynamized in future versions)
	QFile file;
	
    file.setFileName("sc4config.conf");
    file.open(stderr, QIODevice::WriteOnly);
	file.write("<XML>\n");
	file.write("<DoubleSpinBoxes>\n");
	 
	// create arrays with widget contents
	for(int ii = 0; ii < allDoubleSpinBoxes.size(); ++ii)
		{
 		QString widgetEntry = "<Element NAME=\"";
		widgetEntry.append(allDoubleSpinBoxes[ii].objectName);
		widgetEntry.append("\" VALUE=\"");
		widgetEntry.append(allDoubleSpinBoxes[ii].textFromValue);
		widgetEntry.append("\"/>\n");
		file.write(widgetEntry, qstrlen(widgetEntry));
		}

	// close and save the configuration file
	file.write("</DoubleSpinBoxes>\n");
	file.write("</XML>\n");
	file.close();	
	}
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

widgetEntry.append(allDoubleSpinBoxes[ii].objectName);
objectName ist eine Funktion und keine Variable...
GoaSkin
Beiträge: 103
Registriert: 13. Juni 2007 00:14
Wohnort: Darmstadt

Beitrag von GoaSkin »

Ich dachte objectName hat einen Rückgabewert vom Typ QString. Was müsste ich ändern, um den im Designer gesetzten Feldnamen zu erhalten?
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Um einen Rückgabewert zu bekommen, musst Du aber auch die Funktion aufrufen.

Code: Alles auswählen

widgetEntry.append(allDoubleSpinBoxes[ii].objectName());
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
GoaSkin
Beiträge: 103
Registriert: 13. Juni 2007 00:14
Wohnort: Darmstadt

Re: alle Formularwerte speichern und laden

Beitrag von GoaSkin »

Hallo,

12 Jahre später bin ich wieder im Rahmen eines anderen Projektes bei diesem Thema und krame deshalb den alten Topic wieder raus.


Gibt es eine Möglichkeit, mit qFindchildren auch eine Liste zu erzeugen, die alphabetisch nach dem Widget-Namen statt nach der Definitionsreihenfolge sortiert ist?
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: alle Formularwerte speichern und laden

Beitrag von veeman »

qFindChildren ist obsolete, verwende direkt die findChildren funktion von QWidget bzw. QObject.

Und ja du kannst die zurückgegebene List nach belieben sortieren.

Beispiel um die Sortierung nach dem Namen durchzuführen:

Code: Alles auswählen

auto items = this->findChildren<QWidget*>();
std::sort(items.begin(), items.end(), [](QWidget *a, QWidget* b) { return a->objectName() < b->objectName(); });
Ansonsten kannst du diverse Widget Eigenschaften mit der Funktion property abfragen; anbei ein vollständiges Beispiel um diverse Widget Eigenschaften als Binary zu speichern / zu laden:

Code: Alles auswählen

#include "QtGuiApplication.h"
#include <QCloseEvent>
#include <QWidget>

typedef void(*visualStateSelector)(QWidget * const widget, QSet<QString> &propertyList);


void defaultVisualStateSelector(QWidget * const widget, QSet<QString> &propertyList)
{
	auto const lineEdit = qobject_cast<QLineEdit*>(widget);
	if (lineEdit != nullptr)
	{
		propertyList << "text";
		return;
	}

	auto const checkBox = qobject_cast<QCheckBox*>(widget);
	if (checkBox != nullptr)
	{
		propertyList << "checked" << "tristate";
		return;
	}

	auto const spinBox = qobject_cast<QSpinBox*>(widget);
	if (spinBox != nullptr)
	{
		propertyList << "minimum" << "maximum" << "value";
		return;
	}

	auto const doubleSpinBox = qobject_cast<QDoubleSpinBox*>(widget);
	if (doubleSpinBox != nullptr)
	{
		propertyList << "minimum" << "maximum" << "value";
		return;
	}

	auto const slider = qobject_cast<QAbstractSlider *>(widget);
	if (slider != nullptr)
	{
		propertyList << "minimum" << "maximum" << "value";
		return;
	}

	auto const abstractButton = qobject_cast<QAbstractButton*>(widget);
	if (abstractButton != nullptr)
	{
		propertyList << "checked" << "down";
		return;
	}
}


void saveVisualState(QString const & fileName, QWidget const & widget, visualStateSelector const selector = defaultVisualStateSelector)
{
	QFile file(fileName);

	QVariantMap propertyMap;

	for (auto const child: widget.findChildren<QWidget*>())
	{
		auto const name = child->objectName();
		if (name.isEmpty())
			continue;

		auto const properties = child->property("store").toString();
		auto propertyList = properties.split(",", QString::SkipEmptyParts).toSet();

		selector(child, propertyList);

		for (auto const property : propertyList)
		{
			auto const pname = property.trimmed();
			auto const cname = pname.toStdString();
			auto const value = child->property(cname.c_str());

			propertyMap.insert(QString("%0.%1").arg(name).arg(pname), value);
		}
	}

	if (file.open(QFile::WriteOnly | QFile::Truncate))
	{
		QDataStream out(&file);
		out << propertyMap;
	}

	file.close();
}


void loadVisualState(QString const & fileName, QWidget & widget, visualStateSelector const selector = defaultVisualStateSelector)
{
	QFile file(fileName);

	if (!file.exists())
		return;

	QVariantMap propertyMap;

	if (file.open(QFile::ReadOnly))
	{
		QDataStream out(&file);
		out >> propertyMap;
	}
	else
		return;

	file.close();

	for (auto const child : widget.findChildren<QWidget*>())
	{
		auto const name = child->objectName();
		if (name.isEmpty())
			continue;

		auto const properties = child->property("store").toString();
		auto propertyList = properties.split(",", QString::SkipEmptyParts).toSet();

		selector(child, propertyList);

		for (auto const property : propertyList)
		{
			auto const pname = property.trimmed();
			auto const cname = pname.toStdString();

			auto const key = QString("%0.%1").arg(name).arg(pname);
			
			auto valueIt = propertyMap.constFind(key);

			if (valueIt == propertyMap.constEnd())
				continue;

			child->setProperty(cname.c_str(), *valueIt);
		}
	}
}


QtGuiApplication::QtGuiApplication(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	loadVisualState("app.vstate", *this);
}


void QtGuiApplication::closeEvent(QCloseEvent *event)
{
	saveVisualState("app.vstate", *this);
	event->accept();
}
Antworten