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:
    !http://s44.radikal.ru/i106/1202/43/c49a1f80eb2c.bmp(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!
    @#include<QApplication>
    #include<QtGui>
    #include<QLineEdit>
    #include<QVBoxLayout>

    #include "widget.h"

    int main(int argc, char argv[])
    {
    QApplication a(argc, argv);
    QVBoxLayout
    layout=new QVBoxLayout;
    QLineEditline1 = new QLineEdit();
    QLineEdit
    line2 = new QLineEdit();
    QPushButtonbtn1= new QPushButton ("+");
    QLineEdit
    output= new QLineEdit();

    layout->addWidget(line1);
    layout->addWidget(line2);
    layout->addWidget(btn1);
    layout->addWidget(output);
    
    
    
    Widget w;
    w.setLayout(layout);
    w.show();
    return a.exec(&#41;;
    

    }
    @


  • Moderators

    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.



  • 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.



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

    !http://i39.tinypic.com/208e9s3.jpg!

    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:
    @#ifndef WIDGET_H
    #define WIDGET_H

    #include <QtGui>

    class Widget : public QWidget
    {
    Q_OBJECT

     public:
    

    Widget(QWidget *parent = 0);
    ~Widget();

     public slots:
    

    void addSlot();
    void subSlot();
    void mulSlot();
    void divSlot();

     private:
    

    QLineEdit *line1, *line2;
    QLabel *output;
    QVBoxLayout *layout;
    QHBoxLayout *buttonLayout;
    QPushButton *add, *sub, *mul, *div;
    };

    #endif // WIDGET_H@

    Then, the cpp implementation of the widget:
    @#include "widget.h"

    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    layout = new QVBoxLayout;
    buttonLayout = new QHBoxLayout;
    line1 = new QLineEdit;
    line2 = new QLineEdit;
    output = new QLabel;

     add = new QPushButton("+", this);
     sub = new QPushButton("-", this);
     mul = new QPushButton("*", this);
     div = new QPushButton("/", this);
    
     layout->addWidget(line1);
     layout->addWidget(line2);
    
     buttonLayout->addWidget(add);
     buttonLayout->addWidget(sub);
     buttonLayout->addWidget(mul);
     buttonLayout->addWidget(div);
    
     layout->addLayout(buttonLayout);
     layout->addWidget(output);
    
     connect(add, SIGNAL(clicked()), this, SLOT(addSlot()));
     connect(sub, SIGNAL(clicked()), this, SLOT(subSlot()));
     connect(mul, SIGNAL(clicked()), this, SLOT(mulSlot()));
     connect(div, SIGNAL(clicked()), this, SLOT(divSlot()));
    
     setLayout(layout);
    

    }

    Widget::~Widget()
    {
    }

    void Widget::addSlot()
    {
    output->setText(QString::number(line1->text().toInt() + line2->text().toInt()));
    }

    void Widget::subSlot()
    {
    output->setText(QString::number(line1->text().toInt() - line2->text().toInt()));
    }

    void Widget::mulSlot()
    {
    output->setText(QString::number(line1->text().toInt() * line2->text().toInt()));
    }

    void Widget::divSlot()
    {
    output->setText(QString::number(line1->text().toInt() / line2->text().toInt()));
    }
    @

    And finally, the reduced to bare minimum main.cpp:
    @#include <QtGui/QApplication>
    #include "widget.h"

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

     return a.exec(&#41;;
    

    }
    @



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



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



  • [quote author="ddriver" date="1329332465"]I warned him of this but didn't implement it for a reason, let him do some of the work himself :)[/quote]
    You're completely right. You said all that yourself already. Cudo's for the nice, helpful post.



  • 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)



  • 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:
    @
    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++":http://www.voidrealms.com/tutorials.aspx?filter=cpp as well as "Qt video tutorials":http://www.voidrealms.com/tutorials.aspx?filter=qt. 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":http://cartan.cas.suffolk.edu/oopdocbook/opensource/

    Good Luck



  • [quote author="ddriver" date="1329375092"]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 [/quote]
    I think you missed part of a sentence here?

    [quote]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.[/quote]
    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 :-)



  • 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.



  • 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(
    !http://s018.radikal.ru/i515/1202/89/cf388d59c6ef.jpg(My programm)!

    Widget.cpp
    @#include "widget.h"

    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    layout=new QGridLayout;
    line=new QLineEdit;
    output = new QLabel;

    seven= new QPushButton("7",this);
    eight=new QPushButton("8",this);
    nine=new QPushButton("9",this);
    
    
    fore= new QPushButton("4",this);
    five=new QPushButton("5",this);
    six=new QPushButton("6",this);
    
    
    one= new QPushButton("1",this);
    two=new QPushButton("2",this);
    three=new QPushButton("3",this);
    minus=new QPushButton("-",this);
    
    
    zero= new QPushButton("0",this);
    
    plus=new QPushButton("+",this);
    ravno=new QPushButton("=",this);
    
    
    
    
    
    layout->addWidget(line,0,0,1,5);
    
    
    
    
    layout->addWidget(seven,2,0);
    layout->addWidget(eight,2,1);
    layout->addWidget(nine,2,2);
    
    
    layout->addWidget(fore,3,0);
    layout->addWidget(five,3,1);
    layout->addWidget(six,3,2);
    
    
    layout->addWidget(one,4,0);
    layout->addWidget(two,4,1);
    layout->addWidget(three,4,2);
    layout->addWidget(minus,4,3);
    
    
    layout->addWidget(zero,5,0);
    
    layout->addWidget(plus,5,1);
    layout->addWidget(ravno,5,2);
    layout->addWidget(output,6,0);
    
    
    
    
    
    
    
    
    setLayout(layout);
    

    connect(seven, SIGNAL(clicked()), this, SLOT(sevenSlot()));
    connect(eight, SIGNAL(clicked()), this, SLOT(eightSlot()));
    connect(nine, SIGNAL(clicked()), this, SLOT(nineSlot()));

    connect(fore, SIGNAL(clicked()), this, SLOT(foreSlot()));
    connect(five, SIGNAL(clicked()), this, SLOT(fiveSlot()));
    connect(six, SIGNAL(clicked()), this, SLOT(sixSlot()));
    connect(one, SIGNAL(clicked()), this, SLOT(oneSlot()));
    connect(two, SIGNAL(clicked()), this, SLOT(twoSlot()));
    connect(three, SIGNAL(clicked()), this, SLOT(threeSlot()));
    connect(zero, SIGNAL(clicked()), this, SLOT(zeroSlot()));

    connect(plus, SIGNAL(clicked()),this,SLOT(addSlot()));

    }

    Widget::~Widget()
    {

    }
    void Widget::sevenSlot()
    {
    line->setText(line->text()+"7");

    }

    void Widget::eightSlot()
    {
    line->setText(line->text()+"8");

    }

    void Widget::nineSlot()
    {
    line->setText(line->text()+"9");
    }

    void Widget::foreSlot()
    {
    line->setText(line->text()+"4");
    }

    void Widget::fiveSlot()
    {
    line->setText(line->text()+"5");
    }

    void Widget::sixSlot()
    {
    line->setText(line->text()+"6");
    }

    void Widget::oneSlot()
    {
    line->setText(line->text()+"1");
    }

    void Widget::twoSlot()
    {
    line->setText(line->text()+"2");
    }

    void Widget::threeSlot()
    {
    line->setText(line->text()+"3");
    }
    void Widget::zeroSlot()
    {
    line->setText(line->text()+"0");
    }

    void Widget::addSlot()
    {
    output->setText(QString::number(line->text().toInt() + line->text().toInt()));

    }
    @

    Widget.h
    @#ifndef WIDGET_H
    #define WIDGET_H

    #include <QtGui>

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    Widget(QWidget *parent = 0);
    ~Widget();
    public slots:
    void sevenSlot();
    void eightSlot();
    void nineSlot();

    void foreSlot();
    void fiveSlot();
    void sixSlot();

    void oneSlot();
    void twoSlot();
    void threeSlot();
    void zeroSlot();

    void addSlot();

    private:

    QGridLayout *layout;
    QLineEdit *line;
    QPushButton *seven, *eight, *nine, *fore, *five, *six,  *one, *two, *three, *minus, *zero,*plus,*ravno;
    QLabel *output;
    

    };

    #endif // WIDGET_H
    @

    main.cpp
    @#include <QtGui/QApplication>
    #include "widget.h"

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

    return a.exec&#40;&#41;;
    

    }
    @



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



  • 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!


  • Moderators

    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.



  • 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.