Problem mit QTimeEdit

Alles rund um die Programmierung mit Qt
Antworten
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Problem mit QTimeEdit

Beitrag von taocp »

Hallo beisammen,

ich bin was Qt angeht noch ein völliger Noob und sollte mich eigentlich jetzt auch eher anderen Dingen widmen, aber das kleine Tool, das ich gerade erstelle, möchte ich noch fertig gestellt haben.
Das Problem bezieht sich darauf, dass ich diverse QRadioButtons habe, über die man eine Zeit für einen Timer auswählen kann. Der erste RadioButton soll sich dabei aber auf eine vom Benutzer selbst zu definierende Zeit beziehen, die mittels eines QTimeEdit Widgets eingegeben werden kann. Also relativ simpel der Abschnitt.
Jetzt segmentiert mein Programm aber, wenn ich die Sekunden des QTimeEdit Widgets einer privaten Klassenvariablen zuordnen möchte. Verwende ich -- wie bei den anderen RadioButtons -- fixe, voreingestellte Werte, so funktioniert es.
Der relevante Codeabschnitt sieht wie folgt aus:

Code: Alles auswählen

if (radioButton_1->isChecked())
	seconds = timeEdit->time().second();
else if (radioButton_2->isChecked())
	seconds = 180;
Verwende ich also den zweiten RadioButton, geht alles wie gewünscht weiter, aber wenn ich mit aktiviertem ersten RadioButton hantiere, stürzt das Programm ab. Die Variable seconds ist als int deklariert.
Kann mir jemand auf die Sprünge helfen, wo der Hund begraben liegt und wie ich das Problem gelöst bekomme?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

timeEdit ist auch korrekt initialisiert?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Beitrag von taocp »

Wurde vom Designer so automatisch vorgenommen:

Code: Alles auswählen

timeEdit = new QTimeEdit(Dialog);
Ganz kurios, folgendes funktioniert:

Code: Alles auswählen

std::cout << timeEdit->time().second();
aber die Zuweisung an meine Klassenvariable nicht. *hilfe*
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Das muss irgendwas anderes sein...
Versuche es mal eine lokalen Varaible zuzuweisen. Dies kannst du ja dann später der Klassenvariable zuweisen.
Nur so als Test.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Beitrag von taocp »

Das funktioniert leider auch nicht. Sobald ich den Wert von timeEdit->time().second() irgendeiner Variablen zuweise, schmiert das Programm ab.
Ich gebe daher jetzt mal den Quelltext meiner drei Dateien an, um die es sich handelt:
(1) main.cpp:

Code: Alles auswählen

#include <QApplication>
#include <QDialog>

#include "teatime.h"

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

	Dialog dialog;
	dialog.show();
	return app.exec();
}
(2) teatime.h

Code: Alles auswählen

#ifndef TEATIME_H_
#define TEATIME_H_

#include <QDialog>
#include <QTimer>

#include "ui_teatime.h"

class Dialog : public QDialog, public Ui::Dialog
{
	Q_OBJECT
	
public:
	Dialog(QWidget *parent = 0);
	
private slots:
	void setProgressBar();
	void startTimer();
	
private:
	int seconds, remaining, progress, progressStep;
};

#endif /*TEATIME_H_*/
(3) teatime.cpp:

Code: Alles auswählen

#include <QtGui>
#include <QtCore>

#include "teatime.h"
#include <iostream>

Dialog::Dialog(QWidget *parent) : QDialog(parent)
{
	setupUi(this);
}

void Dialog::setProgressBar()
{	
	remaining -= 1; // verbleibende Sekunden werden heruntergezählt
	
	if (remaining % progressStep == 0)
		++progress;
	progressBar->setValue(progress);
}

void Dialog::startTimer()
{
	// Check which radio button was selected
	if (radioButton_1->isChecked())
		seconds = timeEdit->time().second();
	else if (radioButton_2->isChecked())
		seconds = 180;
	else if (radioButton_3->isChecked())
		seconds = 300;
	else if (radioButton_4->isChecked())
		seconds = 420;

	remaining = seconds;
	progress = 0; // bisheriger Fortschritt in Prozent
	progressStep = seconds / 100; // wieviele Sekunden entsprechen einem Prozent
	
	QTimer *timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(setProgressBar()));
	timer->start(1000);
}
Die GUI-Elemente liegen in der ui_teatime.h worin sich auch die Erzeugung von

