برنامه‌نویسی گرافیکی آسان با چارچوب Qt-قسمت نهم

برنامه‌نویسی گرافیکی آسان با چارچوب Qt-قسمت نهم

در جلسه قبل با جاوااسکریپت قلب ماشین حساب را نوشتیم. در این جلسه می‌خواهیم فایل 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")
    }

همانطور که در کد بالا می‌بینید تمامی کلیدهای روی ماشین حساب به یک یا چند کلید از صفحه‌کلید نگاشت شده‌اند.

امین  خزاعی

امین خزاعی

امین، برنامه نویس سیستمی و امنیت و ساکن شیراز. عاشق گنو/ لینوکس و نرم افزار آزاد. امین اعتقاد دارد همیشه باید برای توسعه نرم افزارهای آزاد و گسترش فرهنگ آزادی در نرم افزار وقت گذاشت.


0 نظر درباره‌ی این پست نوشته شده است.

ثبت نظر