QT Demo Calqlatr (3) calculator.js

Source: Internet
Author: User

After analyzing main.cpp and CALQLATR.QML, the specific logical part of the calculator is how to store data, calculate results, and display it on the UI when a user taps a number or operator on the UI? This article through the analysis calculator.js to unfold in detail.

Entry function

The user has only two actions on the UI: Click the number and click Operator, the resulting action will trigger the following processing:

    function operatorpressed (operator) {calcengine.operatorpressed (operator)}    function digitpressed (digit) { calcengine.digitpressed (Digit)}

The operatorpressed (operator) and digitpressed (digit) functions are actually triggered in BUTTON.QML:

        OnClicked: {            if (operator)                window.operatorpressed (parent.text)            else                window.digitpressed ( Parent.text)        }

As to whether a button is operator is the tag that is set when the button is created in NUMBERPAD.QML:

    ...    button {text: "2"} button {text:    "3"} button {text: "    0"}    button {text: "±"; color: "#6da43d"; operator : true}    button {text: "?"; color: "#6da43d"; operator:true}    button {text: "+"; color: "#6da43d"; Operator: True}    ...

So the whole is strung together:

    • Create all the buttons in NUMBERPAD.QML and set the Operator property value of the button according to the actual need
    • When the button is clicked by the mouse, it is judged by the Operator property value to call the window.operatorpressed (parent.text) function or the window.digitpressed (parent.text) function. and passes in the text of the current button
    • The operatorpressed (operator) and digitpressed (digit) functions of window did not do any special processing, and the function of the calcengine (i.e. calculator.js) response was called directly through.
Disabled (OP) function

Open the Calculator.js file, the first function is disabled (OP), and there are calls to the function in Digitpressed (OP) and operatorpressed (OP). Let's analyze what this function does:

Function Disabled (OP) {    if (op = = "." && digits.tostring (). Search (/\./)! =-1) {        return True    } else if (op = = Window.squareroot &&  digits.tostring (). Search (/-/)! =-1) {        return True    } else {        return F Alse    }}

