Java Swing দিয়ে ধাপে ধাপে কাজ করা ক্যালকুলেটর অ্যাপ তৈরি, GridLayout থেকে ActionListener পর্যন্ত সম্পূর্ণ গাইড

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

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

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

যা যা লাগবে

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

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

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

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

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

এডিটরে 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 এ রাখলে ডিসপ্লে সবসময় উপরে থাকবে

ধাপ ৩: 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 মেথডটি চলবে
  • লুপ ব্যবহার করায় নতুন বাটন যোগ করতে চাইলে শুধু অ্যারেতে একটি লেখা বাড়ালেই হবে

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

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

@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 মেথড বাটনের গায়ে লেখা টেক্সটটিই ফেরত দেয়, তাই আলাদা করে আইডি রাখার দরকার হয় না

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

সমান চিহ্নে চাপ দিলে 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
  • শতকরা হিসাব ও চিহ্ন বদলানোর বাটন

শেষ কথা

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

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

Level 0

আমি নাছিরুল হক। বিশ্বের সর্ববৃহৎ বিজ্ঞান ও প্রযুক্তির সৌশল নেটওয়ার্ক - টেকটিউনস এ আমি 15 ঘন্টা 26 মিনিট যাবৎ যুক্ত আছি। টেকটিউনস আমি এ পর্যন্ত 9 টি টিউন ও 0 টি টিউমেন্ট করেছি। টেকটিউনসে আমার 0 ফলোয়ার আছে এবং আমি টেকটিউনসে 0 টিউনারকে ফলো করি।


টিউনস


আরও টিউনস


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


টিউমেন্টস