Java Swing দিয়ে ক্যালকুলেটর অ্যাপ বানানোর সহজ গাইড

টিউন বিভাগ জাভা
প্রকাশিত

জাভা শেখার শুরুতে বেশিরভাগ সময় আমরা শুধু কনসোলে লেখা ছাপাই। কিন্তু নিজের হাতে বানানো একটা উইন্ডো, যেখানে বাটনে চাপ দিলে সত্যি সত্যি হিসাব হয়, সেটি দেখার আনন্দই আলাদা। ক্যালকুলেটর অ্যাপ বানানো এই জায়গায় সবচেয়ে ভালো প্রথম প্রজেক্ট, কারণ এতে একসাথে লেআউট, ইভেন্ট হ্যান্ডলিং, অবস্থা সংরক্ষণ আর এরর সামলানো, সবকিছুর চর্চা হয়ে যায়।

এই টিউনে আমরা Java Swing ব্যবহার করে একটি সম্পূর্ণ কাজ করা ক্যালকুলেটর তৈরি করব। কোনো বাড়তি লাইব্রেরি লাগবে না, শুধু JDK থাকলেই চলবে। প্রতিটি ধাপে কোডের সাথে ব্যাখ্যা থাকবে যাতে আপনি কেবল কপি না করে বুঝতে পারেন কোন লাইনটি কী করছে। শেষে সম্পূর্ণ কোড একসাথে দেওয়া থাকবে এবং কমন সমস্যাগুলোর সমাধানও থাকবে।

যা যা লাগবে

  • কম্পিউটারে JDK 17 বা তার চেয়ে নতুন ভার্সন ইনস্টল করা থাকতে হবে
  • IntelliJ IDEA Community Edition অথবা Eclipse, যেকোনো একটি এডিটর
  • জাভাতে ক্লাস, মেথড ও অ্যারে সম্পর্কে প্রাথমিক ধারণা
  • আনুমানিক ৪০ মিনিট সময়, তাড়াহুড়ো করলে ভুল ধরা কঠিন হবে

অ্যাপটি কেমন হবে

আমাদের ক্যালকুলেটরে উপরে থাকবে একটি ডিসপ্লে বক্স, আর নিচে চার সারি ও চার কলামে সাজানো ষোলোটি বাটন। যোগ, বিয়োগ, গুণ ও ভাগ কাজ করবে, C বাটনে সব মুছে যাবে, আর শূন্য দিয়ে ভাগ করতে চাইলে প্রোগ্রাম ভেঙে না গিয়ে বাংলায় বার্তা দেখাবে।

  • ডিসপ্লের জন্য JTextField ব্যবহার করব, তবে সেটি এডিট করা যাবে না
  • বাটনগুলো সাজাতে GridLayout ব্যবহার করব, কারণ এতে সব বাটন সমান মাপের হয়
  • প্রতিটি বাটনের ক্লিক ধরতে একটিই ActionListener ব্যবহার করব
  • আগের সংখ্যা ও অপারেটর মনে রাখতে ক্লাসের ভেতরে কয়েকটি ফিল্ড রাখব

Swing কম্পোনেন্টের স্তর বিন্যাস, JFrame থেকে JButton পর্যন্ত

কোড লেখার আগে উপরের চিত্রটি একবার দেখে নিন। Swing এ প্রতিটি জিনিস আরেকটির ভেতরে বসে, ঠিক বাক্সের ভেতরে বাক্সের মতো। সবার বাইরে থাকে পুরো উইন্ডোটি, তার ভেতরে থাকে একটি খালি জায়গা, আর সেই খালি জায়গাতেই আমরা নিজেদের জিনিস গুলো বসাই। এই স্তর গুলো মাথায় না থাকলে পরে লেআউট নিয়ে সমস্যা হলে বোঝা যায় না ভুলটা কোথায় হয়েছে।

ডান দিকের ডালটি লক্ষ করুন। বাটন গুলো সরাসরি উইন্ডোতে বসছে না, বরং আগে একটি পাতা তৈরি করা হচ্ছে আর সেই পাতার উপরে বাটন গুলো সাজানো হচ্ছে। এভাবে কাজ করার সুবিধা হলো, পাতাটিকে যেকোনো সময় পুরো উইন্ডোর যেকোনো জায়গায় সরানো যায় এবং ভেতরের বাটন গুলো নিজে থেকেই সাথে সাথে চলে আসে।

শুরুতে অনেকেই একটি ভুল করেন, সব কিছু সরাসরি উইন্ডোতে বসিয়ে দেন। তখন একটি অংশ বদলাতে গেলে পুরো সাজানোটাই এলোমেলো হয়ে যায়। তাই অভ্যাস করুন, যেই কয়েকটি জিনিস একসাথে থাকবে সেগুলোকে আগে একটি পাতায় বসিয়ে নিন।

Swing এর মূল ধারণা, কম্পোনেন্ট আর কনটেইনার

Swing দিয়ে কাজ করার আগে দুইটি শব্দ ভালোভাবে বুঝে নেওয়া দরকার। প্রথমটি কম্পোনেন্ট, দ্বিতীয়টি কনটেইনার। কম্পোনেন্ট হলো পর্দায় দেখা যায় এমন প্রতিটি আলাদা জিনিস, যেমন একটি বাটন, একটি লেখার ঘর বা একটি লেবেল। কনটেইনার হলো এমন জিনিস যার ভিতরে অন্য কম্পোনেন্ট রাখা যায়।

