استفاده از JTable در جاوا – قسمت دوم

استفاده از JTable در جاوا- قسمت دوم

در قسمت قبل نحوه ایجاد JTable در جاوا با استفاده از معرفی نام ستون ها و اطلاعات جدول را گفتم.برای دیدن قسمت قبل به لینک زیر مراجعه کنید:

استفاده از JTable درجاوا- قسمت اول

در این آموزش قصد دارم نحوه ایجاد جدول با استفاده از یک Table Model را شرح دهم.

همانطور که در قسمت قبلی شرح داده شد،به دو صورت می توان اطلاعات یک جدول را به JTable معرفی کرد. روش اول که استفاده آرایه ها بود توضیح داده شد. روش بعدی استفاده از Table Model است. در این روش باید کلاسی ایجاد کنیم که از کلاس AbstractTableModel ارث بری کند. و یک Object از این کلاس را به عنوان آرگمان ورودی به متد سازنده JTable دهیم.

کلاس AbstractTableModel یک کلاس Abstract است که دارای ۳ متد Abstract است که باید توسط ما پیاده سازی شود. این متد ها عبارتند از:

  • public int getRowCount()
  • public int getColumnCount()
  • public Object getValueAt(int rowIndex, int columnIndex)

 

برای ایجاد TableModel پیاده سازی این ۳ متد الزامی است. در این روش هم باید یک آرایه برای نام ستون ها و یک آرایه دو بعدی برای اطلاعات جدول تعریف کنیم و در سه متد گفته شده از آنها استفاده کنیم. پس کدهای برنامه تا اینجا شیبه کد زیر است:

Public class TableModel extends AbstractTableModel {

    private String[] col = new String[]{
        "col-0", "col-1", "col-2", "col-3"
    }; //
    private String[][] data = new String[][]{
        {"val-00", "val-01", "val-02", "val-03"},
        {"val-10", "val-11", "val-12", "val-13"},
        {"val-20", "val-21", "val-22", "val-23"},
        {"val-30", "val-31", "val-32", "val-33"}
    };

    @Override
    public int getRowCount() {
    }

    @Override
    public int getColumnCount() {
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
    }
}

حال وقت آن است که بدنه ی متد ها را پیاده سازی کنیم.

متد getRowCount تعداد سطر های جدول را بر می گرداند، پس باید از تعداد سطر های آرایه data استفاده کنیم. به شکل زیر:

    @Override
    public int getRowCount() {
        return data.length;
    }

متد getColumnCount تعداد ستون های جدول را بر می گرداند، پسمی توانیم از طول آرایه col استفاده کنیم. به این شکل:

    @Override
    public int getColumnCount() {
        return col.length;
    }

متد دیگری به نام getColumnName وجود دارد که برای شاناساندن نام ستون ها به JTable استفاده می شود. وجود این متد الزامی نیست ولی اگر آن را پیاده سازی نکنیم نام ستون ها یا حروف a  تا Z یا ترکیبی از آنها مشخص می شود. این یعنی اگر بخواهیم که نام ستون ها را خودمان تعیین کنیم باید این متد را که در کلاس AbstractTableModel قرار دارد Override کنیم.

شکل کلی این متد به این صورت است:

 public String getColumnName(int column)

برای پیاده سازی آن باید نام ستون خواسته شده را برگردانیم. به شکل زیر:

    @Override
    public String getColumnName(int column) {
        return col[column];
    }

متد getValueAt آدرس یک سلول از جدول را می گیرد و اطلاعات آن سلول را به صورت یک Object بر می گرداند. این Object میتواند هر نوعی باشد. این Object حتی میتواند از نوع کامپوننت ها باشد. اطلاعات ما در این مثال فقط از نوع String است. پس این متد را میتوانیم اینگونه پیاده سازی کینم:

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return data[rowIndex][columnIndex];
    }

