در این جلسه می خواهیم بخش های ناقص ماشین حساب را کامل کنیم ابتدا از Button qml شروع می کنیم
برای اینکه هر کلید بتواند با ماوس هم کار کند از کنترل MouseArea استفاده ميکنیم.
property alias text: textItem.text property color color: "#eceeea" property bool operator: false property bool dimmable: false property bool dimmed: false
MouseArea { id: mouse anchors.fill: parent anchors.margins: -5 onClicked: { if (operator) window.operatorPressed(parent.text) else window.digitPressed(parent.text) } }
توسط خصوصیت operator که از نوع bool است نوع کلید ورودی مشخص میشود که عددی است یا عملگر است. پس از تشخیص نوع ورودی تابعی که در فایل اصلی main.qml تعریف کردیم را فراخوانی میکنیم. Window شناسه کنترل ریشه فایل مذکور است.
حال برای نوشته روی کلیدها میخواهیم انیمیشن استفاده کنیم.
Text { id: textItem font.pixelSize: 48 wrapMode: Text.WordWrap lineHeight: 0.75 color: (dimmable && dimmed) ? Qt.darker(button.color) : button.color Behavior on color { ColorAnimation { duration: 120; easing.type: Easing.OutElastic} } states: [ State { name: "pressed" when: mouse.pressed && !dimmed PropertyChanges { target: textItem color: Qt.lighter(button.color) } } ] }
در کنترل text انیمیشن را بر روی رنگ کنترل اجرا میکنیم. استفاده از Behavior برای استفاده از قابلیت انیمیشن پیشفرض مربوط به تغییر یک خصوصیت است که در اینجا بر روی خصوصیت رنگ کار میکند.
حال نیاز به تابعی داریم که وقتی کلید فشرده میشود مقدار متغیر dimmed را بروز کند.
function updateDimmed() { dimmed = window.isButtonDisabled(button.text) }
برای اینکه با رخداد فشرده شدن کلید این تابع فراخوانی شود باید رخداد ذکر شده را یکبار به تابع بالا متصل کنیم.
Component.onCompleted: { numPad.buttonPressed.connect(updateDimmed) updateDimmed() }
وقتی از Component.onCompleted استفاده میکنیم بدنه آن فقط یکبار پس از ساخته شدن کامپوننت که در اینجا کلید است، اجرا میشود. برای اتصال دادن رخداد به تابع از connect استفاده میکنیم.
نکته قابل توجه این است که در کنترلی مثل MouseArea رخدادی مثل onPressed از قبل تعریف شده و برای استفاده آماده است اما وقتی کامپوننتی را به صورت دستی باید رخدادها را تعریف و فعال کنیم. در اینجا رخداد buttonpressed هنوز آماده استفاده نیست. برای تعریف و فعالسازی این رخداد باید به فایل NumberPad.qml رفته و در آن رخداد را فعال کنیم.
signal buttonPressed
کلمه کلیدی signal مشخص میکند این کامپوننت رخدادی به اسم buttonPressed دارد که هر جا این کامپوننت اصتفاده شود رخداد ذکر شده نیز قابل استفاده است.
حال باید فایل Display.qml را تکمیل کنیم. توابعی که در صفحه نمایش ماشین حساب کاربرد دارند به صورت زیر هستند.
function displayOperator(operator) { listView.model.append({ "operator": operator, "operand": "" }) enteringDigits = true listView.positionViewAtEnd() }
این تابع عملگر ورودی را به مدل listview اضافه میکند .
function newLine(operator, operand) { displayedOperand = displayNumber(operand) listView.model.append({ "operator": operator, "operand": displayedOperand }) enteringDigits = false listView.positionViewAtEnd() }
این تابع در یک خط عملگر و عدد را به مدل اضافه میکند.
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 listView.positionViewAtEnd() }
برای تبدیل ارقام وارد شده به عدد از این تابع استفاده میشود.
function setDigit(digit) { var i = listView.model.count - 1; listView.model.get(i).operand = digit; listView.positionViewAtEnd() }
تابع بالا برای تغییر یک رقم خاص در صفحه نمایش بکار میرود.
function clear() { displayedOperand = "" if (enteringDigits) { var i = listView.model.count - 1 if (i >= 0) listView.model.remove(i) enteringDigits = false } }
این تابع صفحه نمایش ماشین حساب را پاک میکند.
function displayNumber(num) { if (typeof(num) != "number") return errorString; var intNum = parseInt(num); var intLen = intNum.toString().length; // Do not count the minus sign as a digit var maxLen = num < 0 ? maxDigits + 1 : maxDigits; if (num.toString().length <= maxLen) { if (isFinite(num)) return num.toString(); return errorString; } // Integer part of the number is too long - try // an exponential notation if (intNum == num || intLen > maxLen - 3) { var expVal = num.toExponential(maxDigits - 6).toString(); if (expVal.length <= maxLen) return expVal; } // Try a float presentation with fixed number of digits var floatStr = parseFloat(num).toFixed(maxDigits - intLen - 1).toString(); if (floatStr.length <= maxLen) return floatStr; return errorString; }
تابع بالا برای نمایش اعداد مختلف در صفحه نمایش ماشین حساب است. اگر طول عدد بالاتر از میزان طول رشته موجود در صفحه نمایش ماشین حساب باشد آن را به صورت نماد علمی نمایش میدهد.
نکته: برای اینکه فایل calculator.js و فایلهای عکس توسط qml قابل شناسایی باشند توجه داشته باشید که حتماً باید در فایل qml.qrc آدرس دهی شوند. در غیر اینصورت نمیتوان آنها را import کرد. فایل qml.qrc فایلی با فرمت xml بوده ولی در محیط توسعه qtcreator این فایل را نمیتوان به صورت دستی ویرایش کرد و موارد گفته شده را به آن افزود. برای ویرایش آن به دایرکتوری پروژه مراجعه نمایید و توسط یک ویرایشگر متنی آن را باز کنید. محتویات آن باید به صورت زیر باشد:
main.qml NumberPad.qml Button.qml Display.qml calculator.js images/paper-grip.png images/paper-edge-right.png images/paper-edge-left.png
حال فایل main.cpp را برای اجرای ماشین حساب تغییر میدهیم.
#include#include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); app.setOrganizationName("Face It"); app.setOrganizationDomain("fitn.ir"); QQuickView view; view.connect(view.engine(), &QQmlEngine::quit, &app, &QCoreApplication::quit); new QQmlFileSelector(view.engine(), &view); view.setSource(QUrl("qrc:///main.qml")); if (view.status() == QQuickView::Error) return -1; view.setResizeMode(QQuickView::SizeRootObjectToView); view.show(); return app.exec(); }
برنامه ماشین حساب تکمیل شد. امیدوارم که استفاده کرده باشید. میتوانید کد کامل ماشین حساب را از آدرس github بنده دریافت نمایید. مجوز آن هم GPLv3 است.
آدرس گیت: https://github.com/saaie/faceit_qml_calculator
ثبت نظر