السبت، 23 أكتوبر، 2010

برنامج قاموس لهواتف Symbian

السلام عليكم ورحمه الله...
اليوم تم اطلاق النسخه الأول من برنامج قاموس لنظام Symbian التي تعمل عليها معظم هواتف Nokia. طبعا المشروع مفتوح المصدر وهو نتيجه ثمره تعاون بيني وبين أخي محمد هويدي حيث أنه هو من أسس المشروع وقام بعمل نسخه Linux ثم سمح لي مشكورا بالدخول معه في المشروع، واليوم نحن نقوم باطلاق النسختين التاليتين وهما تخصا نظامي Symbian  و Windows.

المشروع مفتوح المصدر وله صفحه على موقع Google Code

تنزيل البرنامج على هواتف Symbian



ما هي الهواتف التي يمكنها تشغيل البرنامج
البرنامج يعتمد على Qt وبالتالي يجب أن يعمل الهاتف على نظام Symbian S60 3rd Edition FP1 او ما يليه أو نظام S60 5th Edition. حسنا كيف لي ان اعرف ما هو نظام هاتفي؟ اذهب الى موقع نوكيا وتأكد من النظام بنفسك.


هناك نسختان للتتحميل الأول بدون Nokia Smart Installer والثانيه معه. يمكنك استخدام أحدى الطريقتين.





الطريقه الأولى:
وهي الطريقه التي ينصح باستعمالها وهي تحميل نسخه القاموس التي تحمل معها Nokia Smart Installer. الهدف من هذا البرنامج انه لكي تعمل برامج Qt فانه يجب توافر مكتبات Qt على الهاتف، وهذا البرنامج يقوم بالتأكد من وجودها فان لم يجدها سوف يقوم بتحميلها من الانترنت، لذلك فانك تحتاج الى اتصال بالشبكه حتى تتمكن من تنصيب القاموس بشكل صحيح، أما اذا كان هاتفك يحتوي على مكتبات Qt فانه سيقوم بتصيب البرنامج مباشره. مكتبه Qt يتم تنزيلها مره واحده فقط على الهاتف ثم تستخدمها كل التطبيقات دون الحاجه لاعاده تنزيلها من جديد في كل مره.

الطريقه الثانيه:
لا ينصح باستخدامها وهي تخص المستخدمين المتقدمين ومن لا يريد دفع مبلغ طائل لتحميل مكتبه Qt. اذا كان هاتفك لا يحتوي على Qt فقم بتنزيل المكتبه من هنا ثم قم بنقلها الى هاتفك وتنصيبها بعدها قم بتحميل نسخه القاموس التي لا تحتوي على Nokia Smart Installer من هنا

تنزيل البرنامج على Windows
قم بتحميل النسخه المخصصه ل Windows ثم قم بفك ضغطها وابدأ العمل   

