February 15, 2012

Asus_G72GX Asus_G72GX
Lab Rat
4 posts

Simple 2 integer number calculator

 

Good evening everybody!

I have started to learn Qt nearly for 2 weeks, and I want to build the simple 2 numbers integer calculator.
My aim is to get those interface:
interface
I started to create my project (new project-Qt widget-Qt gui app-only desktop-with out ui checkbox[This means that I work with out any qml design, I adding my widget elements manually])
I’v already write the code for my interface: (main.cpp) But I have no idea what to do next, I mean I do not know how to add sum function in header file and where I should assign signal for my plus button. Maybe someone could help me and say me what should I read first. Thanks a lot for your replies!

  1. #include<QApplication>
  2. #include<QtGui>
  3. #include<QLineEdit>
  4. #include<QVBoxLayout>
  5.  
  6. #include "widget.h"
  7.  
  8. int main(int argc, char *argv[])
  9. {
  10.     QApplication a(argc, argv);
  11.     QVBoxLayout*layout=new QVBoxLayout;
  12.     QLineEdit*line1 = new QLineEdit();
  13.     QLineEdit*line2 = new QLineEdit();
  14.     QPushButton*btn1=  new QPushButton ("+");
  15.     QLineEdit*output= new QLineEdit();
  16.  
  17.     layout->addWidget(line1);
  18.     layout->addWidget(line2);
  19.     layout->addWidget(btn1);
  20.     layout->addWidget(output);
  21.  
  22.  
  23.  
  24.     Widget w;
  25.     w.setLayout(layout);
  26.     w.show();
  27.     return a.exec();
  28. }

15 replies

February 15, 2012

mlong mlong
Robot Herder
1551 posts

You should move the definition and instantiation of layout, line1, line2, btn1, and output into the Widget class itself, rathern than in main(). Then define a doAddition() slot in Widget. Then, after you have instantiated all of the components, you can connect the btn1->clicked() signal to your doAddition() slot.

Encapsulating all of the components into one widget will make life much easier for you.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

February 15, 2012

Deleted Member # 269f Deleted Member # 269f
Lab Rat
251 posts

Do you have previous C++ experience or are you new to c++ as well as Qt? From the approach you used it seems you are not that familiar with the object oriented programing paradigm.

As mlong said – you need to subclass most of your code, you only need the first and the last 4 lines in your main(). Declare the pointers in the class body, allocate with “new” inside the constructor, that is the place to make the connections for the GUI elements and the widget custom slots as well.

February 15, 2012

Deleted Member # 269f Deleted Member # 269f
Lab Rat
251 posts

I slightly enhanced your assignment by adding + – * and / operations and a horizontal layout to hold the 4 buttons inside the vertical layout.

Typically, using line edits for ints is not that good idea since you have to do plenty of conversion from string to int to string, but nevertheless here is what you should basically aim for:

I didn’t bother adding comments, so if you have questions feel free to ask.
Also note this application is far from perfect, you can input text instead of numbers, and if you divide by text you divide by zero (you can fix that by checking before you divide in the divSlot() implementation) which will crash the program. And since I used ints there are also rounding errors :)

First, the widget.h:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QtGui>
  5.  
  6. class Widget : public QWidget
  7. {
  8.  Q_OBJECT
  9.  
  10.      public:
  11.  Widget(QWidget *parent = 0);
  12.  ~Widget();
  13.  
  14.      public slots:
  15.  void addSlot();
  16.  void subSlot();
  17.  void mulSlot();
  18.  void divSlot();
  19.  
  20.      private:
  21.  QLineEdit *line1, *line2;
  22.  QLabel *output;
  23.  QVBoxLayout *layout;
  24.  QHBoxLayout *buttonLayout;
  25.  QPushButton *add, *sub, *mul, *div;
  26. };
  27.  
  28. #endif // WIDGET_H

