Qt: How to track Release or Change event for Phonon::SeekSlider? - qt

I'm using Phonon::SeekSlider, it's a cool thing and I don't need to bother about synchronization between slider and MediaObject but now I need to track the moment when user releases the slider after moving it or when it's value is changed or when the current time of MediaObject is changed. I cannot find any public signals, I can see them in the slider's code but they are private. How could I inherit/implement/track whatever to track this event?
Thanks

You can create a class inherits SeekSlider
in the .h file :
#include <Phonon/SeekSlider>
using namespace Phonon;
class MySeekSlider : public SeekSlider
{
Q_OBJECT
public:
MySeekSlider(QWidget *parent = 0);
signals:
void release(qint64 pos);
protected:
virtual void mouseReleaseEvent(QMouseEvent *);
};
and in the.cpp
void MySeekSlider::mouseReleaseEvent(QMouseEvent *)
{
emit release(this->pos());
}
or use the tick signal of your MediaObject
void tick ( qint64 time )

You may connect to private signals same way as to any others.
QStaticMetaObject ignores visibility level of signals|slots. The only difference of private signals from normal (which has protected visibility level) - you cannot emit them when subclassing your Phonon::SeekSlider.

I suppose there is no way to do it but to create a new class inherited from QSlider, and add the whole functionality about MediaObject inside.

Related

Display actual time in a Qt program

What is a simple way to display the actual time (Hh: mm: ss) in MainWindow's title ?
Using slots and signals technology.
I'm building my answer on the one provided by Riateche. Instead of using a user defined QTimer and connecting signals/slots, you can use the provided timerEvent() of any QObject. It will basically do the same under the hood, but save you a lot of typing. This would look like this:
class MainWindow : public QMainWindow
{
public:
MainWindow();
protected:
void timerEvent(QTimerEvent *event);
};
MainWindow::MainWindow()
{
startTimer(1000); // 1-second timer
}
void MainWindow::timerEvent(QTimerEvent * event)
{
setWindowTitle(QTime::currentTime().toString("hh:mm:ss"));
}
Create a QTimer with 1 sec interval (or e.g. 100 msec for more accuracy), connect its timeout signal to your slot. In the slot get the current time using QTime::currentTime() static function, convert it to string using toString and assign it to a GUI element (e.g. a label).

Get rid of god object of QMainWindow

I am making an application with three libraries ITK VTK and Qt. Since I want all functionality in the event loop and connection of signals and slots so I defined all functionality under QMainWindow definition. Now mainwindow object became bulky and I tried to make different classes for different functionality but then all things messing in main.cpp Idea of modularization is missing. Can you suggest how should be structure of a program?
I rarely have anything more in main.cpp than creating and showing my QMainWindow, then calling app.exec().
If your QMainWindow starts to become bulky, then it means you should probably organize this code into different coherent classes (instead of moving it to main.cpp). The basic idea is to change a code that looks like this:
class MainWindow : public QMainWindow
{
public:
void doSomething();
void foo1();
void foo2();
void foo3();
void bar1();
void bar2();
void bar3();
private:
// ...
}
To a code that looks like this:
class Foo:
{
public:
void doSomething1();
void doSomething2();
void doSomething3();
private:
// ...
}
class Bar:
{
public:
void doSomething1();
void doSomething2();
void doSomething3();
private:
// ...
}
class MainWindow : public QMainWindow
{
public:
void doSomething();
private:
Foo foo_;
Bar * bar_;
// ...
}
How do you choose the classes Foo and Bar and which members of MainWindow you transfer to these new classes depends of course of your context. But the idea is to organize your code smartly so that each class have a "responsibility", and then MainWindow can delegate each work to the class that is responsible for this work. Like in a house, there are electricians for managing electricity, plumbers for managing water, etc... and the responsibility of the house keeper is only to call the appropriate guys to do the appropriate job. In your case, you probably want a class to perform any work related to ITK, and a class to perform any work related to VTK, then if they become bulky also, subdivide these classes.

What is the right way to suppress Qt signals when values are explicitely set

