how to connect function between two classes - c++

I have two different class in two files:
class Game: public QGraphicsView()
class Window: public QMainWindow()
{
public: Window();
Game *game;
public slots: void test() {game = new Game();};
}
in Window.cpp I start a new Game using test() function:
Window::Window() {test();}
now in Game.cpp I create a QMessageBox with two QPushButton
QMessageBox *box= new QMessageBox();
QPushButton *btYES = box->addButton(tr("YES"),QMessageBox::ActionRole);
QPushButton *btNO = box->addButton(tr("NO"),QMessageBox::ActionRole);
box->exec();
if (box->clickedButton() == btYES) {Window::test();}
if (box->clickedButton() == btNO) {close();}
As you can see I want to connect the function test() to btYES inside the Game.cpp but that function is inside Window.cpp and its function is to start a new game.
It is possible to do so?

QPushButton emits events when it its pressed/released
So you could connect the, lets say, released signal to a slot:
connect(button, SIGNAL(released()), windowClass, SLOT(handleButton()));
In your case you need to send it across classes, so you may need to do it in two steps.
In game:
// connect the button to a local slot
connect(btYES, SIGNAL(released()), this, SLOT(handleYesButton()));
// in the slot emit a signal - declare the signal in the header
game::handleYesButton()
{
emit userChoiceYes();
}
In window
// connect the signal in game to a your slot:
connect(game, SIGNAL(userChoiceYes()), this, SLOT(test()));
Then when btnYes is pressed/released the signal released is emitted - you pick that up in handleYesButton() and emit your own signal which your window class is connected to and handles it in test()

Based on #code_fodder answer, but you don't even need another slot, plus the basic signal for a QPushButton is clicked(). Here's the documentation :
A push button emits the signal clicked() when it is activated by the
mouse, the Spacebar or by a keyboard shortcut. Connect to this signal
to perform the button's action. Push buttons also provide less
commonly used signals, for example pressed() and released().
To start, instead of adding another slot in your class Game, just connect the button's signal clicked() to another signal :
connect(btYES, SIGNAL(clicked()), this, SIGNAL(btYesClicked()));
The signal from the class Game is now emitted when you press the button btYes. Now, you just have to connect this signal to a slot test() in your class Window :
connect(game, SIGNAL(btYesClicked()), this, SLOT(test()));

Related

check when a button is clicked event qt

I am a beginner in Qt and I would like to know, how can I create an event which checks when a button in the windows gets clicked? The window has a single push button.
I could not find a simple and correct example for my question, that's why I am asking here. I did google first.
Thank you
class MyClass : public QWidget
{
public:
MyClass ()
{
QPushButton *pButton = new QPushButton(this);
QObject::connect(pButton, &QPushButton::clicked, this, &MyClass::onButtonClicked);
}
public slots:
void onButtonClicked () {qDebug () << "Button clicked";};
};
onButtonClicked will be called if the button pressed.
Please see signals & slots and QPushButton signals for more information.
Qt employs the signals and slots paradigm. You don't check if a button is clicked. When a button is clicked, it emits a signal. You can connect your own functions to that signal. So whenever that button is clicked, the signal is emitted, and triggers all the functions it is connected to.
Be sure to check out signals and slots, which is a core concept of Qt, along with properties and meta data.
Note that as a QWidget derived, a button comes with the following methods, which are triggered by mouse events and you can override them if you wish, although in the case of something as a button that is hardly necessary:
virtual void mouseDoubleClickEvent(QMouseEvent * event)
virtual void mouseMoveEvent(QMouseEvent * event)
virtual void mousePressEvent(QMouseEvent * event)
virtual void mouseReleaseEvent(QMouseEvent * event)

C++ GUI how to use private data from one window in the second one