تا اینجا کارهایی که برای ساخت کلاس TableModel الزامی بود را انجام دادیم. البته میتوانیم متد های دیگری را هم که در کلاس AbstractTableModel وجود دارند را بسته به نیازمان Override کنیم. مثلا متد setValueAt یا متد getColumnClass یا متد isCellEditable که قصد دارم آموزش این متد ها را در یک قسمت به صورت جداگانه قرار دهم.

حال برای اینکه بتوانیم از کلاس TableModel استفاده کنیم باید یک JTable ایجاد کنیم و یک Object از نوع کلاس TableModel را به سازنده ی سازنده ی JTable پاس دهیم. به صورت زیر:

TableModel tableModel = new TableModel();
JTable table = new JTable(tableModel);

و در ادامه باید باید table را به Jframe اضافه کنیم(add کنیم) و JFrame را نمایش دهیم. که این کار در قسمت قبل توضیح داده شد.

کد کامل برنامه در زیر آورده شده است:

کلاس TableModel

import javax.swing.table.AbstractTableModel;

public class TableModel extends AbstractTableModel {

    private String[] col = new String[]{"col-0", "col-1", "col-2", "col-3"};
    private String[][] data = new String[][]{{"val-00", "val-01", "val-02", "val-03"}, {"val-10", "val-11", "val-12", "val-13"}, {"val-20", "val-21", "val-22", "val-23"}, {"val-30", "val-31", "val-32", "val-33"}};

    @Override
    public int getRowCount() {
        return data.length;
    }

    @Override
    public int getColumnCount() {
        return col.length;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return data[rowIndex][columnIndex];
    }

    @Override
    public String getColumnName(int column) {
        return col[column];
    }
}

کلاس TableModelDemo برای استفاده از TableModel