মজার ব্যাপার হলো, কনটেইনার নিজেও একধরনের কম্পোনেন্ট। এর মানে একটি কনটেইনারের ভিতরে আরেকটি কনটেইনার রাখা যায়, আর তার ভিতরে আরও কম্পোনেন্ট। এভাবেই একটি গাছের মতো কাঠামো তৈরি হয়। আমাদের ক্যালকুলেটরে সবচেয়ে বাইরের কনটেইনার হলো উইন্ডো, তার ভিতরে রয়েছে ডিসপ্লের জায়গা আর বাটনগুলো রাখার প্যানেল।

এই কাঠামোটি বুঝে গেলে বড় ইন্টারফেস বানানো অনেক সহজ হয়ে যায়। কারণ তখন পুরো পর্দাটিকে এক নজরে না ভেবে ছোট ছোট অংশে ভাগ করে ভাবা যায়। প্রতিটি অংশের জন্য আলাদা প্যানেল নিয়ে সেটিকে নিজের মতো সাজিয়ে নেওয়া যায়, তারপর সব প্যানেল একসাথে মূল উইন্ডোতে বসিয়ে দেওয়া যায়।

  • বাটন, লেবেল আর লেখার ঘর সবই কম্পোনেন্ট, এগুলো পর্দায় দেখা যায়।
  • প্যানেল ও উইন্ডো হলো কনটেইনার, এদের ভিতরে অন্য জিনিস রাখা যায়।
  • বড় ইন্টারফেসকে ছোট প্যানেলে ভাগ করে নিলে কোড গোছানো থাকে।
  • প্রতিটি কম্পোনেন্ট কোন কনটেইনারে আছে তা মনে রাখলে সমস্যা খুঁজে পাওয়া সহজ হয়।

ধাপ ১: প্রজেক্ট ও ক্লাস তৈরি

এডিটরে New Project থেকে একটি সাধারণ Java প্রজেক্ট খুলুন এবং src ফোল্ডারের ভেতরে Calculator নামে একটি ক্লাস তৈরি করুন। ফাইলের নাম আর পাবলিক ক্লাসের নাম হুবহু এক হতে হবে, নাহলে কম্পাইলার এরর দেবে।

  • ক্লাসটি JFrame থেকে extends করব, ফলে আমাদের ক্লাসটিই একটি উইন্ডো হয়ে যাবে
  • ActionListener ইন্টারফেস implements করব, ফলে বাটনের ক্লিক এই ক্লাসেই ধরা পড়বে
  • প্রয়োজনীয় ইমপোর্ট তিনটি, javax.swing, java.awt এবং java.awt.event প্যাকেজ থেকে

ধাপ ২: উইন্ডো ও ডিসপ্লে তৈরি

কনস্ট্রাক্টরের ভেতরে উইন্ডোর মাপ, বন্ধ করার নিয়ম আর অবস্থান ঠিক করে নিচ্ছি। setLocationRelativeTo মেথডে null দিলে উইন্ডোটি স্ক্রিনের ঠিক মাঝখানে খোলে।

display.setEditable(false);
display.setHorizontalAlignment(JTextField.RIGHT);
display.setFont(new Font("Arial", Font.BOLD, 32));
display.setText("0");
add(display, BorderLayout.NORTH);
  • setEditable মিথ্যা রাখা জরুরি, নাহলে ব্যবহারকারী ডিসপ্লেতে যেকোনো লেখা টাইপ করে ফেলতে পারবে
  • ডান দিকে সংখ্যা দেখানো হলে দেখতে সত্যিকারের ক্যালকুলেটরের মতো লাগে
  • BorderLayout.NORTH এ রাখলে ডিসপ্লে সবসময় উপরে থাকবে

LayoutManager কী এবং কেন এত জরুরি

অনেকে শুরুতে ভাবেন, প্রতিটি বাটনের জায়গা নিজে ঠিক করে দিলেই তো হয়ে যায়। কিন্তু এভাবে করলে একটি বড় সমস্যা হয়। ব্যবহারকারী যদি উইন্ডোটি টেনে বড় বা ছোট করেন, তখন বাটনগুলো আগের জায়গাতেই আটকে থাকে, ফলে পুরো নকশাটি এলোমেলো দেখায়। আবার আলাদা কম্পিউটারে পর্দার মাপ ভিন্ন হলে সমস্যা আরও বাড়ে।

এই সমস্যার সমাধানই LayoutManager। এটি একধরনের নিয়ম, যা ঠিক করে দেয় কম্পোনেন্টগুলো কীভাবে সাজবে এবং জায়গা বদলালে কে কতটুকু জায়গা নেবে। আমাদের ক্যালকুলেটরে বাটনগুলো সারি ও কলামে সমানভাবে সাজানো দরকার, তাই এখানে গ্রিড ভিত্তিক নিয়মটি সবচেয়ে মানানসই। উইন্ডো বড় করলেও বাটনগুলো নিজেরাই সমানভাবে বড় হয়ে যায়।