I have got problem in Qt. I have to make two windows:
In the first one you can click on 10 buttons and each button have to add an item(name of the button) in comboBox in the second window. But I can't refer to this comboBox. I am out of any ideas :(
I tried to make the variable protected and public, but it doesn't work. I had included window2.h to window1 and I'm trying to do something like this:
//this is in window1
void window1::on_button1_clicked() {
window2::combo->addItem("button1");
}
You can connect the button's click signals to a slot in the second window. This slot will add the information to the combobox.
To do that, you will need to distinguish the signals from each other. The best way to do this is to use a QSignalMapper.
class window1 {
Q_OBJECT
... // your other definitions...
QSignalMapper* signalMapper;
};
window1::window1 (/*your constructor's parameters*/) {
signalMapper = new QSignalMapper(this); // Will map each buttons' signals to a signal with a QString parameter.
// You can do an iteration instead of this if your buttons are on a container.
signalMapper->setMapping(button1, QString("button1"));
signalMapper->setMapping(button2, QString("button2"));
// ...
signalMapper->setMapping(button10, QString("button10"));
// Same comment as above applies here.
connect(button1, SIGNAL(clicked()),
signalMapper, SLOT(map());
connect(button2, SIGNAL(clicked()),
signalMapper, SLOT(map());
// ...
connect(button10, SIGNAL(clicked()),
signalMapper, SLOT(map());
connect(signalMapper, SIGNAL(mapped(QString)),
window2, SLOT(updateCombo(QString)));
}
class window2 {
Q_OBJECT
... // your other definitions...
public slots:
void updateCombo(QString);
};
void window2::updateCombo(QString str) {
combo->addItem(str);
}
Alternatively to the QSignalMapper approach you could name the button objects in window1 (setName("buttonXYZ")), connect the clicked signals to a slot in window2 and ask for the object name of the sender (sender()->name()).
So in the receiving slot you could do :
m_combo->addItem(sender()->name());
or
if(sender()->name() == "Button1") {
m_combo->addItem("Foo");
}

Is it possible to track if QLineEdit was clicked on?

What does the documentation say
QPushButton has a clicked() signal so one can do something like this
connect(ui->Btn,SIGNAL(clicked()),this,SLOT(DoSmth()));
QLineEdit has a textEdited() signal that allows to track the edit action.
What I am trying to achieve
I'm trying to run a function when a QLineEdit was just clicked on, not edited. Is that possible?
You can subclass QLineEdit and reimplement QWidget::focusInEvent, where you can check if the reason of the focus was mouse click. Then use this subclass instead of QLineEdit. You may create a custom signal and emit it from this event handler too to be able to use it through signal/slots.
#include <QLineEdit>
#include <QFocusEvent>
class FocusHandlerLineEdit : public QLineEdit
{
Q_OBJECT
protected:
void focusInEvent(QFocusEvent * event) {
QLineEdit::focusInEvent(event);
if(event->reason() == Qt::MouseFocusReason)
emit gotFocus();
}
signals:
void gotFocus();
};

Qt4: connect slot and signal from other forms

I have a small problem. I want run function in MainWindow from AnotherWindow. I can't set connect() for it.
Main class: MainWindow
Other form: AnotherWindow
Function in main class: setVariable(QString)
Function in other form: btnClicked()
I have now connected button signal clicked():
// In AnotherWindow.cpp
connect(ui->btnOK, SIGNAL(clicked()), this, SLOT(btnOkClicked()));
// Function in same file
void interfaceWindow::btnOkClicked() {
/* Some actions - emit signal? */
this->close();
}
btnOkClicked() are declared as private slot.
// In MainWindow.cpp
void MainWindow::setVariable(QString _var) {
this->var = _var;
}
setVariable(QString) are declared as public slot.
How I can send variable from AnotherForm (from btnOkClicked() function) to MainWindow (setVariable(QString) function) ? How and where I must send signal and make connection?
I readed about signals and slots, but my code don't work - I don't paste it here because it's terrible :)
Any help for Qt newbie?
You need to have an reference of AnotherWindow in MainWindow OR vice versa. Then you need the following things:
// AnotherWindow.h
signals:
void buttonOkClickedSignal(QString var);
// AnotherWindow.cpp
void interfaceWindow::btnOkClicked() {
emit buttonOkClickedSignal("The button got clicked!");
this->close();
}
Next step varies based on whether MainWindow has reference to AnotherWindow or vice versa. You can either:
// AnotherWindow.cpp
connect(this, SIGNAL(buttonOkClickedSignal(QString), &mainWindow, SLOT(setVariable(QString)));
or:
// MainWindow.cpp
connect(&anotherWindow, SIGNAL(buttonOkClickedSignal(QString), this, (SLOT(setVariable(QString)));
If you are invoking the slot through signal it shouldn't matter whether it's private or public (see Qt Documentation).
Hope this helps.
I'm not entirely sure I understand your question, but let me try.
You want to be able to fire a slot in another class. There are a few ways you can do that.
Declare one as a friend class to the other. Then they can see the protected and private variables/memebers
It is possible to make slots static so you can call them without a class object.
For example,
class MainWindow {
private slot:
void setVariable(QString);
}
class AnotherWindow {
friend class MainWindow;
MainWindow *window;
public:
AnotherWindow() {
connect(this, SIGNAL(fire(QString)), window, SLOT(setVariable(QString)));
}
signals:
void fire(QString);
public slots:
void onButtonClicked() {
emit fire(QString);
}
}
The previous is pseudocode so don't expect it to compile. I think this is what you want. Basically since your slot is private on MainWindow you need to make it a friend. To connect, it needs to be a member. Then when the onButtonClicked slot is evoked, then it fire()s the setVarialbe() slot.
Here is a simple code for your another window:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = 0)
{
okBtn = new QPushButton ("I am Ok!");
MyData = "";
connect(okBtn ,SIGNAL(clicked()),this,SLOT(OnOk()));
}
~MyWidget();
private:
QString MyData;
QPushButton * okBtn;
//something that modify string MyData
signals:
void MyDataSignal(QString);
//Internal slot that emits signal with proper data
private slots:
void OnOk()
{
if(MyData!="")
{
emit MyDataSignal(MyData);
}
}
};
Now in MainWindow create an object of MyWidget (suppose myWid)and connect it to slot
connect(myWid, SIGNAL(MyDataSignal(QString)),this,SLOT(OnMyWidOkClicked(QString)));
the signal will pass string to slot.
While making signals and slots keep in mind following points:
To connect a signal to a slot (or to another signal), they must have the same parameter
Parameters should be in the same order in both signal and slot.
if a signal has more parameters than the slot it is connected to, the additional parameters are simply ignored but opposite is not possible.
If you will connect a signal that have unmatched parameters to slot then no compile time error will occur but at run time command window will show a warning that signal/slot/connection does not exist.

MDI window and QSignalMapper basics

First of all my apologies for big looking question but indeed it's not. I’m reading Foundation of qt development book and while reading fourth chapter author tells the basics of MDI window by showing this example :
MdiWindow::MdiWindow( QWidget *parent ) : QMainWindow( parent ) {
setWindowTitle( tr( "MDI" ) );
QWorkspace* workspace = new QWorkspace;
setCentralWidget( workspace );
connect( workspace, SIGNAL(windowActivated(QWidget *)), this, SLOT(enableActions()));
QSignalMapper* mapper = new QSignalMapper( this );
//my problem is in this line
connect( mapper, SIGNAL(mapped(QWidget*)), workspace, SLOT(setActiveWindow(QWidget*)) );
createActions();
createMenus();
createToolbars();
statusBar()->showMessage( tr("Done") );
enableActions();
}
His this para of explanation completely eluded me (is it me or others having problem understanding it too?) :
Next, a signal mapping object called QSignalMapper is created and
connected. A signal mapper is used to tie the source of the signal to
an argument of another signal. In this example, the action of the menu
item corresponding to each window in the Window menu is tied to the
actual document window. The actions are in turn connected to mapper.
When the triggered signal is emitted by the action, the sending action
has been associated with the QWidget* of the corresponding document
window. This pointer is used as the argument in the mapped(QWidget*)
signal emitted by the signal mapping object.
My question : I still don’t get what is signal mapper class, how it’s used and what's functionality it's doing in the example above?. Can anyone please explain the above para using easy terms? also It’d be awesome if you could please teach me about mapper class’s basics with simple example? possibly in layman’s term?
P.S : A confusion is when we have MDI window, do menu changes (though actions are disabled/enabled) e.g suppose for one particular document we have menu “File/close” and for other document we have “File/remaper” ?
The QSignalMapper is used to re-emit signals with optional parameters. In other words (from the documentation):
This class collects a set of parameterless signals, and re-emits them
with integer, string or widget parameters corresponding to the object
that sent the signal.
A good example (also from the doc - take a look at it) is set as follows:
Suppose we want to create a custom widget that contains a
group of buttons (like a tool palette). One approach is to connect
each button's clicked() signal to its own custom slot; but in this
example we want to connect all the buttons to a single slot and
parameterize the slot by the button that was clicked.
So imagine you have a number of buttons encapsulated in a class, say ButtonWidget, with a custom signal void clicked(const QString &text). Here is the definition:
class ButtonWidget : public QWidget {
Q_OBJECT
public:
ButtonWidget(QStringList texts, QWidget *parent = 0);
signals:
void clicked(const QString &text);
private:
QSignalMapper *signalMapper;
};
The constructor could then be defined like the following:
ButtonWidget::ButtonWidget(QStringList texts, QWidget *parent)
: QWidget(parent)
{
signalMapper = new QSignalMapper(this);
QGridLayout *gridLayout = new QGridLayout;
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
}
connect(signalMapper, SIGNAL(mapped(const QString &)),
this, SIGNAL(clicked(const QString &)));
setLayout(gridLayout);
}
So what happens here? We construct a grid layout and our buttons of type QPushButton. The clicked() signal of each of these is connected to the signal mapper.
One of the forces using QSignalMapper is that you can pass arguments to the re-emitted signals. In our example each of the buttons should emit a different text (due to the definition of our signal), so we set this using the setMapping() method.
Now all that's left to do is map the signal mapper to the signal of our class:
connect(signalMapper, SIGNAL(mapped(const QString &)),
this, SIGNAL(clicked(const QString &)));
Assume we have a testing class called TestClass then ButtonWidget can be used thusly:
TestClass::TestClass() {
widget = new ButtonWidget(QStringList() << "Foo" << "Bar");
connect(widget, SIGNAL(clicked(const QString &)),
this, SLOT(onButtonClicked(const QString &)));
}
void TestClass::onButtonClicked(const QString &btnText) {
if (btnText == "Foo") {
// Do stuff.
}
else {
// Or something else.
}
}
By using the signal mapper this way you don't have to declare and manage all the buttons and their clicked signals, just one signal pr. ButtonWidget.
The buttom line is that the signal mapper is great for bundling multiple signals and you can even set parameters when it re-emits them. I hope that gave some intuition about the usage of QSignalMapper.
Your example code
The explanation (your "para") states that all the actions are each individually mapped to a specific QWidget*. When triggering an action its respective QWidget* will be passed to the slot QWorkspace::setActiveWindow(QWidget*) of workspace, which in turn activates the widget.
Also note that the mapping from action to widget has to happen somewhere in your code. I assume it is done in createActions() or enableActions() perhaps.
A QSignalMapper allows you to add some information to a signal, when you need it. This object internally have a map like QMap<QObject*,QVariant>. Then you connect an object to it, and when the slot is called, it re-emit the signal with the associated value.
Workflow:
mySignalMapper:
[ obj1 -> 42 ]
[ obj2 -> "obiwan" ]
[ obj3 -> myWidget ]
connect(obj1,mySignal,mySignalMapper,SLOT(map())); // idem for obj2 and obj3
(obj2 emits "mySignal")
-> (mySignalMapper::map slot is called)
-> (sender() == obj2, associated data = "obiwan")
-> (mySignalMapper emits mapped("obiwan"))
I was going to add a more detailed example, but Morten Kristensen was faster than me ;)