I have two windows: mainwindow.ui and dialog.ui. In the mainwindow.cpp I initialise some objects on the heap of another class for Ethernet-communication and use functions of these objects to read date from the bus and show the values in the mainwindow.ui. In dialog.ui I would like to set the values on the bus, but the problem is to access the communication-functions and objects in mainwindow.cpp.
I wanted to define dialog.cpp as friend class, but I make something wrong. Here is some code:
mainwindow.h
class MainWindow : public QMainWindow
{protected: DateReg *myPosReg;...}
mainwindow.cpp
...
myPosReg = new DateReg(DateValue->AddReg());
...
myPosReg->GetValue(a,b,c);
myPosReg->setValue(a,b,c);
...
Can I somehow access setValue() function in dialog.cpp? Should I allways use dialog.cpp for the dialog.ui or there is some possibility work with dialog.ui-date in mainwindow.cpp? To set the values in dialog.ui I use QDoubleSpinBox.
In the mainwindow.ui I call dialog.ui.
Excuse me for my English.
As far as I understand, you have two classes: MainWindow and Dialog. As MainWindow::myPosReg is protected, you can only access it in Dialog, if Dialog derives from MainWindow or if it is a friend.
The following design should work:
class MainWindow : public QMainWindow
{
[...]
protected:
DateReg *myPosReg;
friend class Dialog;
};
class Dialog
{
[...]
MainWindow* myMainWindow;
void someFunction()
{
myMainWindow->myPosReg->setValue([...]);
}
};
As an alternative, I would suggest a more Qt-ish way by using signals and slots. When the spin-boxes in Dialog change, emit a signal to which MainWindow listens.
We start with the dialog:
class Dialog : public QDialog
{
[...]
Dialog()
{
[...init ui...]
connect(ui->spinBoxA, SIGNAL(valueChanged(int)),
this, SLOT(onSpinBoxValueChanged()));
connect(ui->spinBoxB, SIGNAL(valueChanged(int)),
this, SLOT(onSpinBoxValueChanged()));
connect(ui->spinBoxC, SIGNAL(valueChanged(int)),
this, SLOT(onSpinBoxValueChanged()));
}
signals:
void valuesChanged(int a, int b, int c);
private slots:
void onSpinBoxValueChanged()
{
emit valuesChanged(ui->spinBoxA->value(), ui->spinBoxB->value(),
ui->spinBoxC->value());
}
};
So the dialog has an internal slot onSpinBoxValueChanged(), which is called when
one of the spinboxes changes its value. The sole purpose of this slot is to emit
another signal valuesChanged to which we'll connect the main window (i.e. the
dialog's internal slot combines three values into one signal).
The main window could be the following:
class MainWindow : public QMainWindow
{
[...]
DateReg *myPosReg;
public slots:
void setValues(int a, int b, int c)
{
myPosReg->setValues(a, b, c);
}
};
And the code, which connects both
int main()
{
[...]
MainWindow* mainWindow = new MainWindow;
Dialog* dialog = new Dialog;
connect(dialog, SIGNAL(valuesChanged(int,int,int)),
mainWindow, SLOT(setValues(int,int,int)));
}
When the user changes the value in a spinbox, the following chain-reaction happens:
QSpinBox::valueChanged(int) -> Dialog::onSpinBoxValueChanged()
-> Dialog::valuesChanged() -> MainWindow::setValues() -> DateReg::setValues()
The advantage is that you decouple MainWindow and Dialog: Dialog just signals that the values have changed but does not care what happens with them and MainWindow changes its myPosReg but does not care, where the values are coming from.
Related
If i click on one dialog button on the other dialog will show some text, it doesnt have to be text basicly connection between two dialogs. Something that will help me about my problem.
If you have two QWidget (or inherited) objects represented as dialogs, then you should use an QObject::connect method. Learn about signals and slots in Qt. It looks like:
class DialogA : public QWidget {
Q_OBJECT
...
public slots:
void ShowSomeText(); // called when receive a signal
...
};
class DialogB : public QWidget {
Q_OBJECT
...
void SendTextSignal(); // sends a signal
...
};
// somwhere in code
DialogA da;
DialogB db;
connect(db, SIGNAL(SendTextSignal()), da, SLOT(ShowSomeText()));
I want to connect a QDoubleSpinBox with a QSlider like this:
QObject::connect(ui->myDoubleSpinBox, SIGNAL(valueChanged(double)),
ui->mySlider, SLOT(setValue(double)));
QObject::connect(ui->mySlider, SIGNAL(valueChanged(double)),
ui->myDoubleSpinBox, SLOT(setValue(double)));
This won't work, for a QSlider only handles int values. So I think i need to add a custom slot to QSlider.
I thought about creating a new class derived from QSlider and then implementing the slot, like this:
QDoubleSlider.hpp
#ifndef QDOUBLESLIDER_H
#define QDOUBLESLIDER_H
#include <QSlider>
class QDoubleSlider : public QSlider
{
Q_OBJECT
public:
explicit QDoubleSlider(QObject *parent = 0);
signals:
public slots:
void setValue(double givenValue);
};
#endif // QDOUBLESLIDER_H
QDoubleSlider.cpp
#include "qdoubleslider.h"
QDoubleSlider::QDoubleSlider(QObject *parent) :
QSlider(parent)
{
}
void QDoubleSlider::setValue(double givenValue)
{
// code
}
Now I have two problems:
The compiler complains about an invalid conversion from QObject* to QWidget* in the constructor.
I don't know how setValue works and thus I don't even know how to implement that slot.
Any ideas?
parent needs to be a QWidget*, just as the error states
Slots work like regular member functions. You should probably store an exact double as a member and set the underlying slider to the appropriate integer equivalent. Remember to only send valueChanged signals if the value really changes.
Furthermore you should probably inherit from QWidget instead and have a QSlider as a child, as you do not want users of your class to change the integer range of your internal slider.
just simply replace your QObject to QWidget, because QSlider constructor is
QSlider ( QWidget * parent = 0 )
you'd better have a new slot named setDoubleValue(double givenValue) and connect to this slot. in this slot, it is simple. like
void QDoubleSlider::setDoubleValue(double givenValue)
{
setValue(static_cast<int>(givenValue));
}
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.
I'm trying to change text of a class Label from another class. I have class MainWindow, which contains Label.
I also have a Bot class from which I wanna change the value of label.
I'm trying to create signal and slots but I have no idea where to start.
I created signal and slots like so:
//in mainwindow.h
signals:
void changeTextSignal();
private slots:
void changeText();
//in mainwindow.cpp
void MainWindow::changeText(){
this->label->setText("FooBar");
}
But I have no idea how to connect a signal to be able to change Label's text from another class.
Read up on Qt signal-slot mechanism. If I understand you correctly, you are trying to signal from Bot to MainWindow that the Label text needs to change. Here's how you do it...
//bot.h
class Bot
{
Q_OBJECT;
//other stuff here
signals:
void textChanged(QString);
public:
void someFunctionThatChangesText(const QString& newtext)
{
emit textChanged(newtext);
}
}
//mainwindow.cpp
MainWindow::MainWindow
{
//do other stuff
this->label = new QLabel("Original Text");
mybot = new Bot; //mybot is a Bot* member of MainWindow in this example
connect(mybot, SIGNAL(textChanged(QString)), this->label, SLOT(setText(QString)));
}
void MainWindow::hello()
{
mybot->someFunctionThatChangesText("Hello World!");
}
Here's a simple code that creates a button and assigns a onclick handler:
auto btn = new QPushButton("CLICK ME");
connect(btn, SIGNAL(clicked()), this, SLOT(btn_Click()));
private slots:
void btn_Click() {
alert("clicked!");
}
It works as it should if called in the main window class. However when I try to do this in a child window, clicking the button does nothing. The child window is shown like this:
auto settingsWindow = new SettingsWindow();
settingsWindow->show();
I guess it's somehow connected with the receiver object which is now a different window. But how can I make it work?
In order to be able to declare signals/slots in your own class you should include Q_OBJECT directive in your class:
class SettingsWindow {
Q_OBJECT
...
};
You should add a MACRO in class SettingsWindow to enable singal receiving.
Add "Q_OBJECT" like the following.
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget();
....