Then, the cpp implementation of the widget:

  1. #include "widget.h"
  2.  
  3. Widget::Widget(QWidget *parent)
  4.      : QWidget(parent)
  5. {
  6.      layout = new QVBoxLayout;
  7.      buttonLayout = new QHBoxLayout;
  8.      line1 = new QLineEdit;
  9.      line2 = new QLineEdit;
  10.      output = new QLabel;
  11.  
  12.      add = new QPushButton("+", this);
  13.      sub = new QPushButton("-", this);
  14.      mul = new QPushButton("*", this);
  15.      div = new QPushButton("/", this);
  16.  
  17.      layout->addWidget(line1);
  18.      layout->addWidget(line2);
  19.  
  20.      buttonLayout->addWidget(add);
  21.      buttonLayout->addWidget(sub);
  22.      buttonLayout->addWidget(mul);
  23.      buttonLayout->addWidget(div);
  24.  
  25.      layout->addLayout(buttonLayout);
  26.      layout->addWidget(output);
  27.  
  28.      connect(add, SIGNAL(clicked()), this, SLOT(addSlot()));
  29.      connect(sub, SIGNAL(clicked()), this, SLOT(subSlot()));
  30.      connect(mul, SIGNAL(clicked()), this, SLOT(mulSlot()));
  31.      connect(div, SIGNAL(clicked()), this, SLOT(divSlot()));
  32.  
  33.      setLayout(layout);
  34. }
  35.  
  36. Widget::~Widget()
  37. {
  38. }
  39.  
  40. void Widget::addSlot()
  41. {
  42.      output->setText(QString::number(line1->text().toInt() + line2->text().toInt()));
  43. }
  44.  
  45. void Widget::subSlot()
  46. {
  47.      output->setText(QString::number(line1->text().toInt() - line2->text().toInt()));
  48. }
  49.  
  50. void Widget::mulSlot()
  51. {
  52.      output->setText(QString::number(line1->text().toInt() * line2->text().toInt()));
  53. }
  54.  
  55. void Widget::divSlot()
  56. {
  57.      output->setText(QString::number(line1->text().toInt() / line2->text().toInt()));
  58. }

And finally, the reduced to bare minimum main.cpp:

  1. #include <QtGui/QApplication>
  2. #include "widget.h"
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.      QApplication a(argc, argv);
  7.      Widget w;
  8.      w.show();
  9.      
  10.      return a.exec();
  11. }

February 15, 2012

Andre Andre
Robot Herder
6399 posts

Nice. Now, enter the numbers 1 and 0 (or “abc”), and press the / button. Boom! :-)

February 15, 2012

Deleted Member # 269f Deleted Member # 269f
Lab Rat
251 posts

I warned him of this but didn’t implement it for a reason, let him do some of the work himself :)

February 15, 2012

Andre Andre
Robot Herder
6399 posts

ddriver wrote:
I warned him of this but didn’t implement it for a reason, let him do some of the work himself :)

You’re completely right. You said all that yourself already. Cudo’s for the nice, helpful post.

February 16, 2012

Asus_G72GX Asus_G72GX
Lab Rat
4 posts

Great thanks for mlong and Andre, especially for ddriver!
ddriver
Can you say why we need to create the elements of our programm in widget.cpp but not in main.cpp? Qt gived me errors if I replace my 3rd QLineEdit for Qlabel (maybe this is the reason, that we need to write it in the widget.cpp?) And why it is not compulsory to write our libraries in widget.cpp (#include<Qlabel>, #include<QLineEdit>, and etc.)? And the last question is why we need to leave the main.cpp with out any changes? Thanks again!
P.S.
I have not so wide knowledge in c++. We had studied the c++ as our first programming language for 4 months. So maybe it is not good idea that our university programm starts from qt after c++. I mean we did not practiced at c++ enough time (we had only 2 hours of lab’s per week)

February 16, 2012

Deleted Member # 269f Deleted Member # 269f
Lab Rat
251 posts

The reason to subclass into widget.h and widget.cpp is because once you do it, you can use the same widget in multiple locations and multiple projects. Once you subclass it, it becomes a reusable and encapsulated object, which is the whole idea of object oriented programming.

The reason I chose QLabel for the result is because the result doesn’t require user input, it is just text. The reason you get an error is probably because you assign either the wrong object or to the wrong pointer. In my solution the pointer I create in the header is a QLabel pointer, which is later assigned to a new QLabel. In the case of your solution, you crate the pointer and assign it to a new object on the same line, so the line should be:

  1. QLabel *output = new QLabel;

I have included <QtGui> in widget.h, and QtGui contains all GUI elements, QLineEdit, QLabel, QPushButton are all contained in <QtGui> which is sort of a master header, and since widget.h is included in widget.cpp, technically QtQui is also included there as well.

Once you subclass your widget you can do changes to your program without even touching main.cpp and your main function. Your main.cpp has only one goal – to create and show an instance of your widget, but what the widget contains must be entirely contained within the widget files in order to promote encapsulation and code reusability.

All this is stuff you should basically know, this is common C++ stuff that applies everywhere not just Qt. You definitely need to improve you C++ skills before you dive into Qt or any other serious C++ framework. There is a ton of C++ as well as Qt learning resources out there, for example you can go to http://www.voidrealms.com where a good man has done a series of C++ [voidrealms.com] as well as Qt video tutorials [voidrealms.com]. While not in depth, he explains well enough for newbies and you could deffinitely make use of his tutorials.

There is also an excellent and FREE book on Qt available for reading online, a book that will teach you BOTH C++ AND Qt at the same time, and here it is: Introduction to Design Patterns in C++ with Qt4 [cartan.cas.suffolk.edu]

Good Luck

February 16, 2012

Andre Andre
Robot Herder
6399 posts

ddriver wrote:
The reason I chose QLabel for the result is because the result doesn’t require user input, it is just text. The reason you get an error is probably because you assign

I think you missed part of a sentence here?

I have included <QtGui> in widget.h, and QtGui contains all GUI elements, QLineEdit, QLabel, QPushButton are all contained in <QtGui> which is sort of a master header, and since widget.h is included in widget.cpp, technically QtQui is also included there as well.

I think that it is good to note, that this is not considdered good practice. It is fine for quick prototyping, but please don’t do this in production environments. It makes compilation slower than needed.

Otherwise, good post again :-)