import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class TableModelDemo extends JFrame {

    private JTable table;
    private TableModel tableModel;

    public TableModelDemo() {
        super("Table Model Demo");
        setSize(470, 470);
        setLayout(new FlowLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        TableModel tableModel = new TableModel();
        JTable table = new JTable(tableModel);
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
    }

    public static void main(String args[]) {
        TableModelDemo tableModelDemo = new TableModelDemo();
        tableModelDemo.setVisible(true);
    }
}

استفاده از JTable درجاوا- قسمت دوم

 

 

این برنامه دقیقا شبیه به برنامه ی قسمت قبل آموزش استفاده از JTable بود با این تفاوت که از یک TableModel برای مشخص کردن اطلاعات جدول استفاده شده بود. به امید خدا در قسمت بعدی آموزش به بررسی متد های دیگر کلاس AbstractTableModel و امکانات دیگر آن و نحوه اضافه کردن ، حذف کردن و آپدیت کردن یک سطر از جدول در زمان اجرای برنامه خواهم پرداخت.

لطفا نظرات و انتقادات خود را در مورد کیفیت آموزش ها بیان بفرمایید تا در قسمت های بعد آموزش، از آنها در بهتر کردن کیفیت آموزش ها استفاده کنم.

همچنین اگر موضوع خاصی برای آموزش های بعدی (بعد از اتمام مبحث JTable) در نظر دارید در قسمت نظرات بیان بفرمایید تا بعد از اتمام مبحث JTable به آموزش آن مبحث بپردازم. موفق و سربلند باشید

امید فرجی

سلام، امید فرجی هستم از همدان. بیشتر از 7 سال میشه که در حوضه برنامه نویسی جاوا و اندروید فعالیت دارم و در این مدت پروژه های تجاری مختلفی انجام دادم. همچنین از سال 91 سایت آموزش تخصصی جاوا را راه اندازی کردم و در خدمت شما هستم. امیدوارم مفید بوده باشم. برای سفارش پروژه هاتون باهام تماس بگیرید.

شما ممکن است این را هم بپسندید

۳۹ پاسخ‌ها

  1. سجاد گفت:

    با سلام

    آقا امید، واقعا خیلی عالی بودن، ما که خیلی لذت بردیم.

    چرا ادامه نمیدین آخه؟

    ما منتظریما.

    راستی، من یه مشکلی داشتم با این جدول که خیلی جدیه، تو سایت برنامه نویس پستش کردم، بخش نگارش استاندارد جاوا

    موضوع: حذف سطر جدولی که سطر و ستون آن از طریق فایل متنی معین میشود..

    ببین راه حلی براش داری؟

    دعات میکنم

    یاحق

    • امید فرجی گفت:

      خواهش میکنم

      راستش سرم فوق العاده شلوغه، و خب استقبال دوستان زیاد نیست که اصرار زیادی برای ادامه آموزش ها به صورت منظم داشته باشم.

      ولی حتما در نظر دارم که از یک ماه دیگه که سرم خلوت شد ، انواع مطالب آموزشی به صورت سریالی آماده کنم و روی سایت قرار بدم. امیدوارم استقبال بشه یا دوستان حداقل نظرشونودر مورد اموزش ها بگن.

      واسه مشکلتم سعی میکنم هر چه سریع تر راهنماییت کنم

      موفق باشی

  2. سلام

    ممنون خیلی عالی بود

    ادامه بدید

  3. علیرضا گفت:

    بهتون تبریک میگم منتظر پرو/زه های اموزشی بعدی شما هستیم

    • امید فرجی گفت:

      ممنونم.
      دو تا آموزش دیگه تقریبا آمادس که امروز یا فردا روی سایت قرارش میدم

  4. حبیب گفت:

    سلام جناب سریعتر بزارید پس فردا امتحان جاوا دارم با تشکر

    • سلام دوست عزیز
      آموزش ها رو قرار دادم.
      فیلم های آموزشی ، بخش پنجم و ششم رو مشاهده بفرمایید.
      یه آموزش دیگه هم داره آماده میشه که پروژه کامل ایجاد یه ماشین حساب گرافیکی هست. به محض آماده شدن روی سایت قرارش خواهد گرفت

  5. fb87 گفت:

    سلام،ممنون از مطالب خوب و مفیدتون….
    من تازه کار با جاوا رو شروع کردم، یه سوال در مورد jtable دارم که ممنون میشم راهنمایی کنید.
    من یه پروژه دارم که توی اون چندتا jtable دارم و میخوام که جدولها اطلاعتشونو از دیتابیس بگیرن، الان به نظر شما من توی این برنامه باید یک کلاس tablemodel داشته باشم؟؟ و برای هرکدوم از جدولها یه تابع توی این کلاس بذارم که data و col رو از دیتابیس پر کنه؟؟ نمیدونم باید چه جور بپرسم، متوجه منظورم شدین؟؟

    • سلام.خواهش میکنم.
      بله باید TableModel داشته باشید. ولی تابع خاصی نمیخواد. میتونید توی کانسترکتور TableModel نام جدول در دیتابیس رو بگیرید و اطلاعات همون جدول رو نمایش بدید.
      کد نگاشت جدول دیتابیس به JTable رو بدون استفاده از TableModel در این لینک نوشتم:
      نگاشت جدول دیتابیس در یک JTable

      شما اگه از TableModel استفاده میکنی کافیه به جز خط آخر کد، همه ی کد ها رو توی کانسترکتور کپی کنی.بقیه TableModel هم طبق آموزش بنویس.
      اگه سوالی بود بفرمایید.
      موفق باشی

  6. fb87 گفت:

    واقعا ممنون……
    من قبلا به همون روشی که شما گفتین با jtable کار کرده بودم ولی با tablemodel نه، یه جایی دیدم که اگه بخوام همزمان با حذف و اضافه کردن به دیتابیسم جدولم هم بروز بشه باید از tablemodel استفاده کنم، درسته؟؟ اگه بدون tablemodel هم میشه اینکارو کرد،میشه بگید چطور؟؟

  7. fb87 گفت:

    حالا من این کاری که شما گفتینو کردم،البته هنوز جواب نگرفتم!! تو قسمت private من اینا رو اضافه کردم:
    private ResultSet rs;
    private Connection c;
    private Statement st;
    Vector data = new Vector();
    Vector columnNames = new Vector();
    یعنی data, columnnames رو اوردم تو قسمت private، بقیه کد رو هم که تو قسمت کانسترکتور کپی کردم، تا اینجا که مشکلی نداره؟؟

    • نه مشکلی نداره.
      ببینید.بهترین راه برای مدیریت JTable استفاده از Model هست. که کدهاتونو لایه بندی میکنه.
      اون کدی که من نوشتمش یه قطعه کده که هر جایی میشه ازش استفاده کرد. چه توی TableMode چه بیرون TableModel.
      همونطور که گفتم، همه چیز دقیقا مثل آموزشه. فقط در کانسترکتور TableModel باید از کدی که توی اون سایت نوشته بودم استفاده کنید.

  8. fb87 گفت:

    ببخشید که من زیاد سوال میپرسم، حالا من تو پروژه م مثلا ۳ تا جدول دارم که هر کدوم اطلاعات یکی از جدولای دیتابیسم رو نمایش میده، یکی اطلاعات دانش اموز، یکی اطلاعات پرسنلی و…. حالا برای هرکدوم از این جدولا باید یه tablemodel بسازم؟؟ یه tablemodel برای نمایش دانش اموزها و یه tablemodel برای پرسنل؟؟

    • خواهش میکنم.
      شما میتونی یه TableModel که تمام کارهای مشترک همه TableModel ها رو داره رو ایجاد کنی، بعد برای هر کدوم از JTable ها یه TableModel بنویسی که از TableModelی که از این TableModelی که امکانات مشترک رو در خودش داشت ارث بری کنه.

  9. fb87 گفت:

    واقعا ممنون، دستتون درد نکنه…… دمتون گرم……
    با tablemodel هم جواب گرفتم، فقط همین سوال اخری که پرسیدمو لطف کنید جواب بدین واقعا ممنون میشم، یعنی برای هرکدوم از جدولا یه tablemodel ؟؟؟؟؟؟

  10. fb87 گفت:

    خیلی ممنون….
    میشه یه آموزش کامل در مورد jtable قرار بدین؟؟ یه سری مسایل مثل کلیک روی جدول، درج و حذف توی جدول و ….

  11. fb87 گفت:

    سلام، آقای فرجی یه سوال توی این تاپیک در مورد کلیک روی جدول پرسیدم، خیلی ممنون میشم اگه شما هم یه نگاه بندازین و اگه ممکنه جواب بدین، خیلی تو این قضیه گیر کردم
    http://barnamenevis.org/showthread.php?414393-%D8%B1%D9%88%DB%8C%D8%AF%D8%A7%D8%AF-click-%D8%B1%D9%88%DB%8C-jtable

  12. fb87 گفت:

    لینکو ندیدین مهندس؟؟؟؟؟؟ خواهش میکنم حداقل شما جواب بدین بدجور کلافه م کرده نمیفهمم چشه

  13. fb87 گفت:

    سلام،فک میکنم اینجا بپرسم زودتر جواب میدین:
    ببینید من یه جدول به همون روش tablemodel ایجاد کردم همونطور که خودتون گفتین، حالا جدولمو روی یه panel قرار دادم
    وقتی این کد رو مینویسم جدول میاد ولی کلیک روی جدول اجرا نمیشه:

    
     BorderLayout borderLayout1 = new BorderLayout();
    jPanel1.add(jTable1, BorderLayout.CENTER);
           jPanel1.setLayout(borderLayout1);
    

    وقتی این دو خط رو جابه جا میکنم یه panel خالی میاد که وقتی روی اون کلیک میکنم رویداد کلیک جدولم اجرا میشه، چرا؟؟؟؟؟؟؟

  14. fb87 گفت:

    ممنون از اینکه جوابمو دادین، گفتم شاید اینجا بیشتر میاین، چشم.

  15. fb87 گفت:

    سلام، ببخشید که من دوباره مزاحم میشم، یه سوال دیگه در مورد jtable دارم:
    چطور میتونم با زدن یه button، یه کلیک رو جدول یا …. یه رویدادی ، اطلاعات جدولمو تغییر بدم، درواقع من میخوام یه جدول داشته باشم که اطلاعات افرادم رو نشون بده بعد با کلیک روی این جدول و دریافت id اون شخص، روی یه جدول دیگه اطلاعات چک هایی که اون طرف صادر کرده رو نشون بده، برای نفر اول اینکارو انجام میدم اما وقتی میخوام چکهای نفر دوم رو نشون بده جدول تغیر نمیکنه، میشه در این مورد هم راهنمایی کنید؟؟

    • سلام. خواهش میکنم دوست عزیز.
      اگه میخوای اصولی کار کنی، باید در TableModel هر JTable متغییر data یا همون اطلاعات جدول رو به صورت Generic تعریف کنی. مثلا یه Vector که نوع داخلش آبجکت هایی از کلاس Person هستند. با این کار اطلاعات هر سطر از JTable داخل یه bean یا یه آبجکت از نوع Person نگهداری میشه و دستتون خیلی بازتر میشه.
      مثلا میتونی آبجکت Personی که در سطر انتخاب شده هست رو به دست بیاری و بدی به یه کلاس تا جدول مربوط به چک ها و غیره رو بر اساس این آبجکت نمایش بده.
      نکتش اینه که هر دفعه باید اطلاعات مربوط به چک ها رو ایجاد کنی و جایگزین اطلاعات قبلی TableModel کنی و با استفاده از متد fireTableDataChanged اطلاعات JTable رو refresh کنی.
      استفاده از Generic معجزه میکنه 🙂

  16. fb87 گفت:

    قسمت اولشو متوجه شدم ولی از اونجا که گفتین “باید هر دفعه اطلاعات مربوط به چک ها رو ایجاد کنی” به بعدشو نفهمیدم!!
    من این کد رو نوشتم:

    
                TableModel_chek tablemodel_chek=new TableModel_chek(id);
                jTbl_chek=new JTable(tablemodel_chek.data,tablemodel_chek.columnNames);
                tablemodel_chek.fireTableDataChanged();
                jTbl_chek .setFont(new Font("B Homa", 0, 13));
                TableColumn column=null;
                for (int i = 0; i < jTbl_chek.getColumnCount(); i++) {
                   column = jTbl_chek.getColumnModel().getColumn(i);
                   column.setMaxWidth(100);       
                }
                ChangeName(jTbl_chek, 0, "کد چک");
                ChangeName(jTbl_chek,1, "نام بانک");
                ChangeName(jTbl_chek,2,"تاریخ");
                ChangeName(jTbl_chek, 3, "حالت ");
                ChangeName(jTbl_chek, 4, "مبلغ");
           
                JScrollPane scrollPane = new JScrollPane(jTbl_chek);
            
                jPnl_chek.setVisible(true);
                jPnl_chek.add(scrollPane);
                jPnl_chek.repaint();
                jPnl_chek.revalidate();
    

    کانسترکتور کلاس TableModel_chek یه آرگومان ورودی داره که در واقع ID اون شخصه که با کلیک روی جدول افراد به دست اومده، که این id رو به این کلاس میفرسم و اطلاعات چک رو برمیگردونه و میخوام با هر بار کلیک روی هر کدوم از سطرهای جدول افراد، جدول چک refresh بشه، ولی این اتفاق نمیفته!! firetable رو درست گذاشتم؟؟

  17. fb87 گفت:

    تا الان فهمیدم که tablemodel مقاددیر جدید رو میگیره ولی این تغییرات روی table اعمال نمیشه!!

  18. fb87 گفت:

    میشه بگید کجاش اشتباهه؟؟ بهتر نیس خودم تمومش کنم؟؟

    • کلا روشت اشتباهه. اگه بخوام اینجوری توضیح بدم که چیکار کنی، باید کل پروژه رو از اول تا آخر توضیح بدم.
      در ضمن، Java Naming و Encapsulation رو هم اصلا رعایت نکردی. در جاوا نامگذاریه متغییر ها با PHP و دیگر زبان ها متفاوته.
      من حدس میزنم شما هنوز یه کمی با OOP مشکل داری.

  19. fb87 گفت:

    خب درسته! من تازه کار با جاوا رو شروع کردم و این اولین برنامه ایه که با جاوا مینویسم…
    پس میشه یه راهنمایی کنید که چطوری جاوا رو درست و اصولی یاد بگیرم؟؟؟
    راستی نظرتون راجع به Jdeveloper چیه؟؟

    • بهترین کار همین کاریه که شما داری انجام میدی. باید تا میتونی پروژه برای خودت تعریف کنی و بنویسی. و هر جا به مشکل برخوردی به کتاب های مرجع مراجعه کنی. و اگه در کتاب مرجع جواب نگرفتی ، در Forum ها برنامه نویسی سوالتو مطرح کنی. در ضمن میتونی پروژه های Open Source رو هم ببینی که چطور اصول رو رعایت کردن ، و تو هم همونطوری عمل کنی.
      البته قبل از همه ی این کارا مطالعه یه سری مقدمات و مطالب در مورد اصول شی گرایی و کلا کد نویسی ضروریه و بهترین منبع برای این مطالعات کتاب های مرجع هست.
      در مورد JDeveloper هم باید بگم شما که هنوز اول کاری بهتره با Netbeans کار کنی بعدا IDE های دیگه رو هم امتحان کنی.
      موفق باشی

  20. fb87 گفت:

    ممنون از راهنماییتون….. سایتتون عالیه و خودتون هم عالی هستین که جواب آدمای بیسوادی مثل منو میدین…..
    بازم ممنون……

  21. fb87 گفت:

    حالا یه سوال اصولی دیگه، من توی دیتابیسم مثلا سه تا جدول دارم به اسم دانش آموز، ثبت نام و گروه آزمایشی، حالا توی پروژه برای هر کدوم از این موجودیت ها یه کلاس ایجاد کردم که توابع set , get رو توی اونها نوشتم، یه کلاسم برای اتصال به دیتابیس نوشتم، حالا به نظر شما برای توابع insert , update,delet, select که مربوط به دیتابیسه برای هرکدوم یه کلاس ایجاد کنم یا این توابع رو توی همون کلاس هایی که برای موجودیت هام ایجاد کردم بنویسم؟؟

    • هیچ کدوم.
      به نظر من بهترین راه اینه که یه کلاس داشته باشی(مثلا به اسم DB) که چند تا متد static داشته باشه(مثلا insert ، update ، delete و …) و این متد ها فقط کارشون اینه که یه Query بگیرن و همه ی کارای اتصال به Database و انجام Query و بستن کانکشن رو انجام بدن. و برای هر Entity هم یه کلاس تعریف کنی (مثلا به اسم StudentDBHelper) و این کلاس ها هم همه هر کدوم متد های insert ، update ، delete و … رو دارند با این تفاوت که این متد ها یه Object از Entityی مورد مورد نظر میگیرن و Query رو میسازن و میدن به متدهای static کلاس DB.
      یه مثال:
      حالا هر جا خواستی یه Student به Database اضافه کنی، کافیه یه Object از کلاس StudentDBHelper ایجاد کنی و به متد indertش یه آبجکت Student بدی تا برای توی دیتابیس بریزتش.
      به این نوع برنامه نویسی برنامه نویسی چند لایه میگن . البته نحوه پیاده سازی لایه ها، بسته به منطق برنامه ی شما میتونه متفاوت باشه.

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *