PDA

View Full Version : Signal and Slot - New Qt user



sml
16th January 2014, 14:22
Greetings to everyone,

I'm new to Qt programming and have one question on simple function.
I have mainWindows with lineEdit and pushButton. Clicked on push button open new theDialog. theDialog contain three lineEdit, which on first two entered number and third is sum of previous two number. On pushButton I want to write this result in lineEdit on mainWindow. There is no error, but I couldn't get result.

Here is code:

mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private slots:
void on_pushButton_clicked();
void textValue(const QString& arg);

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "thedialog.h"
#include <QDebug>
#include <iostream>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

theDialog *thedialog = new theDialog;
QObject::connect(thedialog, SIGNAL(textEdited(QString)), this, SLOT(textValue(QString)));

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_pushButton_clicked()
{
theDialog thedialog;
thedialog.setModal(true);
thedialog.exec();
}

void MainWindow::textValue(const QString &arg)
{
ui->lineEdit->setText(arg);
qDebug()<<"Message from textValue Function";
}

thedialog.h


#ifndef THEDIALOG_H
#define THEDIALOG_H

#include <QDialog>

namespace Ui {
class theDialog;
}

class theDialog : public QDialog
{
Q_OBJECT

public:
explicit theDialog(QWidget *parent = 0);
~theDialog();

signals:
void textEdited(const QString& arg);

public slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();

public:
Ui::theDialog *ui;
};

#endif // THEDIALOG_H


thedialog.cpp


#include "thedialog.h"
#include "ui_thedialog.h"
#include <QDebug>

theDialog::theDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::theDialog)
{
ui->setupUi(this);
}

theDialog::~theDialog()
{
delete ui;
}

void theDialog::on_pushButton_clicked()
{

double lineEdit = ui->lineEdit->text().toDouble();
double lineEdit_2 = ui->lineEdit_2->text().toDouble();
double result = lineEdit + lineEdit_2;
ui->lineEdit_3->setText(QString::number(result));

}


void theDialog::on_pushButton_2_clicked()
{

emit textEdited(ui->lineEdit_3->text());
qDebug()<<"Sent Message";
theDialog::close();
}


main.cpp


#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

Thanks in advance.

anda_skoa
16th January 2014, 16:24
You connect the dialog's signal before you call exec()



theDialog thedialog;

connect(&thedialog, SIGNAL(textEdited(QString)), this, SLOT(textValue(QString)));

thedialog.exec();


Alternatively connect the second dialog button to the dialog's accept() slot and add a getter



QString theDialog::resultText() const
{
return ui->lineEdit_3;
}

and call that after the dialog has finished


theDialog thedialog;
thediailog.exec();
textValue(thedialog.resultText());


Cheers,
_

d_stranz
16th January 2014, 16:43
This code in the MainWindow constructor is meaningless.


theDialog *thedialog = new theDialog;
QObject::connect(thedialog, SIGNAL(textEdited(QString)), this, SLOT(textValue(QString)));

You create an instance of "theDialog", connect it to a slot in your MainWindow class, then it goes out of scope. That instance has absolutely no relationship to the instance of theDialog that you create (on the stack) in your push button slot handler:


void MainWindow:on_pushButton_clicked()
{
theDialog thedialog; // NOT the same as "thedialog" in the constructor
thedialog.setModal(true);
thedialog.exec();
}


So the dialog that you are posting in your push button handler has no relationship to the dialog you create in the constructor (and whose signal you connect to the slot in the MainWindow). The signals from dialog you create in the push button handler aren't connected to anything.

Please learn how to use "[CODE]" tags when posting source code here. This is not the same as using "[QUOTE]" tags, as you did in your original post. Click the "Go Advanced" button when posting to see the expanded list of editing tools, and click the "#" button to insert a pair of "[CODE]" tags.

sml
17th January 2014, 12:33
Solved. Thanks for your advice.

mainwindow.cpp


void MainWindow::on_pushButton_clicked()
{
theDialog *thedialog = new theDialog(this);
thedialog->setModal(true);
QObject::connect(thedialog, SIGNAL(textEdited(QString)), this, SLOT(textValue(QString)));
thedialog->exec();
}

anda_skoa
17th January 2014, 13:02
You don't need to setModal(true), exec() does that internally.

And you might want to delete the dialog, either explicitly after exec() or by setting the WA_DeleteOnClose widget attribute.

Cheers,
_

sml
28th January 2014, 15:46
Greetings,

I have one more question.
In dialog i entered some parameter for calculation and send on mainwindow. When I want to change some parameter and click on pushbutton on mainwindow i get empty dialog and need to enter again all parameter.
How can I save parameter from previous dialog?

Best regards.

anda_skoa
28th January 2014, 18:06
You add a method to the dialog that allows you to set the values.
Then you call that after creating the dialog and before calling exec() on it

Cheers,
_

sml
3rd February 2014, 14:21
Thanks anda_skoa, that's helps.