February 16, 2012

Deleted Member # 269f Deleted Member # 269f
Lab Rat
251 posts

Sorry, my mind just shifts from one point to another and I accidentally forgot to finish my thought. Fixed it.

Yes you are right on including <QtGui> being slower than including just the components I need, but since my system is very powerful and this is a tiny program I ignore such compile time penalties. Best practice would encourage to include only the bare minimum needed.

February 18, 2012

Asus_G72GX Asus_G72GX
Lab Rat
4 posts

Good Evening!

What can you advise if I have the same project (QtGui, creating with out form[*ui]), but in that case I need to create one qlineedit and the number keyboard. I have started to programm my calculator but I collide with some problems. I realized that it is impossible to store more than one integer number in one Qline. Because when user cliks the number button and then the next button, first number must store somewhere in order to procede the addSlot command. As you can see I’v tried to do this, but when i press plus number my answer just doubles. And what is also main, the answer must appear at qline but I was not able to do this, so I just created the QLabel. Please can you explain how can I make addition of two and more numbers in one Qline. I guess that I need to use for and if statements here….
P.S.
Sorry for disturbing all of you again(
My programm

Widget.cpp

  1. #include "widget.h"
  2.  
  3. Widget::Widget(QWidget *parent)
  4.     : QWidget(parent)
  5. {
  6.     layout=new QGridLayout;
  7.     line=new QLineEdit;
  8.     output = new QLabel;
  9.  
  10.     seven= new QPushButton("7",this);
  11.     eight=new QPushButton("8",this);
  12.     nine=new QPushButton("9",this);
  13.  
  14.  
  15.     fore= new QPushButton("4",this);
  16.     five=new QPushButton("5",this);
  17.     six=new QPushButton("6",this);
  18.  
  19.  
  20.     one= new QPushButton("1",this);
  21.     two=new QPushButton("2",this);
  22.     three=new QPushButton("3",this);
  23.     minus=new QPushButton("-",this);
  24.  
  25.  
  26.     zero= new QPushButton("0",this);
  27.  
  28.     plus=new QPushButton("+",this);
  29.     ravno=new QPushButton("=",this);
  30.  
  31.  
  32.  
  33.  
  34.  
  35.     layout->addWidget(line,0,0,1,5);
  36.  
  37.  
  38.  
  39.  
  40.     layout->addWidget(seven,2,0);
  41.     layout->addWidget(eight,2,1);
  42.     layout->addWidget(nine,2,2);
  43.  
  44.  
  45.     layout->addWidget(fore,3,0);
  46.     layout->addWidget(five,3,1);
  47.     layout->addWidget(six,3,2);
  48.  
  49.  
  50.     layout->addWidget(one,4,0);
  51.     layout->addWidget(two,4,1);
  52.     layout->addWidget(three,4,2);
  53.     layout->addWidget(minus,4,3);
  54.  
  55.  
  56.     layout->addWidget(zero,5,0);
  57.  
  58.     layout->addWidget(plus,5,1);
  59.     layout->addWidget(ravno,5,2);
  60.     layout->addWidget(output,6,0);
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.     setLayout(layout);
  70. connect(seven, SIGNAL(clicked()), this, SLOT(sevenSlot()));
  71. connect(eight, SIGNAL(clicked()), this, SLOT(eightSlot()));
  72. connect(nine, SIGNAL(clicked()), this, SLOT(nineSlot()));
  73.  
  74. connect(fore, SIGNAL(clicked()), this, SLOT(foreSlot()));
  75. connect(five, SIGNAL(clicked()), this, SLOT(fiveSlot()));
  76. connect(six, SIGNAL(clicked()), this, SLOT(sixSlot()));
  77. connect(one, SIGNAL(clicked()), this, SLOT(oneSlot()));
  78. connect(two, SIGNAL(clicked()), this, SLOT(twoSlot()));
  79. connect(three, SIGNAL(clicked()), this, SLOT(threeSlot()));
  80. connect(zero, SIGNAL(clicked()), this, SLOT(zeroSlot()));
  81.  
  82. connect(plus, SIGNAL(clicked()),this,SLOT(addSlot()));
  83.  
  84.  
  85.  
  86.  
  87.  
  88. }
  89.  
  90. Widget::~Widget()
  91. {
  92.  
  93. }
  94. void Widget::sevenSlot()
  95. {
  96.     line->setText(line->text()+"7");
  97.  
  98. }
  99.  
  100. void Widget::eightSlot()
  101. {
  102.     line->setText(line->text()+"8");
  103.  
  104. }
  105.  
  106. void Widget::nineSlot()
  107. {
  108.     line->setText(line->text()+"9");
  109. }
  110.  
  111.  
  112. void Widget::foreSlot()
  113. {
  114.     line->setText(line->text()+"4");
  115. }
  116.  
  117.  
  118. void Widget::fiveSlot()
  119. {
  120.     line->setText(line->text()+"5");
  121. }
  122.  
  123.  
  124. void Widget::sixSlot()
  125. {
  126.     line->setText(line->text()+"6");
  127. }
  128.  
  129.  
  130. void Widget::oneSlot()
  131. {
  132.     line->setText(line->text()+"1");
  133. }
  134.  
  135. void Widget::twoSlot()
  136. {
  137.     line->setText(line->text()+"2");
  138. }
  139.  
  140. void Widget::threeSlot()
  141. {
  142.     line->setText(line->text()+"3");
  143. }
  144. void Widget::zeroSlot()
  145. {
  146.     line->setText(line->text()+"0");
  147. }
  148.  
  149.  
  150.  
  151. void Widget::addSlot()
  152. {
  153.     output->setText(QString::number(line->text().toInt() + line->text().toInt()));
  154.  
  155. }

Widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QtGui>
  5.  
  6. class Widget : public QWidget
  7. {
  8.     Q_OBJECT
  9.  
  10. public:
  11.     Widget(QWidget *parent = 0);
  12.     ~Widget();
  13. public slots:
  14. void sevenSlot();
  15. void eightSlot();
  16. void nineSlot();
  17.  
  18. void foreSlot();
  19. void fiveSlot();
  20. void sixSlot();
  21.  
  22. void oneSlot();
  23. void twoSlot();
  24. void threeSlot();
  25. void zeroSlot();
  26.  
  27.  
  28. void addSlot();
  29.  
  30.  
  31. private:
  32.  
  33.  
  34.     QGridLayout *layout;
  35.     QLineEdit *line;
  36.     QPushButton *seven, *eight, *nine, *fore, *five, *six,  *one, *two, *three, *minus, *zero,*plus,*ravno;
  37.     QLabel *output;
  38.  
  39. };
  40.  
  41. #endif // WIDGET_H

main.cpp

  1. #include <QtGui/QApplication>
  2. #include "widget.h"
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication a(argc, argv);
  7.     Widget w;
  8.     w.show();
  9.  
  10.     return a.exec();
  11. }