Swing এ কয়েক ধরনের নিয়ম আছে এবং প্রতিটির আলাদা কাজ। সব সময় একটিই ব্যবহার করতে হবে এমন নয়, বরং বিভিন্ন প্যানেলে বিভিন্ন নিয়ম মিশিয়ে ব্যবহার করাই স্বাভাবিক। যেমন মূল উইন্ডোতে উপরে ডিসপ্লে আর নিচে বাটন বসাতে সীমানা ভিত্তিক নিয়ম কাজে লাগে, আর বাটনগুলোর ভিতরে গ্রিড নিয়ম কাজে লাগে।

  • নিজে হাতে জায়গা ঠিক করলে উইন্ডোর মাপ বদলালে নকশা ভেঙে যায়।
  • গ্রিড ভিত্তিক নিয়মে সব ঘর সমান জায়গা পায়, ক্যালকুলেটরের জন্য আদর্শ।
  • সীমানা ভিত্তিক নিয়মে উপর, নিচ ও মাঝখানে আলাদা অংশ রাখা যায়।
  • এক প্রোগ্রামে একাধিক নিয়ম মিশিয়ে ব্যবহার করা একেবারে স্বাভাবিক।

ধাপ ৩: GridLayout দিয়ে বাটন সাজানো

এখানে একটি অ্যারেতে বাটনের লেখাগুলো রেখে লুপ চালিয়ে বাটন বানাচ্ছি। ষোলোটি বাটন হাতে হাতে লিখলে কোড অকারণে লম্বা হতো।