The above code else if part is problematic, and the correct one should be:

    } else if (op = = "√" &&  digits.tostring (). Search (/-/)! =-1) {

The reason for this is that in the previous chapter, the operator displayed in the UI (the Text field of the button) is a special character that is UTF-8 encoded, so it is also necessary to use this special character for judgment.

The specific functions of the Disabled (OP) function are:

    • If the current character is ".", and the current input already contains a "." , then it is certainly not allowed in the input character "." The
    • If the current character is "√" and the current value is a negative number (that is, the first character is "-"), then it must be allowed to perform a radical operation.
    • All others are normal and are handled separately by operatorpressed (operator) and digitpressed (digit) functions
Digitpressed (OP) function

The digitpressed (OP) function is triggered each time a number is clicked, specifically as follows:

Function digitpressed (OP) {    if (Disabled (OP))        return    if (digits.tostring (). Length >=)        return    if (lastop.tostring (). length = = 1 && ((lastop >= "0" && lastop <= "9") | | lastop = ".")) {        digits = digits + op.tostring ()        display.appenddigit (op.tostring ())    } else {        digits = op        Display.appenddigit (Op.tostring ())    }    lastop = op}

Where the Disabled (OP) call has been described in the previous section, if it is an illegal number click (multiple. or negative), it is returned directly. The next judgment is that if the input character length is greater than 14, the continuation of the input is not allowed.

One of the following if else judgments is for first-time and non-first-time input processing:

    if (lastop.tostring (). length = = 1 && ((lastop >= "0" && lastop <= "9") | | lastop = ".")) {        //non-first input, because lastop.tostring (). length = = 1        //Here The judge is whether Lastop is legal, actually meaningful, the main function is to determine if a character is a number or operator, if it is an operator, You also need to go to the Else section and re-assign digits        digits = digits + op.tostring ()        display.appenddigit (op.tostring ())    } else {        First input, because the initial length of the lastop is 0        //OP is assigned to digits, and OP is displayed on the output        digits = Op        display.appenddigit (op.tostring ())    }

However, the above judgment lacks the following validity judgement for OP (after all, a button with text "" is also laid out in the input number area):

    if (! ( (Op >= "0" && op <= "9") | | OP = = ".") )        return

Of course, after finishing digit, remember to update lastop:

    Lastop = Op

Operatorpressed (OP) function

First, you need to remove the useless parts of the code, such as the operator: "1/x", "x^2", "Abs", "Int", "MC", "m+", "Mr", "M", Window.leftarrow, "Off" and "AC". These are essentially operator-handling parts that do not exist on the UI. The code after cropping is as follows:

Function operatorpressed (OP) {if (Disabled (OP)) return Lastop = Op if (previousoperator = = "+") {D igits = number (digits.valueof ()) + number (curval.valueof ())} else if (Previousoperator = = "?") {digits = number (Curval)-Number (digits.valueof ())} else if (Previousoperator = = "x") {digits = Numbe R (Curval) * Number (digits.valueof ())} else if (previousoperator = = "÷") {digits = number (Curval)/number (digi        Ts.valueof ())} else if (Previousoperator = = "=") {} if (op = = "+" | | op = = "?" | | op = = "X" | | op = = "÷") {    Previousoperator = Op curval = digits.valueof () display.displayoperator (Previousoperator) return } if (op = = "=") {display.newline ("=", Digits.tostring ())} curval = 0 Previousoperator = "" If (OP = = "±") {digits = (digits.valueof () *-1). ToString ()} else if (op = = "√") {digits = (math.sqrt (digits.valueof ( )). ToString ()} else if (op = ="C") {Display.clear ()}} 

We split the above code and analyze it block by piece.

The first part

    if (Disabled (OP))        return    lastop = op

At the beginning of the operatorpressed (OP) function is also to judge the Disable (OP), according to the Disable (OP) function analysis, here is mainly to determine whether the negative number of the root operation.

If the operation conforms to the law, update the lastop to the current operator before processing. The modification here mainly affects the judgment of lastop in the digitpressed (OP) function, thus confirming that it is a new digital string input.

Part II

    if (Previousoperator = = "+") {        digits = number (digits.valueof ()) + number (curval.valueof ())    } else if (Previousop Erator = = "?") {        digits = number (Curval)-Number (digits.valueof ())    } else if (Previousoperator = = "X") {        digits = number (cur Val) * Number (digits.valueof ())    } else if (previousoperator = = "÷") {        digits = number (Curval)/number (Digits.valu EOf ())    } else if (Previousoperator = = ") {    }

Note that the previousoperator is determined here, that is, when the "+?x÷" is entered, the result of the previous operator is calculated only when the next operator is required. As 2+3=5, the value of 2+3 is calculated only when "=" is actually entered

Part III

    if (op = = "+" | | op = = "?" | | op = = "X" | | op = "÷") {        previousoperator = op        curval = digits.valueof ()        Displa Y.displayoperator (previousoperator)        return    }

With the analysis of the second part above, we can see that when we enter "+?x÷", we actually save op to Previousoperator, use Curval to record the digits value before entering "+?x÷", and display the operator to the interface, then return OK.

Fourth part

    if (op = = "=") {        display.newline ("=", Digits.tostring ())    }    curval = 0    previousoperator = ""

When the = sign is entered, because the result has been calculated in the second part, only the "=" operator and the result of the calculation can be displayed here. And after the calculation, you need to empty the Curval and Previousoperato (the cleanup here is necessary, the main reason is that if you do not empty, the input operator, because Curval and Previousoperato have values, The second part of the process is performed again, resulting in an error).

Fifth part

    if (op = = "±") {        digits = (digits.valueof () *-1). ToString ()    } else if (op = = "√") {        digits = (math.sqrt (digit S.valueof ())). ToString ()    } else if (op = = "C") {        display.clear ()    }

The final processing is for a few special operators, such as the "±" operator equivalent to * (-1), and "√" means to open the square calculation. The "C" operator means that the output is emptied.

Note that although there is no "AC" operator on the UI, it is important to note that the difference between the "AC" and "C" operators is:

    else if (op = = "AC") {        curval = 0        memory = 0        lastop = ""        digits = "0"    }

That is, the "C" operator simply clears the output, but the cached data is not cleared and can continue to be computed, while the "AC" operator clears all cached data and needs to start the operation.

There is a bug where the input results are emptied when no operator is entered, but once the "=" operator is entered, then "C" does not react.

Operation of Display

In Calculator.js the four functions that were called to display were:

    • Display.appenddigit (op.tostring ())
    • Display.displayoperator (Previousoperator)
    • Display.newline ("=", digits.tostring ())
    • Display.clear ()
Appenddigit (digit) function

    function appenddigit (digit)    {        if (!enteringdigits)            listView.model.append ({"Operator": "", "operand": "" })        var i = listview.model.count-1;        ListView.model.get (i). operand = ListView.model.get (i). operand + digit;        Enteringdigits = True    }

The default value of Enteringdigits is false, with two places that are false, the newline (operator, operand) function, and the clear () function, as well as two places to true. The Displayoperator (operator) function and the appenddigit (digit) function are respectively.

The judgment here means that if Enteringdigits is false then add a new line, then what is false? The default value is definitely not the case, the first input must be to add a new line. The NewLine (operator, operand) function and the clear () function need to add new lines, which are explained in detail when referring to these two functions.

The rest of the action is to add the currently entered number to its operand field, and set Enteringdigits to True (that is, the next digital input does not need to create a new line).

Displayoperator (operator) function

    function Displayoperator (operator)    {        listView.model.append ({"operator": operator, "operand": ""})        Enteringdigits = True    }

The first thing to note is that the function is called only when the "+?x÷" operator is processed in the Calculator.js file.

This function is well understood, because "+?x÷" is a binocular operator, and when these operators are entered, only the operator is displayed (on one line), and then the user is waited for the next operand to be entered. When we were making calculations on the book, we used the operator and the second operand on one line, so this place enteringdigits to true, meaning that the next digital input does not have to start again.

NewLine (operator, operand) function

    function newLine (operator, operand)    {        listView.model.append ({"operator": operator, "operand": operand})        enteringdigits = False        listview.positionviewatend ()    }

It is also important to note that the function is called when the "=" operator is processed in the Calculator.js file.

The result is calculated at the time of invocation, so there is only one line to display "=" and the result of the operation, and since this calculation process is complete, the next digital input needs to be entered in a new line, so the enteringdigits is false.

The last call to the Positionviewatend () function is to have the ListView re-layout, and its effect is to display the last few rows when the number of rows in the ListView is too long to ensure that the results are displayed correctly. In fact, this operation should be placed on every need to create a new row, that is, after ListView.model.append () is called.

Clear () function

    function Clear ()    {        if (enteringdigits) {            var i = listview.model.count-1            if (i >= 0)                Listview.mod El.remove (i)            enteringdigits = False        }    }

The code in this section only deals with the fact that when the input status is a number (that is, after entering the number consecutively and entering the "+?x÷" operator), pressing the "C" operator will erase the last item, but there are many problems with this processing. Its meaning is completely unclear, so the code written is completely illogical.

And the reference to Windows comes with the calculator, the above has "CE" and "C" two clear keys, the role of which is (from Baidu know on hangling1981 answer "C and CE on the difference between the calculator)

    • C is the function of the previous input of the number, calculation results and storage and other information to zero, the equivalent of a full word of the blackboard wiped clean, without leaving any traces.
    • The function of CE is to clear the current input data or symbols, for example: Want to calculate 14*2, accidentally input 14*3, then found the wrong. At this point, press the CE key, 3 clear, and then enter 2, you can calculate the results.
Summarize

This example is my first analysis of the QML called JS in the program, and this will be JS and QML and C + + code combination of the form is very innovative, all of a sudden GUI programming door to JS developers open. But the entire program still needs to be compiled and run, not dynamically loaded and executed (if so, is it a browser?). )

However, the above analysis also shows that the sample program is not a good product at all, and there is a big problem with both UI design and specific code logic. Once again proved that: the letter is not as good as the book, the letter code than the uncensored, their code is the real code.

QT Demo Calqlatr (3) calculator.js

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.