أرجوا ممن يستطيع المساعده في أحد هذه النقاط ان لا يتردد
1. تجريب البرنامج وطلاعنا على أي أخطاء أو مميزات تودونها، هنا أو على صفحه البرنامج في Google Code
2. قاعده البيانات المتوفره فقيره وبها بعض الأخطاء، من يملك قاعده بيانات أفضل يكون من حقنا استخدامها أن يطلعنا عليها.
2. القاموس يحتوي على قاعده للترجمه من الانجليزيه الى العربيه ونحتاج الى قاعده بيانات اخرى للترجمه من العربيه الى الانجليزيه.
4. نحتاج الى مصمم يساعدنا في تصميم icon للبرنامج, ويا حبذا لو أن أحد المصممين يقترح علينا تصميم بسيط فيمكننا عمل ( CSS ( Cascade Style sheet للبرنامج مثل مواقع الويب, هذا التصميم سيضاف لنسخه الهاتف فقط لانها لا تبدو جميله بعكس نسخه Linux و Windows
5. من يملك جهاز يعمل على نظام MeeGo أو Maemo ويستطيع مساعدتنا في تجربه البرنامج، للأسف أنا لم أقم بتجهيزها لهذا النظام ولكن ان وجد من يستطيع تجربتها على جهازه فيمكنني المحاوله.

في انتظار أرائكم ومقترحاتكم..

الجمعة، 22 أكتوبر، 2010

ماذا أحتاج لكي أبدأ البرمجة باستخدام Qt

حسنا لقد تأخرت في اكمال مواضيع Qt بما فيه الكفايه اليوم سأعود لها ان شاء الله وستكون أول مهمه هي تحديث المقال السابق الذي كان يحمل نفس العنوان حيث أن معلوماته أصبحت قديمه للأسف. الأمور تسير مع Qt بسرعه فائقه.


الأدوات التي أحتاجها
1. Nokia Ovi Suite : فائده البرنامج هذا هو نقل التطبيقات وتنزيلها على هاتفك ال Symbian بعد الانتهاء من برمجتها.
2. Nokia Qt SDK : وهي بيئه تطوير متكامله لتطوير برامج Qt ل Symbian وباقي المنصات، ما يميز هذه البيئه سهولتها عن الأمور المعقده التي كنا نستخدمها سابقا لتجهيز بيئه التطوير كما أنها تحتوي على كل ما تحتاجه من الأف الى الياء.

تجهيز الهاتف
بعد أن قمت بتنزيل Nokia Qt SDK الأن يجب تجهيز الهاتف لكي يستقبل برامج Qt كالتالي:
1. يجب تنصيب Qt Runtime على الهاتف

2. تنصيب برنامج ال TRK لتمكين الهاتف من عمل On Device Debugging كالتالي:
ولكن توجد أكثر من نسخه كيف يمكنني معرفه النسخه التي تلائم الهاتف, فمثلا على هاتف Nokia N97 يمكنك التوجه الى موقع نوكيا وفحص مواصفات الجهاز وعندها ستشاهد التالي:
طبعا واضح ان الهاتف يعمل على نظام S60 5th Edition وبالتالي يجب أخذ النسخه المناسبه لهذا النظام.

الان أنت جاهز لعمل تطبيقات Qt لهواتف Symbian.

الأحد، 10 أكتوبر، 2010

نوكيا تقوم بعقد دوره تدريبيه ل Qt في الأردن و لبنان

سوف تقوم شركه نوكيا بعقد دوره تدريبيه عن Qt في كل من الأردن ولبنان, مده الدوره يومان سوف يتم تعريف المشتركين بالأمور الأساسيه في Qt. لا تحتاج الى معرفه مسبقه بها، بل الى معرفه في لغه C++ فقط.

المواضيع التي سيتم تناولها في الدوره

الوم الأول
Time: 9:00 - 17:00

Welcome and Forum Nokia Intro
Intro to Forum Nokia Services
Lowering the barriers to publishers
Marketing your apps
Developers meet Businesses

Qt Overview and Introduction
What is Qt? Why use Qt?
Qt Status, Qt in Mobile Devices
Changes in Qt 4.7
Qt and the Nokia N8 Device

Qt Essentials
Qt Modules
Tools and Build Chain

First Qt Application
Qt Projects
QObject
Parent/Child Relationship
Basic QWidgets
Layout managers

Nokia Qt SDK
Working with Qt Projects in Mobile Platforms
Multi-Platform Development with Nokia Qt SDK

Meta-Object System
Meta-Objects
Signals and Slots

Creating Simple UIs with Nokia Qt SDK
Qt Creator and Form Designer
Using Generated UI code
QActions
Existing Dialog Classes

Event Handling Basics
Events in Qt
Timers



اليوم الثاني
Time: 9:00 - 17:00

Custom Widgets – Painting System
Paint Events
QPainter and QPaintDevices
Overview on QGraphicsView

Creating Outstanding User Interfaces
Animations Framework and Effects
Graphics View and Custom UI
Qt Gesture Framework and Multi-touch UI in N8

Porting Mobile Applications to Qt
Comparing Android and Qt Based Development
Comparing iPhone and Qt Based Development
Approaches When Code Re-Use Is Not Possible
Re-Using Native Platform Code
Approaches on Wrapping Symbian Services

New Qt APIs – Qt Mobility APIs
Overview on Qt Mobility APIs
API Walkthrough
Contacts, Location, Messaging, Multimedia, Sensors

للتسجيل من الأردن
للتسجيل من لبنان

السبت، 31 يوليو، 2010

التحريك

مقدمة
في هذا الدرس سوف نتعرف على أسس التحريك وهي نفس الأسس التي تعتمد عليها جميع الألعاب حتى ألعاب الحاسوب تعتمد على طرق مشابهة للمبادئ المطروحة في هذا الدرس.
ملاحظة قبل المتابعة
هذا الدرس يعتمد بشكل كلي على ال Multi-Threading في جافا لذلك يجب عليك الاحاطه في هذا الموضوع. يمكنك الاطلاع على هذا الدرس الممتاز في منتيدات الفريق العربي.


public class AnimationCanvas extends Canvas implements Runnable {

    protected void showNotify() {
        Random r = new Random( System.currentTimeMillis() );
        x = r.nextInt( getWidth() );
        y = r.nextInt( getHeight() );
        dirX = 4;
        dirY = 4;

    }

    protected void paint(Graphics g) {
        g.setColor( 0x0 );
        g.fillRect( 0, 0, getWidth(), getHeight() );

        g.setColor( 0xFFFFFF );
        g.fillRect( x, y, WIDTH, HEIGHT );

    }

    public void run() {
        while( !quit ) {
            x += dirX;
            y += dirY;

            if( x <= 0 || x + WIDTH >= getWidth() ) {
                dirX *= -1;

            }

            if( y <= 0 || y + HEIGHT >= getHeight() ) {
                dirY *= -1;
                
            }
            repaint();
            serviceRepaints();

            try {
                Thread.sleep( 50 );

            } catch( Exception ex ) {
                ex.printStackTrace();

            }

        }

    }

    public void start() {
        Thread t = new Thread( this );
        t.start();

    }

    public void stop() {
        quit = true;

    }
    private boolean quit = false;
    private int x;
    private int y;

    private int dirX;
    private int dirY;
    private final int WIDTH = 10;
    private final int HEIGHT = 10;
}

في السطور ما بين 3 و 9 قمنا بأخذ قيمه عشوائيه لكل من الاحداثيات السينية والصادية. الاحداثايات السينية محصورة ما بين 0 و عرض شاشه الهاتف أما الاحداثيات الصادية فهي محصورة ما بين 0 و ارتفاع الشاشة. ثم قمنا بتجهيز متجهات الحركة على المحورين بقيم ابتدائية تساوي 4 لكل منهما.


لاحظ أن الفئة تقوم بعمل implements لل Runnable أي أنها يمكن أن تكون قيمه مرسلة لخيط معين لتنفيذها في ذلك الخيط وهو ما تم عمله فعلا في ال start method ما بين السطور 50 و 54.

في ال run method نقوم بالتحرك خطوه على كل من المحاور ثم نقوم بفحص القيم الجديدة للاحداثايت فاذا تجاوزت أحدها الشاشه نقوم بعكس اتجاه الحركه. هذه ال method عالقه في حلقه تكراريه لا نهائيه لن تنتهي الا بتغيير قيمه المتغير quit الى false.

في كل حلقه نقوم باعاده رسم المربع في المكان الجديد ثم نجبر الخيط على الانتظار لمده 50 milliseconds.

الان نقوم بعرض هذه الشاشة على شاشه الهاتف كالتالي:
public class AnimationMidlet extends MIDlet implements CommandListener {
    AnimationCanvas animator;
    
    public void startApp() {
        animator = new AnimationCanvas();
        animator.start();
        Display.getDisplay(this).setCurrent( animator );
        animator.addCommand( new Command( "Exit", Command.EXIT, 0 ) );
        animator.setCommandListener( this );

    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable d) {
        animator.stop();
        destroyApp(true);
        notifyDestroyed();
    }
}

مقدمة في انشاء واجهة مستخدم منخفضة المستوى - الجزء الثالث

 الخطوط
التحكم في لون وحجم وشكل الخط
في JME لا يوجد الكثير من الخيارات للتحكم في الخطوط فهي تحتوي على ثلالثه أنواع فقط من الخطوط ويمكنك تحديد ثلاثه أحجام أيضا ولا يوجد ما يسمى بالنقاط لتحديد حجم الخط أما تنسيقه فهو محصور ما بين الخط العادي والخط الغامق والخط المائل والخط الذي تحته سطر.

كيفيه انشاء خط لاستخدامه في الرسم
Font f = Font.getFont(int face, int style, int size);
أنواع الخطوط
  • FACE_SYSTEM
  • FACE_MONOSPACE
  • FACE_PROPORTIONAL
 تنسيق الخطوط
  • STYLE_PLAIN
  • STYLE_BOLD
  • STYLE_ITALIC
  • STYLE_UNDERLINED
حجم الخط
  • SIZE_SMALL
  • SIZE_MEDIUM
  • SIZE_LARGE
الصور
يتم رسم الصور عن طريق ال drawImage method الموجوده في الفئه Graphics.
public void drawImage(Image img,
                      int x,
                      int y,
                      int anchor)
محاذاه الصوره يشبه الى حد كبير محاذاه النصوص التي تم شرحها سابقا.

مجال الرسم
يمكن تحديد مجال للرسم بحيث أن لأي شيء خارج هذا المجال فانه لن يرسم باستخدام ال setClip method الموجوده في الفئه Graphics.
public void setClip(int x,
                    int y,
                    int width,
                    int height)
استقبال الأحادث في ال Canvas
عند الضغط على أزرار الهاتف فان مجموعه من ال methods سوف يتم تنفيذها لكي تعلمك بحدوث الحدث كما سترسل لك بعض المعلومات عن الزر الذي تم الضغط عليه.
protected void keyPressed(int keyCode)
protected void keyReleased(int keyCode)
Protected void keyRepeated(int keyCode)

Game Actions
يمكن معرفه ال Game Action المقابل لكل keycode تم استقباله في أحد ال methods السابقه عن طريق
int gameAction = getGameAction(keyCode);
أنواع ال Game Actions التي تدعمها JME هي كالتالي:
  • UP
  • DOWN
  • LEFT
  • RIGHT
  • FIRE
  • GAME_A
  • GAME_B
  • GAME_C
  • GAME_D
ال Game Actions يمكن أت ترتبط بأزرار مختلفه حسب نوع الجهاز وهي بذلك تريح المبرمج من عناء اختلاف الأجهزه فمثلا زر ال Fire في هواتف Nokia عاده هو الزر الموجود في منتصف لوحه التحرك أو الزر الذي يحمل الرقم 5 وبالتالي فانت عندما تقوم بعمل لعبه ما فان المستخدم سيستخدم نفس الأزرار التي تعود على استخدامها وبنفس الطريقه.

مثال
public class KeyCanvas extends Canvas {

    private Font mFont;
    private String mMessage = "[Press keys]";


    public KeyCanvas() {
        mFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
    }


    public void paint(Graphics g) {
        int w = getWidth();
        int h = getHeight();

        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, w - 1, h - 1);
        g.setColor(0x0);
        g.drawRect(0, 0, w - 1, h - 1);
        g.setFont(mFont);
        int x = w / 2;
        int y = h / 2;
        g.drawString(mMessage, x, y, Graphics.BASELINE | Graphics.HCENTER);
    }

    protected void keyPressed(int keyCode) {
        int gameAction = getGameAction(keyCode);

        switch (gameAction) {
            case UP:
                mMessage = "UP";
                break;

            case DOWN:
                mMessage = "DOWN";
                break;

            case LEFT:
                mMessage = "LEFT";
                break;

            case RIGHT:
                mMessage = "RIGHT";
                break;
            case FIRE:
                mMessage = "FIRE";
                break;
            case GAME_A:
                mMessage = "GAME_A";
                break;
            case GAME_B:
                mMessage = "GAME_B";
                break;
            case GAME_C:
                mMessage = "GAME_C";
                break;
            case GAME_D:
                mMessage = "GAME_D";
                break;
            default:
                mMessage = "";
                break;
        }
        repaint();
    }
}
في المثال السابق أعدنا تعريف keyPressed method وفي داخلها قمنا بمعرفه ال Game Action الذي حصل باستخدام جملة switch ثم أدخلنا اسم هذا ال Game Action في متغير اسمه mMessage وفي أخر سطر من ال method استدعينا repaint لكي تقوم باعاده رسم الشاشه.


في ال paint method نقوم برسم المتغير mMessage في منتصف الشاشه. لاحظ أن هذه الفئه ترث من الفئه Canvas وبالتالي نستطيع وضعها على شاشه الهاتف وهو ما سنقوم به في السطور الأتيه:
public class KeyEvents extends MIDlet {
    public void startApp() {
        KeyCanvas canvas = new KeyCanvas();
        Display.getDisplay(this).setCurrent( canvas );
        
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
}

الجمعة، 16 يوليو، 2010

نوكيا سوف تجعل عمليه ال Signing لبرامج ال Symbian مجانا

أعلنت شركه نوكيا عن نيتها جعل ال Signing لبرامج ال Symbian مجانا بعد أن كانت تكلف هذه العمليه 215$ وقد بدأ العمل في هذه الخطوه التجربيه منذ 23 June. وهذا البرنامج سوف يغطيي البرامج التي من نوع Symbian بشقيها sis و sisx والتي من نوع Qt والتي من نوع Flash Lite. سوف لن يغطي البرنامج برامج الجافا وهو أمر مفهوم حيث ان تكاليف ال Signing لبرامج الجافا لا تذهب لشركه نوكيا وانما لشركه Oracle مالكه جافا.

خطوات نشر برنامج على Ovi أصبح كالتالي كما جاء نقلا عن موقع نوكيا:
  • Ovi Publisher emails support and requests more details  
  • Ovi Publish support asks publisher to review and accept new terms and conditions
  • Ovi Publisher accepts new terms and conditions and provides IMEI numbers for up to 5 devices
  • Ovi Publish support sends publisher UIDs, a cert installer, and developer cert/key pair for testing their app
  • Ovi Publisher packages their unsigned SIS file using the UID provided and tests on their device making sure is tested against Symbian’s signing criteria
  • Ovi Publisher submits their app (unsigned SIS file with the UID provided) to the intake tool
  • QA and moderation will test the app and if it passes it will be express signed by Nokia and put into Ovi Store

الأربعاء، 26 مايو، 2010

مقدمة في انشاء واجهة مستخدم منخفضة المستوى - الجزء الثاني

تنسيق الخطوط
يوجد تنسيقان مختلفان للخطوط وهما:
  • Solid
  • Dotted
ويمكن استخدامهما عن طريق ال setStrokeStyle method داخل الفئة Graphics كالتالي:
public void paint(Graphics g) {
 g.drawRect(20, 10, 35, 35);
 g.setStrokeStyle(Graphics.DOTTED);
 g.drawRect(20, 60, 35, 35);
}

في المثال السابق سوف يتم رسم مربع ولكن حدود المربع سوف ترسم بخط متقطع بسبب تغيير التنسيق. 

رسم النصوص
يوجد العديد من ال methods التي سةف تساعدك على رسم النصوص على الشاشة وجميعها موجودة داخل الفئة Graphics:
  • public void drawChar(char character, int x, int y, int anchor)
  • public void drawChars(char[] data, int offset, int length,int x, int y, int anchor)
  • public void drawString(String str, int x, int y, int anchor)
  • public void drawSubstring(String str, int offset, int len,int x, int y, int anchor)
جميع القيم الممررة لل methods واضحة وبسيطه الا أخر قيمة وهي ال anchor. هذه القيمة هي عبارة عن النقطة المرجعية للرسم والتي يجب أن تنطبق عليها قيم ال x و y في جميع ال methods.


قيم ال anchor هي عباره عن عملية Bitwise Or بين قيمة المحاذاة الأفقيه والتي يمكن أن تكون ( LEFT, HCENTER, RIGHT ) وبين قيمة المحاذاة العمودية والتي يمكن أن تكون ( TOP, BASELINE, BOTTOM ).

الأن لنفترض أنك أعطيت احدى ال methods السابقة القيم التالية:
x = 10
y = 5
anchor = Graphics.LEFT | Graphics.TOP

سيرسم النص بحيث أن زاويه المربع المحيطة بالنص من الأعلى واليسار سوف تنطبق على النقطة ( 10,5 ).

مثال
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.*;

public class TextDrawing extends MIDlet implements CommandListener {
    Command cmdExit = new Command( "Exit", Command.EXIT, 0 );

    public void startApp() {
        TextCanvas canvas = new TextCanvas();
        canvas.addCommand( cmdExit );
        canvas.setCommandListener( this );
        Display.getDisplay(this).setCurrent( canvas );

    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable d) {
        notifyDestroyed();

    }
    
}

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;

public class TextCanvas extends Canvas {
    public void paint(Graphics g) {
        int w = getWidth();
        int h = getHeight();
        g.setColor(0xffffff);
        g.fillRect(0, 0, w, h);
        g.setColor(0x000000);

        g.drawString("TOP_LEFT", 0, 0, Graphics.TOP | Graphics.LEFT);
        g.drawString("TOP_RIGHT", w, 0, Graphics.TOP | Graphics.RIGHT);
        g.drawString("BOTTOM_LEFT", 0, h, Graphics.BOTTOM | Graphics.LEFT);
        g.drawString("BOTTOM_RIGHT", w, h, Graphics.BOTTOM | Graphics.RIGHT);

        g.drawString("JME World", w / 2, h / 2, Graphics.BASELINE | Graphics.HCENTER);
    }
    
}