I have one more question. Let say on mainwindow there is three pushbutton (pushbutton1, pushbutton2, pushbutton3), when is clicked on push button open new dialog where you can enter parameter.
One pushbutton (pushbutton1) is main and other two pushbutton (pushbutton2, pushbutton3) is function. (Lets say on pushbutton each side have connection point)
Is there posability for user to draw line on mainwindow from pushbutton1 to pushbutton2 or pushbutton3 to pass data and do calculation? (Not to change GUI).

(For example: Like in electronic you connect more resistance: parallel, etc...)

d_stranz
3rd February 2014, 21:18
One pushbutton (pushbutton1) is main and other two pushbutton (pushbutton2, pushbutton3) is function. (Lets say on pushbutton each side have connection point)
Is there posability for user to draw line on mainwindow from pushbutton1 to pushbutton2 or pushbutton3 to pass data and do calculation? (Not to change GUI).

I am not sure what you mean here by "draw line". Do you mean that when the user closes the dialog created by pushbutton1, the functions performed by clicking pushbuttons2 and 3 will automatically be executed? That's easy:



void MainWindow::on_pushButton1_clicked()
{
theDialog thedialog;
connect( &thedialog, SIGNAL(textEdited(QString)), this, SLOT(textValue(QString)));
if ( QDialog::OK == thedialog.exec() )
{
QString text = getTheTextValue(); // you have to write these three methods
doPushButton2Function( text );
doPushButton3Function( text );
}
}

Or do you really mean "draw a line": | Button1 | -------------------------> | Button2 | --------------------------> | Button3 | on your screen?

sml
3rd February 2014, 22:24
^
Yes, I mean draw a line and that line pass parameter from dialog on pushbutton1 to dialog on pushbutton2 or pushbutton3. ( |Button1| -----> |Button2| or |Button1| -----> |Button3| )


For example: You have to enter parameter 'a', 'b', 'c', 'd', etc to dialog on pushbutton1. After that on mainwindow you have two more pushbutton, one have some function 'a+b+c' and other 'a*b*c'. With that "line" you connect your pushbutton1 with data to function pushbutton2 or pushbutton3.

d_stranz
4th February 2014, 17:45
Drawing a line does not cause code to execute. If the user types parameters into the dialog and clicks OK, then get those parameters from the dialog and save them in variables in the program. If the user wants to add a+b+c, then they simply click pushbutton2. What is the point of drawing a line between two pushbuttons?

Are you really trying to create a graphical programming application like LabView? If you are, then you are confusing the graphical picture of the program (the icons that represent processing steps and the lines that show flow of execution) with the code that gets executed when the program runs. The picture is not the program.

sml
5th February 2014, 10:38
Let's say is similar like LabView (but much simplier).
For example i want to make GUI for calculate electric circuit. You add one by one resistor and after that you connect one by one. Every resistor have own resistance (you click on resistor and add number in Ohm). Any idea?

PS: example about pushbutton was idea for trasfer data from one dialog to another, who is connected with line.

anda_skoa
5th February 2014, 11:07
Have a look at QGraphicsView

Cheers,
_

d_stranz
5th February 2014, 23:57
For example i want to make GUI for calculate electric circuit. You add one by one resistor and after that you connect one by one. Every resistor have own resistance (you click on resistor and add number in Ohm). Any idea?

This is a much, much more difficult problem than you realize.

First - You need to design a data structure that will represent your resistor network. There is no Qt class that can do this for you, so you need to use a "directed graph" or some similar data structure. Here is a good example. (http://badboys.7p.com/notes/Graph%20-%20Linked%20Implementation%20%28C++%29.htm) Be careful - your resistor network is not a "directed acyclic graph". Whenever you have two or more resistors in parallel, this forms a "cycle" (or circle) in the graph. The algorithms for traveling through cyclic vs. acyclic graphs are different.

The vertexes (nodes) in this graph will be your resistors. Each resistor node will have a value, its resistance in Ohms. A junction where two wires come together or one wire splits into two can be represented as a resistor with 0 Ohms resistance.

The edges in the graph represent the wires that connect:


the voltage source to the resistor network
one resistor to another resistor (including a junction 0 Ohm "resistor")
the resistor network to the voltage sink (ground)


The value associated with each edge is the total resistance computed up to that point for the network.

Second - You need to write a computation class that takes as input the network data structure. This computation class follows the network from one end to the other. At each node, it combines the resistance computed from the previous node with the resistance for the new node (using the rules for combining serial and parallel resistance) and then passes that to the next. So the starting resistance at the voltage source is 0, and the ending resistance at the voltage sink is what is computed by the computation class.

Note that up until this point, what I have described is completely independent of anything you see on the screen. It is just plain, old C++.

Third - You need to write a graphics generator that will also take the network data structure as an input. This graphics generator maps the nodes and edges into graphics objects that will appear on the screen. As anda_skoa said, QGraphicsView (part of Qt's Graphics / View architecture) would be an excellent choice for this.

Finally - the really hard part: You need to write a graphics editor that will allow the user to interactively create and edit the network. As the user changes things in the picture, you need to update the network data structure so it matches the picture on the screen.

My guess is that this little project is at least a month's worth of work if you are working at it full time.

sml
6th February 2014, 09:54
Thanks anda_skoa and d_stranz on advice.