JPanel panel = new JPanel(new GridLayout(4, 4, 6, 6));
String[] labels = {"7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "C", "0", "=", "+"};
for (String label : labels) {
    JButton button = new JButton(label);
    button.setFont(new Font("Arial", Font.PLAIN, 22));
    button.addActionListener(this);
    panel.add(button);
}
add(panel, BorderLayout.CENTER);
  • GridLayout এর শেষ দুটি সংখ্যা বাটনের মাঝের ফাঁকা জায়গা ঠিক করে
  • addActionListener এ this দেওয়ার মানে হলো ক্লিক হলে এই ক্লাসের actionPerformed মেথডটি চলবে
  • লুপ ব্যবহার করায় নতুন বাটন যোগ করতে চাইলে শুধু অ্যারেতে একটি লেখা বাড়ালেই হবে

ক্যালকুলেটরের GridLayout ব্যাখ্যাচিত্র, ৪ × ৪ ঘরে সাজানো বাটন

উপরের ব্যাখ্যাচিত্রে বাটন গুলো ঠিক যেভাবে পর্দায় বসবে সেভাবেই আঁকা হয়েছে। GridLayout এর নিয়মটি খুব সরল, আপনি শুধু বলে দেবেন কত সারি আর কত কলাম চান, বাকিটা সে নিজেই সমান ভাগ করে নেবে। প্রতিটি ঘরের মাপ একদম সমান হয়, তাই আলাদা করে কোনো মাপ ঠিক করে দিতে হয় না।

সবচেয়ে জরুরি কথাটি হলো ক্রম। যে ক্রমে বাটন গুলো যোগ করবেন, ঠিক সেই ক্রমেই সেগুলো বাম থেকে ডানে আর উপর থেকে নিচে বসবে। মাঝখানে একটি বাটন যোগ করতে ভুলে গেলে তারপরের সব বাটন এক ঘর করে সরে যাবে এবং পুরো ক্যালকুলেটরটি দেখতে অদ্ভুত লাগবে। তাই কোড লেখার সময় চিত্রটি পাশে খোলা রেখে এক সারি করে মিলিয়ে নিন।

রঙ গুলো শুধু বোঝার সুবিধার জন্য দেওয়া হয়েছে, কোডে এমন রঙ দিতে হবে না। তবে একটি পরামর্শ কাজে দেবে, সংখ্যার বাটন আর অপারেটরের বাটন গুলোকে মনে মনে আলাদা দুটি দল হিসেবে ভাবুন। পরে ক্লিক ধরার সময় এই ভাগটিই আপনার কাজে লাগবে, কারণ দুই দলের জন্য করণীয় কাজ সম্পূর্ণ আলাদা।

ইভেন্ট চালিত প্রোগ্রামিং আসলে কী

সাধারণ কনসোল প্রোগ্রামে কাজের ধারা সোজা। উপর থেকে নিচে লাইন ধরে চলে, শেষ হলে প্রোগ্রাম বন্ধ হয়। কিন্তু গ্রাফিকাল অ্যাপে ব্যাপারটি একেবারে আলাদা। এখানে প্রোগ্রাম চালু হয়ে অপেক্ষা করতে থাকে, ব্যবহারকারী কিছু করলে তবেই কাজ শুরু হয়। এই ধরনটিকেই বলা হয় ইভেন্ট চালিত প্রোগ্রামিং।

ভিতরে আসলে একটি বিশেষ থ্রেড সব সময় চোখ রাখে, কোথায় ক্লিক হলো বা কোন কী চাপা হলো তা দেখার জন্য। কিছু ঘটলে সেটি একটি বার্তা তৈরি করে এবং যে কোড সেই বার্তার জন্য অপেক্ষা করছিল তাকে ডেকে দেয়। আমাদের ক্যালকুলেটরে প্রতিটি বাটনের সাথে এমন একটি শ্রোতা জুড়ে দেওয়া হয়, তাই বাটনে চাপ পড়লেই সংশ্লিস্ট কোডটি চলে।

এখানে একটি গুরুত্বপূর্ণ সাবধানতা আছে। ওই থ্রেডেই পর্দা আঁকার কাজও হয়। তাই শ্রোতার ভিতরে যদি অনেক সময় লাগে এমন কাজ দেওয়া হয়, তবে পুরো উইন্ডোটি জমে যায় এবং ব্যবহারকারী ভাবেন অ্যাপটি নষ্ট হয়ে গেছে। এই কারণে ভারী কাজ সব সময় আলাদা থ্রেডে পাঠাতে হয়, আর শ্রোতার ভিতরে শুধু হালকা কাজ রাখতে হয়।

  • গ্রাফিকাল অ্যাপ অপেক্ষা করে, ব্যবহারকারী কিছু করলেই কাজ শুরু হয়।
  • প্রতিটি বাটনের সাথে একটি শ্রোতা জুড়ে দিলে ক্লিক ধরা যায়।
  • শ্রোতার ভিতরে সময়সাপেক্ষ কাজ দিলে উইন্ডো জমে যায়।
  • ভারী কাজ আলাদা থ্রেডে পাঠালে অ্যাপ সচল থাকে।

ধাপ ৪: ক্লিক ধরা ও অবস্থা মনে রাখা

ক্যালকুলেটরের আসল বুদ্ধি এখানেই। ব্যবহারকারী সংখ্যা চাপলে সেটি ডিসপ্লেতে যোগ হবে, আর অপারেটর চাপলে আগের সংখ্যা আলাদা করে রেখে দিতে হবে।

@Override
public void actionPerformed(ActionEvent event) {
    String command = event.getActionCommand();
    if ("0123456789".contains(command)) {
        if (startNew) {
            display.setText(command);
            startNew = false;
        } else {
            display.setText(display.getText() + command);
        }
    } else if (command.equals("C")) {
        display.setText("0");
        first = 0;
        operator = "";
        startNew = true;
    } else if (command.equals("=")) {
        calculate();
    } else {
        first = Double.parseDouble(display.getText());
        operator = command;
        startNew = true;
    }
}
  • startNew নামের boolean ফিল্ডটি মনে রাখে পরের সংখ্যাটি নতুন করে শুরু হবে নাকি আগেরটির সাথে জুড়বে
  • first ফিল্ডে অপারেটর চাপার আগের সংখ্যাটি জমা থাকে
  • getActionCommand মেথড বাটনের গায়ে লেখা টেক্সটটিই ফেরত দেয়, তাই আলাদা করে আইডি রাখার দরকার হয় না

বাটনে চাপ দেওয়ার পর ActionListener এর ভেতরে যা ঘটে

একটি বাটনে চাপ দেওয়ার পর ভেতরে ঠিক কী কী ঘটে, সেটি উপরের চিত্রে ধাপে ধাপে সাজানো হয়েছে। নতুনদের কাছে এই অংশটি জাদুর মতো লাগে, কারণ কোথাও তো লেখা নেই যে চাপ দিলে অমুক কাজটি হবে। আসলে Swing নিজে একটি আলাদা সারি চালায়, সেখানে সব ঘটনা লাইন ধরে দাঁড়ায় এবং একটি করে কাজ শেষ হয়।

এই সারির কথাটি মনে রাখা দরকার, কারণ এর একটি বড় ফল আছে। আপনার লেখা কাজটি যদি অনেক সময় নেয়, তাহলে ওই সময়টুকু পুরো উইন্ডো জমে থাকবে, কোনো বাটনই সাড়া দেবে না। ক্যালকুলেটরের হিসাব চোখের পলকে হয়ে যায় তাই এখানে সমস্যা হবে না, কিন্তু ভবিষ্যতে ফাইল পড়া বা ইন্টারনেট থেকে কিছু আনার কাজ করলে সেটি আলাদা থ্রেডে করতে হবে।

চতুর্থ ধাপটি একটু খেয়াল করুন। কোন বাটনে চাপ পড়েছে সেটি বোঝার জন্য আলাদা করে ষোলটি মেথড লেখার দরকার নেই, বাটনের গায়ের লেখাটি ধরেই কাজ চালানো যায়। এভাবে লিখলে কোড অনেক ছোট হয় এবং পরে নতুন বাটন যোগ করা সহজ হয়ে যায়।

ধাপ ৫: হিসাব করার লজিক ও শূন্য দিয়ে ভাগ

সমান চিহ্নে চাপ দিলে calculate মেথডটি চলবে। এখানে সবচেয়ে গুরুত্বপূর্ণ অংশ হলো ভাগের আগে ভাজক শূন্য কিনা যাচাই করা।

private void calculate() {
    double second = Double.parseDouble(display.getText());
    double result;
    switch (operator) {
        case "+":
            result = first + second;
            break;
        case "-":
            result = first - second;
            break;
        case "*":
            result = first * second;
            break;
        case "/":
            if (second == 0) {
                display.setText("শূন্য দিয়ে ভাগ নয়");
                startNew = true;
                return;
            }
            result = first / second;
            break;
        default:
            return;
    }
    display.setText(format(result));
    startNew = true;
}

private String format(double value) {
    if (value == Math.floor(value)) {
        return String.valueOf((long) value);
    }
    return String.valueOf(value);
}

format মেথডটি কেন দরকার

জাভাতে double টাইপে হিসাব করলে দুই যোগ দুই এর ফল দেখায় 4.0 হিসেবে। format মেথডটি দেখে নেয় ফলটি পূর্ণসংখ্যা কিনা, হলে দশমিক অংশ বাদ দিয়ে দেখায়। এই ছোট কাজটুকু না করলে অ্যাপটি অপেশাদার দেখায়।

ধাপ ৬: প্রোগ্রাম চালু করা

Swing এর সব কাজ Event Dispatch Thread নামের একটি বিশেষ থ্রেডে চালানোই নিয়ম। তাই main মেথডে সরাসরি উইন্ডো না খুলে invokeLater ব্যবহার করছি।

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        Calculator calculator = new Calculator();
        calculator.setVisible(true);
    });
}
  • setVisible সত্যি না করলে উইন্ডো তৈরি হয় ঠিকই কিন্তু চোখে দেখা যায় না
  • setDefaultCloseOperation এ EXIT ON CLOSE না দিলে উইন্ডো বন্ধ করার পরেও প্রোগ্রাম চলতেই থাকে
  • চেহারা আরও সুন্দর করতে UIManager দিয়ে সিস্টেমের নিজস্ব Look And Feel সেট করে নিতে পারেন