February 19, 2012

Andre Andre
Robot Herder
6399 posts

Did you take a look at the Calculator example that comes with Qt? It seems to be exactly what you are after…

February 24, 2012

Asus_G72GX Asus_G72GX
Lab Rat
4 posts

Andre

Yes I know about it, anyway thanks! But those code are quit difficult and complicated to understand. Could you have any idea about how to fix my code. I just need that may calculator could add numbers, I will make other functionallity (multiply, minus and etc.) by my own based on your example. I just do not know how to make that qlineedit could store the first entered number in the memory and then clear the space for 2nd number and so on. I hope on your help! Thanks!

February 24, 2012

mlong mlong
Robot Herder
1551 posts

The QLineEdit should not be the thing that is permanently storing your values. You should have an independent variable whose job it is to retain that value. You should type your value into the line edit, then upon some other action (like hitting the + button) your code can retrieve the value from the line edit, store it in your variable, then clear the line edit to prepare it for the next number.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

February 24, 2012

steno steno
Ant Farmer
239 posts

You just need to know when to parse the first and second numbers based off of the users input. So, how do you know when the user is done entering the first number? How do you know when the user is done entering the second number? Answer those questions and then use QString::number to get the first and second number from the line edit.

 
  ‹‹ QDateTime and Time Zones      List is expanding and hiding everything else!! ››

You must log in to post a reply. Not a member yet? Register here!