Code: Alles auswählen

timeEdit = new QTimeEdit(Dialog);
befindet (in der Funktion setupUi()).

Da steckt doch irgendwo ein Würmchen drin ...
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Beitrag von taocp »

Okay, ich glaube ich konnte das Problem lösen, wenngleich ich noch nicht genau verstanden habe, warum dies so sein muss. Ich erzeuge also jetzt innerhalb des if-Blocks ein temporäres QTime Objekt, welches mir erstmal den Wert für time() speichert und welches ich dann anschließend mit minute() und second() auslesen kann:

Code: Alles auswählen

if (radioButton_1->isChecked()) {
	QTime time = timeEdit->time();
	seconds = (time.minute() * 60) + time.second();
}
Warum muss ich das denn so machen?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Was für ein Compiler ist das?
Wenn ich richtig liege, werden die Objekte erst nach 'Zeilenende' gelöscht...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Beitrag von taocp »

mingw unter Windows:
gcc version 3.4.2 (mingw-special)
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Du hast die Lösung eigentlich schon selbst gefunden, wie es auch mit der ersten Variante funktionieren sollte:
Der SegFault kommt nicht von der Zuweisung, sondern von dem Wert, den du ausliest. second() liefert (wie du in deinem letzten Post richtig festgestellt hast) nur die Anzahl der Sekunden, nicht aber die Zeit in Sekunden. Wenn du dann die Sekunden in deinem timeEdit nicht verstellst, sind diese per default auf null. Somit ist dein remaining auf Null, was wahrscheinlich irgendwo zu einem Fehler führt.
Wenn du folgendes nimmst sollte es auch klappen:

Code: Alles auswählen

if (radioButton_1->isChecked()) { 
  
   seconds = (timeEdit->time().minute() * 60) + timeEdit->time().second(); 
}
Grüße
Franz

// Nachtrag:
Solche Sachen kannst du immer leicht rausfinden, wenn du vor und nach den kritischen Stellen eine debug-Ausgabe machst (qDebug()). So siehts du, wie weit dein Programm bei der Ausführung kommt, wo also der Fehler passiert.
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Beitrag von taocp »

Ahja, das ist ja mal sehr interessant. Und was meint ihr müsste ich nun vornehmen, um den Fall geschickt abzufangen, dass der Benutzer im QTimeEdit Feld nur Sekunden oder nur Minuten angibt? Denn nur wenn er beides manipuliert, funktioniert es derzeit. Initialisieren hilft nichts, da die Werte anscheinend wieder überschrieben werden.
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

Beitrag von taocp »

Oh, ich glaub ich hab den Fehler gefunden.
Ich manipuliere doch den Wert von progressStep anhand der eingegebenen Sekunden mit einer Division durch 100. Später verwende ich progressStep als Divisor für eine Modulo-Operation und wenn der 0 ist -> *bumm*
taocp
Beiträge: 12
Registriert: 10. Januar 2007 14:03

[gelöst] Problem mit QTimeEdit

Beitrag von taocp »

Also ich wollte mal den Titel auf gelöst setzen und hier noch schreiben, dass ich den kleinen Teil des Programms umgeschrieben habe. Ich verwende jetzt statt ints zwei double Variablen und caste dann für den Aufruf der ProgressBar wieder in einen int.
Mein Timer ruft ja sekündlich den Signal Handler setProgressBar() auf. Also berechne ich in der Variablen progressStep, um wieviel Prozent sich der Fortschritt nach einer Sekunde verbessert hat. Der Codeausschnitt ist dann der folgende:

Code: Alles auswählen

void Dialog::setProgressBar()
{	
	progress += progressStep;	
	progressBar->setValue(static_cast<int>(progress));
}

void Dialog::startTimer()
{
	// Check which radio button was selected
	if (radioButton_1->isChecked())
		seconds = (timeEdit->time().minute() * 60) + timeEdit->time().second();
	else if (radioButton_2->isChecked())
		seconds = 180;
	else if (radioButton_3->isChecked())
		seconds = 300;
	else if (radioButton_4->isChecked())
		seconds = 420;

	progress = 0; // current progress in percentage
	progressStep = 100.0 / seconds; // how many percent correspond to one second
	
	QTimer *timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(setProgressBar()));
	timer->start(1000);
}
Antworten