সম্পূর্ণ কোড একসাথে

উপরের ধাপগুলো মিলিয়ে পুরো ফাইলটি নিচে দেওয়া হলো। Calculator.java নামে সেভ করে রান করলেই অ্যাপটি চালু হবে।

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Calculator extends JFrame implements ActionListener {
    private final JTextField display = new JTextField();
    private double first = 0;
    private String operator = "";
    private boolean startNew = true;

    public Calculator() {
        setTitle("সহজ ক্যালকুলেটর");
        setSize(340, 420);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout(8, 8));
        display.setEditable(false);
        display.setHorizontalAlignment(JTextField.RIGHT);
        display.setFont(new Font("Arial", Font.BOLD, 32));
        display.setText("0");
        add(display, BorderLayout.NORTH);
        JPanel panel = new JPanel(new GridLayout(4, 4, 6, 6));
        String[] labels = {"7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "C", "0", "=", "+"};
        for (String label : labels) {
            JButton button = new JButton(label);
            button.setFont(new Font("Arial", Font.PLAIN, 22));
            button.addActionListener(this);
            panel.add(button);
        }
        add(panel, BorderLayout.CENTER);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        String command = event.getActionCommand();
        if ("0123456789".contains(command)) {
            if (startNew) {
                display.setText(command);
                startNew = false;
            } else {
                display.setText(display.getText() + command);
            }
        } else if (command.equals("C")) {
            display.setText("0");
            first = 0;
            operator = "";
            startNew = true;
        } else if (command.equals("=")) {
            calculate();
        } else {
            first = Double.parseDouble(display.getText());
            operator = command;
            startNew = true;
        }
    }

    private void calculate() {
        double second = Double.parseDouble(display.getText());
        double result;
        switch (operator) {
            case "+":
                result = first + second;
                break;
            case "-":
                result = first - second;
                break;
            case "*":
                result = first * second;
                break;
            case "/":
                if (second == 0) {
                    display.setText("শূন্য দিয়ে ভাগ নয়");
                    startNew = true;
                    return;
                }
                result = first / second;
                break;
            default:
                return;
        }
        display.setText(format(result));
        startNew = true;
    }

    private String format(double value) {
        if (value == Math.floor(value)) {
            return String.valueOf((long) value);
        }
        return String.valueOf(value);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Calculator calculator = new Calculator();
            calculator.setVisible(true);
        });
    }
}

দশমিক ও ধারাবাহিক হিসাব সামলানোর নিয়ম

সাধারণ যোগ বিয়োগ কাজ করার পর প্রথম যে দুইটি জিনিস আটকে দেয়, তার একটি দশমিক আর অন্যটি ধারাবাহিক হিসাব। দশমিকের ক্ষেত্রে মূল নিয়মটি খুব সহজ, একটি সংখ্যায় একটির বেশি দশমিক বিন্দু থাকতে পারে না। তাই দশমিকের বাটনে চাপ পড়লে আগে দেখে নিতে হয় বর্তমান সংখ্যাটিতে ইতিমধ্যে বিন্দু আছে কি না। থাকলে চাপটি অগ্রাহ্য করতে হয়।

ধারাবাহিক হিসাবের ব্যাপারটি একটু বেশি ভাবনার। ব্যবহারকারী যখন পাঁচ যোগ তিন যোগ দুই চাপেন, তখন দ্বিতীয় যোগের বাটনে চাপ পড়ার সাথে সাথেই আগের যোগটি সম্পন্ন করে ফেলতে হয় এবং ফল ডিসপ্লেতে দেখাতে হয়। এভাবে যেকোনো লম্বা হিসাব ধাপে ধাপে এগোতে পারে, আর সমান বাটনে চাপ পড়লে শুধু শেষ কাজটি বাকি থাকে।

এই কাজটি ঠিকভাবে করতে তিনটি তথ্য মনে রাখা দরকার। আগের সংখ্যা কত ছিল, কোন চিহ্নটি অপেক্ষা করছে, আর এখন নতুন সংখ্যা টাইপ করা শুরু হয়েছে কি না। এই তিনটি তথ্য ঠিকভাবে রাখলে হিসাব কখনো এলোমেলো হবে না। বিশেষ করে শেষ তথ্যটি জরুরি, কারণ এর উপরেই নির্ভর করে নতুন অঙ্ক আগের সংখ্যার সাথে যুক্ত হবে নাকি নতুন করে শুরু হবে।

  • একটি সংখ্যায় একটির বেশি দশমিক বিন্দু ঢুকতে দেবেন না।
  • চিহ্নের বাটনে চাপ পড়লে আগের অপেক্ষমাণ হিসাবটি আগে সেরে ফেলুন।
  • আগের সংখ্যা, অপেক্ষমাণ চিহ্ন আর নতুন ইনপুট শুরু হয়েছে কি না, এই তিনটি মনে রাখুন।
  • সমান বাটনের পর নতুন অঙ্ক চাপলে হিসাব নতুন করে শুরু হওয়া উচিত।

