در جلسه قبل با جاوااسکریپت قلب ماشین حساب را نوشتیم. در این جلسه میخواهیم فایل main.qml را کامل کنیم. این فایل، فایل اصلی طراحی گرافیکی ما است که برنامه ما در شروع، این فایل را فراخوانی میکند. پس باید بقیه فایلهای qml از اینجا فراخوانی شوند. البته نیازی به import کردن آنها نیست و تنها در صورتی که در دایرکتوری اصلی پروژه نباشند باید دایرکتوری آنها را import کرد.
ماشین حساب دارای صفحهکلید و صفحه نمایش است پس باید NumberPad که قبلاً آن را ایجاد کردهایم و همچنین Display که آن را نیز قبلاً ایجاد کردهایم باید در فایل اصلی مورد استفاده قرار دهیم.
Item{ id: pad width: 180 NumberPad { id: numPad; y: 10; anchors.horizontalCenter: parent.horizontalCenter } }
در کنترل آیتم آن را مورد استفاده قرار میدهیم و عرض آیتم را محدود به ۱۸۰ میکنیم و در نتیجه NumberPad نمیتواند عرضی بیش از ۱۸۰ داشته باشد. Anchors.horizantalCenter مکان قرار گیری آن در محور افقی تعیین میکند که در اینجا تعیین شده در وسط محور افقی کنترل پدر قرار گیرد.
Display { id: display x: -16 width: window.width - pad.width height: parent.height }
سپس زیر مجموعه کنترل Rectangle کنترل Display را قرار میدهیم. اگر به عرض و ارتفاع آن نگاه کنید میبینید که بر اساس عرض و ارتفاع کنترلهای دیگر عرض و ارتفاع diplay تنظیم شده است. با این کار با تغییر اندازه ماشین حساب متناسب با آن اندازه display نیز تغییر میکند.
حال برای اینکه با ماوس بتوان محل قرارگیری display را از چپ به راست برد (با دراگ و دراپ) باید از کنترل MouseArea در این کنترل استفاده کرد. همچنین برای اینکه تغییر مکان diplay و دکمههای ماشین حساب با انیمیشن همراه باشد باید از کنترل AnimationController استفاده کنیم.
AnimationController {
id: controller
animation: ParallelAnimation {
id: anim
NumberAnimation { target: display; property: "x"; duration: 400; from: -16; to: window.width - display.width; easing.type: Easing.InOutQuad }
NumberAnimation { target: pad; property: "x"; duration: 400; from: window.width - pad.width; to: 0; easing.type: Easing.InOutQuad }
SequentialAnimation {
NumberAnimation { target: pad; property: "scale"; duration: 200; from: 1; to: 0.97; easing.type: Easing.InOutQuad }
NumberAnimation { target: pad; property: "scale"; duration: 200; from: 0.97; to: 1; easing.type: Easing.InOutQuad }
}
}
}
کنترل بالا زیر مجموعه کتابخانه QtQuick است و در ساختارش یک تایمر وجود دارد که بر اساس آن زمان انجام انیمیشن تعیین میشود. همچنین یک خصوصیت به نام progress دارد که مقدار آن بین 0 تا 1 قابل تغییر است و مقدار آن به صورت real یا اعشاری میتواند باشد. خصوصیت animation این کنترل شامل دو قسمت میباشد که یکی همزمان انیمیشن برای زیر مجموعههای خود اجرا میکند و دیگری به صورت سری آنها را اجرا ميکند. Target کنترلی که باید انیمیشن روی آن اجرا شود است و property خصوصیتی از کنترل مقصد است که باید در حین انیمیشن تغییر کند.
MouseArea { property real startX: 0 property real oldP: 0 property bool rewind: false height: 50 anchors { bottom: parent.bottom left: parent.left right: parent.right } onPositionChanged: { var reverse = startX > window.width / 2 var mx = mapToItem(window, mouse.x).x var p = Math.abs((mx - startX) / (window.width - display.width)) if (p < oldP) rewind = reverse ? false : true else rewind = reverse ? true : false controller.progress = reverse ? 1 - p : p oldP = p } onPressed: startX = mapToItem(window, mouse.x).x onReleased: { if (rewind) controller.completeToBeginning() else controller.completeToEnd() } }
نکته قابل توجه این است که MouseArea باید در کنترل Display تعریف شود. همانطور که در کد بالا میبینید startX مقدار اولیه x مربوط به display میباشد، oldP مقدار progress قبلی انیمیشن است و rewind یک مقدار منطقی برای تعیین اجرای انیمیشن از ابتدا تا انتها یا از انتها تا ابتدا است. زیرا اگر display سمت راست باشد باید انیمیشن از آخر به اول اجرا شود. mapToItem تابعی است که کنترلی را میگیرد و مقدار x و y داده شده که نسبت به صفحه است به نسبت به کنترل گرفته شده بازمیگرداند.
نکته قابل توجهی که وجود دارد این است که وقتی اندازه ماشین حساب تغییر میکند باید خصوصیتهای انیمیشن نیز متناسب با تغییر کنند. برای این منظور باید تابع reload کنترل انیمیشن فراخوانی شود.
onWidthChanged: controller.reload()
onHeightChanged: controller.reload()
چند تابع را با جاوااسکریپت میسازیم که توابع موجود در فایل قلب ماشین حساب را فراخوانی میکنند.
function operatorPressed(operator) { CalcEngine.operatorPressed(operator) numPad.buttonPressed() } function digitPressed(digit) { CalcEngine.digitPressed(digit) numPad.buttonPressed() } function isButtonDisabled(op) { return CalcEngine.disabled(op) }
حال باید کاری کنیم که اگر کاربر به جای ماوس با کیبرد کار کرد نیز ماشین حساب کار کند. برای این کار باید از رخداد onpressed کنترل Keys استفاده کنیم.
Keys.onPressed: { if (event.key == Qt.Key_0) digitPressed("0") else if (event.key == Qt.Key_1) digitPressed("1") else if (event.key == Qt.Key_2) digitPressed("2") else if (event.key == Qt.Key_3) digitPressed("3") else if (event.key == Qt.Key_4) digitPressed("4") else if (event.key == Qt.Key_5) digitPressed("5") else if (event.key == Qt.Key_6) digitPressed("6") else if (event.key == Qt.Key_7) digitPressed("7") else if (event.key == Qt.Key_8) digitPressed("8") else if (event.key == Qt.Key_9) digitPressed("9") else if (event.key == Qt.Key_Plus) operatorPressed("+") else if (event.key == Qt.Key_Minus) operatorPressed("−") else if (event.key == Qt.Key_Asterisk) operatorPressed("×") else if (event.key == Qt.Key_Slash) operatorPressed("÷") else if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) operatorPressed("=") else if (event.key == Qt.Key_Comma || event.key == Qt.Key_Period) digitPressed(".") else if (event.key == Qt.Key_Backspace) operatorPressed("backspace") }
همانطور که در کد بالا میبینید تمامی کلیدهای روی ماشین حساب به یک یا چند کلید از صفحهکلید نگاشت شدهاند.
ثبت نظر