I got a from QWidget derived class that holds three QSpinBoxes (e.g. coordinates). The valueChanged() signal is connected and is emitted in at least these three cases:
up/down button
manually entered number
setValue()
However, when using setValue(), I want to suppress the signal(s), since I don't want to have (three) signals. In my understanding, there are two ways to handle this:
QObject::blockSignals()
using a flag that indicates whether the values were explicitely set
Both variants work, but I think they are not straight-forward at all: For the first one, I generally block all signals AND I need to set blockSignals(true) for all underyling widgets (blockSignals doesn't block children QObjects in my application). For the second one, I need to query the flag in every update method AND the signals are raised although I don't need them.
Are there any general designing patterns that prevent such behavior? If not, what variant would you prefer?
The third option would be to subclass QSpinBox, implement desired functionality there, and used derived class instead of QSpinBox - this hides all associated complexity in derived class and allows you use it just like QSpinBox.
For example, following class
myQSpinBox.h
#ifndef MYQSPINBOX_H
#define MYQSPINBOX_H
#include <QSpinBox>
class myQSpinBox : public QSpinBox
{
Q_OBJECT
public:
myQSpinBox(QWidget * parent = 0 );
protected:
bool valueBeingSet;
public slots:
void setValue (int val);
private slots:
void On_valueChanged(int val);
signals:
void valueChangedNotBySet(int val);
};
#endif // MYQSPINBOX_H
myQSpinBox.cpp
#include "myQSpinBox.h"
myQSpinBox::myQSpinBox(QWidget * parent)
: QSpinBox(parent)
, valueBeingSet(false)
{
connect(this,SIGNAL(valueChanged(int)),this,SLOT(On_valueChanged(int)));
}
void myQSpinBox::setValue ( int val )
{
valueBeingSet = true;
QSpinBox::setValue(val);
valueBeingSet = false;
}
void myQSpinBox::On_valueChanged(int val)
{
if(!valueBeingSet)
emit valueChangedNotBySet(val);
}
will emit valueChangedNotBySet(int); in cases 1. and 2., but not in case 3., keeping all QSpinBox functionality intact

Need to know UP/DOWN arrow button is clicked while implementing QDateTimeEdit in Qt?

Need to know UP/DOWN arrow button is clicked while implementing QDateTimeEdit in Qt?
I want to catch which button UP/DOWN clicked while changing the time.
Please tell me the function which catches this signal.
Please reply me fast.
That is quite simple.
To catch that you must create your own class inherited from QDateTimeEdit and reimplement
stepBy(int steps) function.
So, your class will looks like:
class MyDateTime : public QDateTimeEdit
{
Q_OBJECT
public:
MyDateTime(QWidget *parent = 0);
public slots:
void stepBy(int steps);
};
And implementation of void stepBy(int steps):
void MyDateTime::stepBy(int steps)
{
// here you can do your own business
if (steps!=0)
qDebug( steps > 0
? "going up"
: "going down" );
// we must call it to provide QDateTimeEdit's
// functionality
QDateTimeEdit::stepBy(steps);
}
Good luck!

QT EventTransition implementation

I am trying to build an QT State Maschine. I have some States, and for those States i need Transition that alter the Graphics on my gui.
The Problem i having and the only reason i am asking, i am Stuck and Point 1.
The compiler cant identifie the QTEventTransition. I have QT 4.6 wroking with QT Creator on Windows.
The compiler does not find Header #include < QtEventTransition >
This is what i did i never did this bevor but i think it should be correct, I have A Header File where i have my Transitions Declareted like this:
class validateBoatTransition : public QtEventTransition
{
public:
validateBoatTransition(Widget *widget,ServerSkeleton* server);
protected:
bool eventTest(QEvent *e);
void onTransition(QEvent *);
private:
Chart* ourChart;
Message current;
BarelySocket* myBarelySocket;
};
Than i have my Cpp File where i have this:
validateBoatTransition::validateBoatTransition(Widget *widget,ServerSkeleton* server)
{
}
void validateBoatTransition::onTransition(QEvent *e)
{
/*
My Logik should go here
*/
}
What i want is that if the Transition is activated by an Button (clicked) it should fire this transition!
I searched the net, but cant find an solution. Can i do that? I should i think.
Yours Thomas
Maybe you should take a look to signals/slot mechanism. I think this is what you need to achieve what you want.
Make your onTransition function a slot instead of an event handler and connect it to the signal clicked of the button.
class validateBoatTransition : public QtEventTransition
{
...
public slots:
void onTransition();
...
}
Somewhere in your code, connect the button to the slot:
QObject::connect(myButton, signal(clicked()), myValidateBoatTransition, slot(onTransition());
Each time the button will be clicked the execution will go through the onTransition function.
I think you're trying to use wrong classes/mechanisms to achieve your goals. If I understand you correctly, you have some GUI and after clicking some button you want to validate some stuff and if this validation is successful the state machine should change it's state. I'd write it this way:
Create some class to handle validation:
class BoatValidator : public QObject
{
Q_OBJECT
// boring stuff like constructor, etc.
public slots:
void validate()
{
if ( /*your validation logic goes here*/ ) {
emit boatTransition();
}
}
signals:
void boatTransition(); // emitted if validation is succesful
};
Then you connect your QPushButton::clicked() to BoatValidator::validate() and use BoatValidator::boatTransition() signal to drive the state machine:
QStateMachine machine;
QState *state1 = new QState(&machine);
QState *state2 = new QState(&machine);
// more state machine setup
// connect validator and button
QPushButton button;
BoatValidator validator;
connect(&button, SIGNAL(clicked()), &validator, SLOT(validate()));
// use validator to change states
state1->addTransition(&validator, SIGNAL(boatTransition()), state2);
Generally I'd use signal to drive state machine, unless some transitions are obviously event driven (for example some QEvent::Enter/QEvent::Leave on GUI widgets, etc.).
What i wanted to do is build a Qt State Machine. The Problem was that i could not trigger my own Transitions (let alone with my own Events). The answers given are good but would lead to a messy code. Why should i use a QT State Machine if i could not use the QT Transitions?
The First Problem above is solved, if you create a new Project. QT Creater is very annoying.
But here now my solution , may it help others.
First my State:
class ServerState : public QState
{
Q_OBJECT
public:
ServerState(QPushButton * pushButton);
~ServerState();
public slots:
void buttonWasClicked();
protected:
void onEntry(QEvent *e);
void onExit(QEvent *e);
private:
QPushButton * pushButton;
};
Normal, but you see i added an Slot. This slot enables me to connect a bottom signal or a Widget Mouse Press Signal to it !
Like this:
QStateMachine *machine = new QStateMachine(this);
ServerState *s1 = new ServerState(connectButton);
connect(connectButton, SIGNAL(clicked()), s1, SLOT(buttonWasClicked()));
machine->addState(s1);
s1->addTransition(connectTransition);
all i needed to to is now fire a declared Event like this one :
#define RegisterToServerEventIndex User+5
class ConnectToServerEvent : public QEvent
{
public:
ConnectToServerEvent() : QEvent(QEvent::Type(QEvent::ConnectToServerEventIndex))
{}
};
when the slot was called:
void ServerState::buttonWasClicked()
{
this->machine()->postEvent(new ConnectToServerEvent());
qDebug("ServerState::buttonWasClicked");
}
The QT State Machine would now call all the Transitions , link with this state:
ConnectToServerTransition::ConnectToServerTransition(QPushButton * pushButtonB,ServerSkeleton* serverSkeleton)
{
this->pushButtonB = pushButtonB;
this->pushButtonB->hide();
this->serverSkeleton = serverSkeleton;
qDebug("ConnectToServerTransition::ConnectToServerTransition");
}
bool ConnectToServerTransition::eventTest(QEvent *e)
{
return (e->type() == QEvent::ConnectToServerEventIndex);
}
void ConnectToServerTransition::onTransition(QEvent *e)
{
if (true == this->serverSkeleton->initalisieren())
{
this->pushButtonB->show();
}else{
qDebug("Conection to Server faild");
}
emit kill();
return;
}
Whats so great that i dare to post?
Well first you can link a Qt SM to a widget where a mouse press event , or somthing else, is called and process the raw data to a an level you need later in your program. All you then need to do is, to emit the singal:
void Widget::mousePressEvent(QMouseEvent *event){
Coordinates current;
current.line = 0;
current.row = A;
current.row = (Row) (event->x() / 30); // 30 = breite von einen Feld
current.line = event->y() / 30; // 30 = länge von einen Feld
emit this->clicked(current);
return;
}
Then this enhenced information (current) is passed to the slot at my state, where i chose to call the correct transition that does the work. You could link more transitions to it, if you need it.
But most importend you dont need to reprogramm the Transition, a think i realy disliked.
Thank you for your help , i could not done it alone.

Resources