ভুল ইনপুট ও ব্যতিক্রম সামলানো

যে অ্যাপ মানুষ ব্যবহার করবে, সেখানে ভুল হবেই। তাই প্রোগ্রামটি এমনভাবে লেখা দরকার যাতে ভুল হলেও সেটি ভেঙে না পড়ে। ক্যালকুলেটরে সবচেয়ে পরিচিত ভুলটি হলো শূন্য দিয়ে ভাগ করা। গণিতে এর কোনো উত্তর নেই, তাই প্রোগ্রামকেও এখানে একটি ভদ্র বার্তা দেখাতে হবে, হঠাৎ বন্ধ হয়ে যাওয়া চলবে না।

এখানে একটি সূক্ষ্ম বিষয় আছে যা অনেকে জানেন না। পূর্ণসংখ্যা দিয়ে ভাগ করার সময় শূন্য দিলে জাভা একটি ব্যতিক্রম তৈরি করে। কিন্তু দশমিক সংখ্যায় একই কাজ করলে ব্যতিক্রম হয় না, বরং ফল হিসেবে অসীম বা অনির্ধারিত মান আসে। তাই শুধু ব্যতিক্রম ধরার উপর ভরসা করলে হবে না, ফলটি আসল সংখ্যা কি না তাও যাচাই করে নিতে হবে।

এর বাইরে আরও কিছু পরিস্থিতি আছে যা আগে থেকে ভেবে রাখা ভালো। ব্যবহারকারী কোনো সংখ্যা না দিয়েই সমান চাপতে পারেন, অথবা পর পর দুইটি চিহ্ন চাপতে পারেন। প্রতিটি ক্ষেত্রে প্রোগ্রামের আচরণ আগে থেকে ঠিক করে রাখলে পরে অপ্রত্যাশিত সমস্যা কম হয়। মনে রাখবেন, ভালো অ্যাপ মানে শুধু সঠিক ইনপুটে সঠিক ফল নয়, ভুল ইনপুটেও ভদ্র আচরণ।

  • শূন্য দিয়ে ভাগের ক্ষেত্রে বার্তা দেখান, প্রোগ্রাম বন্ধ হতে দেবেন না।
  • দশমিক ভাগে ব্যতিক্রম হয় না, তাই ফলটি আসল সংখ্যা কি না যাচাই করুন।
  • পর পর দুইটি চিহ্ন চাপলে কী হবে তা আগেই ঠিক করে রাখুন।
  • এরর দেখানোর পর ক্লিয়ার বাটনে সব কিছু আবার শুরু করার ব্যবস্থা রাখুন।

কমন সমস্যা ও সমাধান

উইন্ডো খুলছে কিন্তু বাটন দেখা যাচ্ছে না

বেশিরভাগ ক্ষেত্রে প্যানেলটি ফ্রেমে যোগ করার আগেই setVisible ডাকা হয়ে গেছে। সব কম্পোনেন্ট যোগ করার পরে সবার শেষে উইন্ডো দৃশ্যমান করুন, অথবা যোগ করার পর revalidate মেথডটি ডাকুন।

বাটনে চাপ দিলে কিছুই হচ্ছে না

প্রতিটি বাটনে addActionListener যোগ করা হয়েছে কিনা দেখুন। লুপের ভেতরে লাইনটি না থাকলে শুধু শেষ বাটনটি কাজ করবে, বাকিগুলো নীরব থাকবে।

বাংলা লেখা বাক্সের ভেতরে ভেঙে যাচ্ছে

যে ফন্ট ব্যবহার করছেন সেটিতে বাংলা অক্ষর নাও থাকতে পারে। Arial এর বদলে সিস্টেমে থাকা কোনো বাংলা ফন্টের নাম দিন, আর ফাইলটি অবশ্যই UTF 8 এনকোডিংয়ে সেভ করুন।

কোড গোছানো রাখার কিছু নিয়ম

ছোট প্রোগ্রামে সব কোড এক জায়গায় লিখলেও চলে যায়। কিন্তু অ্যাপে নতুন বাটন আর নতুন সুবিধা যোগ হতে থাকলে সেই কোড দ্রুত জটিল হয়ে ওঠে। তখন একটি ছোট পরিবর্তন করতে গিয়েও অন্য জায়গা ভেঙে যায়। এই ঝামেলা এড়ানোর সহজ উপায় হলো শুরু থেকেই কাজগুলো আলাদা আলাদা মেথডে ভাগ করে রাখা।

সবচেয়ে কাজের ভাগটি হলো পর্দা তৈরির কাজ আর হিসাব করার কাজ আলাদা রাখা। উইন্ডো ও বাটন বানানোর কোড এক জায়গায় থাকবে, আর যোগ বিয়োগের হিসাব করার কোড সম্পূর্ণ আলাদা জায়গায় থাকবে। এই ভাগটি করলে বড় একটি সুবিধা পাওয়া যায়, হিসাবের কোডটি পর্দা ছাড়াই আলাদাভাবে পরীক্ষা করে দেখা সম্ভব হয়।

নাম দেওয়ার ব্যাপারেও একটু যত্ন নেওয়া দরকার। ভেরিয়েবলের নাম দেখেই যেন বোঝা যায় সেটি কী কাজ করে। এক অক্ষরের নাম লেখার সময় দ্রুত মনে হয়, কিন্তু কয়েক দিন পর নিজের কোড পড়তে গিয়েই বিপদে পড়তে হয়। একইভাবে যে সংখ্যাগুলো বার বার লাগে সেগুলো আলাদা ধ্রুবক হিসেবে উপরে লিখে রাখলে পরে বদলানো সহজ হয়।

  • পর্দা তৈরির কোড আর হিসাবের কোড আলাদা মেথডে রাখুন।
  • হিসাবের অংশ আলাদা থাকলে সেটি নিজে নিজে পরীক্ষা করা যায়।
  • ভেরিয়েবলের নাম দেখে যেন কাজ বোঝা যায়, এক অক্ষরের নাম এড়ান।
  • বার বার লাগে এমন মান আলাদা ধ্রুবক হিসেবে উপরে লিখে রাখুন।
  • একটি মেথড যদি অনেক লম্বা হয়ে যায়, তবে তাকে ভেঙে ছোট করুন।

আরও যা যোগ করতে পারেন

  • দশমিক বিন্দুর বাটন, তবে একই সংখ্যায় দুবার বিন্দু বসতে না দেওয়ার শর্ত লিখতে হবে
  • কীবোর্ড থেকে সংখ্যা চাপার সুবিধা, এর জন্য KeyBinding ব্যবহার করা ভালো
  • আগের হিসাবের তালিকা দেখানোর জন্য একটি ছোট JTextArea
  • শতকরা হিসাব ও চিহ্ন বদলানোর বাটন

Swing না JavaFX, কোনটি দিয়ে শুরু করবেন

ডেস্কটপ অ্যাপ বানানোর জন্য জাভাতে দুইটি বড় ব্যবস্থা আছে। একটি Swing, অন্যটি JavaFX। নতুনদের মনে প্রশ্ন আসে কোনটি শেখা উচিত। উত্তরটি নির্ভর করে আপনি কী করতে চান তার উপর, তবে শেখার শুরুতে Swing দিয়ে হাত পাকানোর কিছু স্পষ্ট সুবিধা আছে।

Swing এর সবচেয়ে বড় সুবিধা হলো এটি জাভার সাথেই আসে, আলাদা কিছু নামাতে হয় না। কোড লিখে সরাসরি চালিয়ে দেখা যায়, তাই শেখার পথে বাধা কম। এছাড়া ইন্টারনেটে Swing নিয়ে অসংখ্য উদাহরণ পাওয়া যায়, আর বহু পুরনো প্রতিষ্ঠানের সফটওয়্যার এখনো Swing দিয়েই চলছে, তাই কাজের বাজারেও এর চাহিদা একেবারে শেষ হয়ে যায়নি।

অন্যদিকে JavaFX দেখতে অনেক আধুনিক, এতে নকশা আলাদা ফাইলে রাখা যায় এবং চেহারা বদলানোর সুবিধা বেশি। নতুন বড় প্রজেক্টের জন্য এটিই বেশি উপযোগী। তবে মূল ধারণাগুলো, অর্থাৎ কম্পোনেন্ট, কনটেইনার, লেআউট আর ইভেন্ট, দুই জায়গাতেই প্রায় একই। তাই Swing দিয়ে এই ধারণাগুলো একবার বুঝে নিলে JavaFX এ যাওয়া অনেক সহজ হয়ে যায়।

  • Swing জাভার সাথেই থাকে, তাই শুরু করতে বাড়তি কিছু লাগে না।
  • মূল ধারণাগুলো দুই ব্যবস্থাতেই এক, তাই শেখা নষ্ট হয় না।
  • নতুন বড় প্রজেক্টে JavaFX বেশি উপযোগী, চেহারা বদলানো সহজ।
  • পুরনো সফটওয়্যার রক্ষণাবেক্ষণের কাজে Swing জানা এখনো কাজে লাগে।

নিজে চেষ্টা করে দেখার জন্য কিছু কাজ

কোডটি একবার চালানোর পর নিচের কাজগুলো নিজে যোগ করার চেষ্টা করুন। প্রতিটি কাজ ছোট, কিন্তু এগুলো করতে গিয়ে লেআউট, ইভেন্ট আর অবস্থা মনে রাখার ধারণাগুলো অনেক পরিষ্কার হয়ে যাবে।

  • কীবোর্ড থেকেও যেন অঙ্ক দেওয়া যায় সেই ব্যবস্থা যোগ করুন।
  • শেষ কাজটি বাতিল করার একটি বাটন যোগ করুন।
  • শতকরা হিসাব করার একটি বাটন বসিয়ে দেখুন।
  • আগের হিসাবগুলো একটি তালিকায় জমা রাখার ব্যবস্থা করুন।
  • উইন্ডোটি টেনে বড় করে দেখুন, বাটনগুলো ঠিকভাবে বাড়ছে কি না।
  • বাটনের রং ও লেখার আকার বদলে নিজের পছন্দমতো চেহারা দিন।

চেহারা সুন্দর করার সহজ কিছু উপায়

কাজ ঠিকভাবে হওয়ার পর অ্যাপটির চেহারার দিকে একবার নজর দেওয়া ভালো। ব্যবহারকারী প্রথমে চোখ দিয়েই বিচার করেন, তাই সামান্য যত্নেই অ্যাপটি অনেক পেশাদার দেখাতে পারে। ভালো খবর হলো এর জন্য কঠিন কিছু শিখতে হয় না, কয়েকটি ছোট পরিবর্তনেই বড় তফাত হয়ে যায়।

সবচেয়ে আগে নজর দিন লেখার আকারে। ডিসপ্লের সংখ্যাটি যদি বড় ও স্পষ্ট হয়, তবে ব্যবহার করতে আরাম লাগে। এরপর বাটনগুলোর মাঝে একটু ফাঁকা জায়গা রাখুন, একেবারে গায়ে গায়ে লাগানো বাটন চোখে চাপ তৈরি করে। ডিসপ্লের সংখ্যাটি ডান দিকে সরিয়ে দিলে সেটি আসল ক্যালকুলেটরের মতো দেখায়, কারণ হিসাবের সংখ্যা আমরা ডান দিক থেকেই পড়ি।

রঙের ব্যাপারে একটি সহজ নিয়ম মনে রাখুন, অল্প রঙ ব্যবহার করাই ভালো। সব বাটন একই রঙে রেখে শুধু সমান আর ক্লিয়ার বাটনকে আলাদা রঙ দিলে সেগুলো সহজে চোখে পড়ে। শেষে উইন্ডোটি পর্দার মাঝখানে খোলার ব্যবস্থা করে দিলে অ্যাপটি চালু হওয়ার সাথে সাথেই গোছানো মনে হয়।

  • ডিসপ্লের লেখা বড় ও স্পষ্ট রাখুন, পড়তে আরাম হবে।
  • বাটনের মাঝে সামান্য ফাঁকা জায়গা রাখলে দেখতে ভালো লাগে।
  • ডিসপ্লের সংখ্যা ডান দিকে সরিয়ে দিন, আসল ক্যালকুলেটরের মতো লাগবে।
  • অল্প রঙ ব্যবহার করুন, শুধু গুরুত্বপূর্ণ বাটনকে আলাদা রঙ দিন।
  • উইন্ডোটি পর্দার মাঝখানে খুলুন, শুরুতেই গোছানো দেখাবে।

এই ক্যালকুলেটরটি ছোট হলেও এর ভিতরে ডেস্কটপ অ্যাপ বানানোর প্রায় সব মূল ধারণা রয়েছে। পর্দা সাজানো, ব্যবহারকারীর কাজ ধরা, অবস্থা মনে রাখা আর ভুল সামলানো, এই চারটি কাজ যেকোনো বড় অ্যাপেও একইভাবে করতে হয়। তাই এই প্রজেক্টটি ভালোভাবে বুঝে নিলে পরের ধাপে অনেক বড় কিছু বানানোর সাহস পেয়ে যাবেন।

একটি পরামর্শ দিয়ে শেষ করি। কোডটি শুধু কপি করে চালিয়ে দেখলে মনে থাকবে না। বরং একবার নিজের হাতে লিখুন, মাঝে মাঝে ইচ্ছে করে ভুল করুন, তারপর এরর বার্তা পড়ে সেটি ঠিক করুন। এই অভ্যাসটিই একজন সাধারণ শিক্ষার্থীকে ধীরে ধীরে দক্ষ ডেভেলপারে পরিণত করে।

শেষ কথা

এই প্রজেক্টটি ছোট হলেও এর ভেতরে গ্রাফিক্যাল অ্যাপ বানানোর মূল কাঠামোটি পুরোটাই আছে। লেআউট দিয়ে সাজানো, ইভেন্ট ধরা, অবস্থা মনে রাখা আর ভুল ইনপুট সামলানো, এই চারটি কাজ শিখে গেলে যেকোনো ডেস্কটপ অ্যাপ বানানো আপনার কাছে সহজ মনে হবে।

কোড লেখা শেষ হলে নিজের মতো করে রঙ, ফন্ট আর বাটনের সাজ বদলে দেখুন। আপনি এই ক্যালকুলেটরে কোন বাড়তি সুবিধাটি যোগ করতে চান, টিউমেন্টে জানান। এখন নিজে একটি দশমিক বিন্দুর বাটন যোগ করার চেষ্টা করুন, তাতেই বুঝতে পারবেন শেখাটা কতটা পাকা হয়েছে।

Level 1

আমি নাছিরুল হক। বিশ্বের সর্ববৃহৎ বিজ্ঞান ও প্রযুক্তির সৌশল নেটওয়ার্ক - টেকটিউনস এ আমি 1 সপ্তাহ 5 দিন যাবৎ যুক্ত আছি। টেকটিউনস আমি এ পর্যন্ত 24 টি টিউন ও 3 টি টিউমেন্ট করেছি। টেকটিউনসে আমার 0 ফলোয়ার আছে এবং আমি টেকটিউনসে 2 টিউনারকে ফলো করি।

আমি নাছিরুল হক। প্রোগ্রামিং আর প্রযুক্তি নিয়ে ঘাঁটাঘাঁটি করতে ভালোবাসি। টেকটিউনসে মূলত Java প্রোগ্রামিং নিয়ে ধাপে ধাপে হাতে কলমে টিউটোরিয়াল লিখি — JDK ইনস্টল ও এনভায়রনমেন্ট সেটআপ থেকে শুরু করে IntelliJ IDEA, Exception Handling, OOP, Java Swing ও ফাইল হ্যান্ডলিং পর্যন্ত। এছাড়া স্মার্টফোন, ব্যাটারি ও নেটওয়ার্ক নিয়ে সহজ ভাষায় ব্যাখ্যামূলক...


টিউনস


আরও টিউনস


টিউনারের আরও টিউনস


টিউমেন্টস