// company_products_manager موجود بداخل المجلد Main.java هنا ذكرنا أن الملف
package company_products_manager;
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import com.toedter.calendar.JDateChooser;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
// و بالتالي أصبح إنشاء كائن منه يمثل إنشاء نافذة JFrame يرث من الكلاس Main هنا جعلنا الكلاس
public class Main extends JFrame implements DBInfo, ActionListener {
// هنا قمنا بتعريف جميع الأشياء التي سنضيفها في النافذة
JLabel image, idLabel, nameLabel, priceLabel, dateLabel, searchLabel, moveFastLabel;
JTextField idField, nameField, priceField, searchField;
JButton updateImageButton, insertButton, updateButton, deleteButton ,exitButton,
selectFirstButton, selectNextButton, selectPreviousButton, selectLastButton;
JScrollPane tableScroller;
String currentImagePath = null;
AddNewProductDialog addProductDialog;
// فقط createAndShowGUI() سيقوم الكونستركتور بإستدعاء الدالة Main عند إنشاء كائن من الكلاس
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
// التي ستنشئ النافذة createAndShowGUI() و بالتالي سيتم إستدعاء الدالة Main هنا قمنا بإنشاء كائن من الكلاس
// هنا نضع كود إنشاء النافذة و محتوياتها
private void createAndShowGUI() {
// لجعل محتوى االنافذة يظهر بشكل أجمل Nimbus إلى الـ UIManager هنا قمنا بتغير الـ
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException ex) { }
// هنا قمنا بإنشاء جميع الأشياء التي سنضيفها في النافذة
panel = new JPanel(null);
model = new DefaultTableModel();
table = new JTable(model);
tableScroller = new JScrollPane(table);
idLabel = new JLabel("ID");
nameLabel = new JLabel("Name");
priceLabel = new JLabel("Price");
dateLabel = new JLabel("Date");
searchLabel = new JLabel();
moveFastLabel = new JLabel("Move Fast", JLabel.CENTER);
idField = new JTextField();
nameField = new JTextField();
priceField = new JTextField();
dateField = new JDateChooser();
searchField = new JTextField();
updateImageButton = new JButton("Update Image");
insertButton = new JButton("Add New", new ImageIcon(this.getClass().getResource("/images/insert.png")));
updateButton = new JButton("Update", new ImageIcon(this.getClass().getResource("/images/update.png")));
deleteButton = new JButton("Delete", new ImageIcon(this.getClass().getResource("/images/delete.png")));
searchLabel = new JLabel("Search");
selectFirstButton = new JButton("First", new ImageIcon(this.getClass().getResource("/images/first.png")));
selectLastButton = new JButton("Last", new ImageIcon(this.getClass().getResource("/images/last.png")));
selectNextButton = new JButton("Next", new ImageIcon(this.getClass().getResource("/images/next.png")));
selectPreviousButton = new JButton("Previous", new ImageIcon(this.getClass().getResource("/images/previous.png")));
exitButton = new JButton("Exit", new ImageIcon(this.getClass().getResource("/images/exit.png")));
addProductDialog = new AddNewProductDialog(this, model);
// هنا قمنا بتحديد حجم و مكان كل شيء سيتم إضافته في النافذة
image.setBounds(80, 41, 270, 250);
updateImageButton.setBounds(150, 300, 130, 34);
idLabel.setBounds(20, 355, 50, 40);
idField.setBounds(80, 355, 270, 40);
nameLabel.setBounds(20, 405, 50, 40);
nameField.setBounds(80, 405, 270, 40);
priceLabel.setBounds(20, 455, 50, 40);
priceField.setBounds(80, 455, 270, 40);
dateLabel.setBounds(20, 505, 50, 40);
dateField.setBounds(80, 505, 270, 40);
deleteButton.setBounds(80, 575, 130, 40);
updateButton.setBounds(220, 575, 130, 40);
tableScroller.setBounds(377, 40, 520, 505);
searchField.setBounds(530, 577, 255, 36);
searchLabel.setBounds(460, 575, 115, 40);
insertButton.setBounds(920, 40, 130, 60);
moveFastLabel.setBounds(890, 150, 190, 30);
selectFirstButton.setBounds(920, 200, 130, 40);
selectLastButton.setBounds(920, 250, 130, 40);
selectNextButton.setBounds(920, 300, 130, 40);
selectPreviousButton.setBounds(920, 350, 130, 40);
exitButton.setBounds(920, 575, 130, 40);
// هنا قمنا بتحديد نوع و حجم خط الأشياء التي سيتم إضافتها في النافذة
updateImageButton.setFont(new Font("Arial", Font.BOLD, 14));
idLabel.setFont(new Font("Arial", Font.BOLD, 16));
idField.setFont(new Font("Arial", Font.BOLD, 15));
nameLabel.setFont(new Font("Arial", Font.BOLD, 16));
nameField.setFont(new Font("Arial", Font.BOLD, 15));
priceLabel.setFont(new Font("Arial", Font.BOLD, 16));
priceField.setFont(new Font("Arial", Font.BOLD, 15));
dateLabel.setFont(new Font("Arial", Font.BOLD, 16));
dateField.setFont(new Font("Arial", Font.BOLD, 13));
deleteButton.setFont(new Font("Arial", Font.BOLD, 16));
updateButton.setFont(new Font("Arial", Font.BOLD, 16));
insertButton.setFont(new Font("Arial", Font.BOLD, 16));
searchField.setFont(new Font("Arial", Font.BOLD, 15));
searchLabel.setFont(new Font("Arial", Font.BOLD, 17));
moveFastLabel.setFont(new Font("Arial", Font.BOLD, 22));
selectFirstButton.setFont(new Font("Arial", Font.BOLD, 16));
selectLastButton.setFont(new Font("Arial", Font.BOLD, 16));
selectNextButton.setFont(new Font("Arial", Font.BOLD, 16));
selectPreviousButton.setFont(new Font("Arial", Font.BOLD, 16));
exitButton.setFont(new Font("Arial", Font.BOLD, 16));
// هنا قمنا بإضافة خط أسود حول الصورة و الحقول لإظهار التصميم بشكل أجمل
image.setBorder(BorderFactory.createLineBorder(Color.gray, 1, true));
idField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
nameField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
priceField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
searchField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
// غير قابل للتعديل و جعلنا لون الخلفية رمادي idField هنا جعلنا الرقم الظاهر في الحقل
idField.setEditable(false);
idField.setBackground(new Color(240, 240, 240));
// و إظهار تصميمه بشكل أجمل dateField هنا قمنا بتحديد طريقة ظهور التاريخ في الحقل
dateField.setDateFormatString("yyyy-MM-dd");
dateField.setBackground(Color.gray);
dateField.getCalendarButton().setIcon(new ImageIcon(this.getClass().getResource("/images/calendar.png")));
dateField.getCalendarButton().setBackground(Color.gray);
// و جعلنا لون خلفيته أبيض table هنا قمنا بتعديل بعض خصائص الجدول
table.setColumnSelectionAllowed(false);
table.getParent().setBackground(Color.white);
tableScroller.setViewportView(table);
// table هنا قمنا بتحديد أسماء الأعمدة في الجدول
model.addColumn("Price ($)");
model.addColumn("Date Of Add");
// عند تشغيل البرنامج سيتم إظهار جميع المنتجات المخزنة سابقاً و إظهار معلومات أول منتج فيه
viewProductsInTheTable();
// هنا قلنا أنه عند النقر على أي منتج في الجدول بواسطة الفأرة سيتم عرض جميع معلوماته
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
int index = table.getSelectedRow();
// هنا قلنا أنه عند تحديد منتج في الجدول بواسطة لوحة المفاتيح سيتم عرض جميع معلوماته
table.addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN )
showProduct(table.getSelectedRow());
public void keyTyped(KeyEvent e) { }
public void keyPressed(KeyEvent e) { }
// لإظهار المنتجات التي تطابقت مع البحث فقط search() هنا قلنا أنه عند إدخال أي نص في مربع البحث سيتم إستدعاء الدالة
searchField.addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent e) {
public void keyTyped(KeyEvent e) { }
public void keyPressed(KeyEvent e) { }
// actionPerformed() هنا قلنا أنه عند النقر على أي زر في النافذة سيتم إستدعاء الدالة
updateImageButton.addActionListener(this);
insertButton.addActionListener(this);
updateButton.addActionListener(this);
deleteButton.addActionListener(this);
selectFirstButton.addActionListener(this);
selectLastButton.addActionListener(this);
selectNextButton.addActionListener(this);
selectPreviousButton.addActionListener(this);
exitButton.addActionListener(this);
// panel هنا قمنا بإضافة جميع الأشياء التي قما بتعريفها في الحاوية
panel.add(updateImageButton);
panel.add(tableScroller);
panel.add(moveFastLabel);
panel.add(selectFirstButton);
panel.add(selectLastButton);
panel.add(selectNextButton);
panel.add(selectPreviousButton);
// هنا قمنا بإظهار معلومات أول منتج في الجدول
// المفضل و في حال تم تصيغر النافذة panel هنا قمنا بتحديد حجم الحاوية
panel.setPreferredSize(new Dimension(1070, 640));
panel.setMinimumSize(new Dimension(1070, 640));
// لترتيب الأشياء التي ستوضع فيها. و جعلناها تمثل الحاوية الأساسية في النافذة GridBagLayout هنا قمنا بإنشاء حاوية جديدة تستخدم الـ
setContentPane(new JPanel(new GridBagLayout()));
// التي تحتوي على كل ما أضفناه في النافذة في حاوية النافذة الأساسية و هكذا سيظل محتوى النافذة يظهر في الوسط panel هنا قمنا بإضافة الحاوية
// هنا قمنا بتحديد بعض خصائص النافذة و جعلناها مرئية
setTitle("Company Products Manager");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// و التي سنستخدمها كلما أردنا الإتصال بقاعدة البيانات getConnection() هنا قمنا ببناء الدالة
private Connection getConnection()
// DBInfo معلومات الإتصال بقاعدة البيانات قمنا بجلبها من الإنترفيس
con = DriverManager.getConnection(DBInfo.DB_NAME_WITH_ENCODING, DBInfo.USER, DBInfo.PASSWORD);
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Connection Error", JOptionPane.ERROR_MESSAGE);
// و التي سنقوم باستدعائها كلما تم تحديث أو حذف منتج في الجدول لإظهار جميع المنتجات المتوفرة viewProductsInTheTable() هنا قمنا ببناء الدالة
private void viewProductsInTheTable()
// لتخزين معلومات منتج واحد في كل عنصر فيه productقمنا بإنشاء المصفوفة
ArrayList<Product> product= new ArrayList();
// products هنا قمنا بالإتصال بقاعدة البيانات و بتجهيز الإستعلام الذي سيجلب جميع قيم الجدول
Connection con = getConnection();
String query = "SELECT * FROM products";
// لتخزين نتيجة الإستعلام rs لتنفيذ الإستعلام, و الكائن st هنا قمنا بإنشاء الكائن
// rs هنا قمنا بتنفيذ الإستعلام و تخزين نتيجته في الكائن
st = con.createStatement();
rs = st.executeQuery(query);
// في كل مرة rs لتخزين منتج واحد من المنتجات التي ستكون موجودة في الكائن product هنا قمنا بإنشاء الكائن
// الحلقة التالية ترجع سطر واحد في كل مرة, أي معلومات منتج واحد
// product بيانات المنتج التي سيتم إرجاعها في كل مرة سيتم تخزينها بشكل مؤقت في الكائن
Float.parseFloat(rs.getString("price")),
rs.getString("add_date"),
// productكعنصر واحد في المصفوفة product في الأخير سيتم إضافة الكائن
productList.add(product);
// هنا قمنا بإغلاق الإتصال مع قاعدة البيانات لأننا لم نعد بحاجة إليها
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
// هنا قمنا بمسح جميع أسطر الجدول
// لتخزين سطر واحد في الجدول يتألف من 4 أعمدة في كل مرة row هنا قمنا بإنشاء المصفوفة
Object[] row = new Object[4];
// row في المصفوفة productهنا في كل مرة سيتم تخزين معلومات منتج واحد من المنتجات المخزنة في المصفوفة
for(int i = 0; i<productList.size(); i++)
row[0] = productList.get(i).getId();
row[1] = productList.get(i).getName();
row[2] = productList.get(i).getPrice();
row[3] = productList.get(i).getAddDate();
// كسطر واحد في الجدول row بعدها سيتم إضافة عناصر المصفوفة
// لفحص القيم التي أدخلها المستخدم في الحقول للتأكد من صحتها قبل إضافة المنتج في قاعدة البيانات checkInputs() قمنا ببناء الدالة
private boolean checkInputs()
if( nameField.getText().equals("") || priceField.getText().equals("") || dateField.getDate() == null )
JOptionPane.showMessageDialog(this,
"Product information are not updated because one or more fields are empty",
JOptionPane.ERROR_MESSAGE);
Float.parseFloat(priceField.getText());
catch(NumberFormatException ex) {
// لتعديل حجم أي صورة يختارها المستخدم للمنتج resizeImage() قمنا ببناء الدالة
// لجعله يساوي حجم المكان المخصص لعرض الصورة التي تم إختيارها
// تمثل الصورة التي يجب تعديل حجمها bytes عند إستدعائها يجب تمرير مصفوفة من الـ
// no-image.jpg في حال لم يتم تمرير مصفوفة لها, سترجع صورة معدلة الحجم من الصورة الإفتراضية
private ImageIcon resizeImage(byte[] pic)
// لحفظ الصورة التي سيتم تعديل حجمها myImage قمنا بتعريف الكائن
// myImage في الكائن no-image.jpg سيتم تخزين الصورة pic في حال لم يتم تمرير مصفوفة تمثل صورة مكان البارامتير
myImage = new ImageIcon(this.getClass().getResource("/images/no-image.jpg"));
// myImage تمثل صورة, سيتم تخزين هذه المصفوفة في الكائن bytes في حال تم تمرير مصفوفة من الـ
myImage = new ImageIcon(pic);
// tempImage ثم قمنا بتخزينها بشكل مؤقت في الكائن myImage هنا قمنا بإنشاء صورة معدلة الحجم من الصورة المخزنة في الكائن
Image tempImage = myImage.getImage().getScaledInstance(image.getWidth(), image.getHeight(), Image.SCALE_SMOOTH);
// tempImage في الأخير قمنا بإرجاع الصورة المعدلة الحجم في الكائن
return new ImageIcon(tempImage);
// لجعل المستخدم قادر على تحديث صورة المنتج من حاسوبه updateImage() قمنا ببناء الدالة
// updateImage سيتم إستدعاء هذه الدالة عندما يقوم المستخدم بالنقر على الزر
private void updateImage()
// و الذي سيمثل نافذة منبثقة لإختيار صورة من الجهاز JFileChooser هنا قمنا بإنشاء كائن من الكلاس
JFileChooser file = new JFileChooser();
file.setCurrentDirectory(new File(System.getProperty("user.home")));
// هنا قمنا بتحديد نوع الصور التي يمكنك للمستخدم إختيارها من جهازه
FileNameExtensionFilter filter = new FileNameExtensionFilter("Select a .JPG .PNG .GIF image", "jpg", "png", "gif");
file.setFileFilter(filter);
// هنا قمنا بإظهار النافذة و تخزين قيمة الزر الذي تم النقر عليه و أدى إلى إغلاق النافذة
int result = file.showOpenDialog(this);
// سيتم تعديل حجمها ليوافق حجم المربع, ثم ستوضع فيه Open بعد إختيار الصورة, إذا قام المستخدم بالنقر على الزر
// update لإرسالها لاحقاَ عند النقر على زر التحديث currentImagePath و سيتم حفظ مسار الصورة التي تم اختيارها في المتغير
if(result == JFileChooser.APPROVE_OPTION)
byte[] selectedImage = Files.readAllBytes(file.getSelectedFile().toPath());
image.setIcon(resizeImage(selectedImage));
currentImagePath = file.getSelectedFile().toPath().toString();
image.setIcon(resizeImage(null));
// لإظهار النافذة التي تسمح بإدخال منتج جديد عندما يتم إستدعاءها addNewProduct() قمنا ببناء الدالة
private void addNewProduct()
// قمنا ببناء هذه الدالة لتحديث معلومات المنتج
private void updateProduct()
// إذا تم التشييك على الحقول و كان لا يوجد أي خطأ أو نقص في المعلومات المطلوب إدخالها
// سيتم تحديث معلومات المنتج في قاعدة البيانات و في الجدول أيضاً
if(checkInputs() && idField.getText() != null)
if(currentImagePath != null)
InputStream img = new FileInputStream(new File(currentImagePath));
String query = "UPDATE products SET name = ?, price = ?, add_date = ?, image = ? WHERE id = ?";
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, nameField.getText());
ps.setString(2, priceField.getText());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String addDate = dateFormat.format(dateField.getDate());
ps.setString(3, addDate);
ps.setInt(5, Integer.parseInt(idField.getText()));
viewProductsInTheTable();
JOptionPane.showMessageDialog(this, "Product information has been successfully updated");
catch(HeadlessException | FileNotFoundException | NumberFormatException | SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
String query = "UPDATE products SET name = ?, price = ?, add_date = ? WHERE id = ?";
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, nameField.getText());
ps.setString(2, priceField.getText());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String addDate = dateFormat.format(dateField.getDate());
ps.setString(3, addDate);
ps.setInt(4, Integer.parseInt(idField.getText()));
viewProductsInTheTable();
JOptionPane.showMessageDialog(this, "Product information are successfuly updated");
catch(HeadlessException | NumberFormatException | SQLException ex){
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
// لتخزين جميع المعلومات المتوفرة حول المنتجات في قاعدة البيانات getProductList() قمنا ببناء الدالة
private ArrayList<Product> getProductList()
ArrayList<Product> product= new ArrayList();
Connection con = getConnection();
String query = "SELECT * FROM products";
st = con.createStatement();
rs = st.executeQuery(query);
Float.parseFloat(rs.getString("price")),
rs.getString("add_date"),
productList.add(product);
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
// و التي سنقوم باستدعائها كلما تم تحديد منتج جديد في الجدول showProduct() هنا قمنا ببناء الدالة
// الخاص بالمنتج id لعرض جميع المعلومات المتوفرة عنه. لاحظ أنه سيتم جلب جميع المعلومات من قاعدة البيانات بناءاً رقم
private void showProduct(int index)
idField.setText(Integer.toString(getProductList().get(index).getId()));
nameField.setText(getProductList().get(index).getName());
priceField.setText(Float.toString(getProductList().get(index).getPrice()));
Date addDate = new SimpleDateFormat("yyyy-MM-dd").parse((String)getProductList().get(index).getAddDate());
dateField.setDate(addDate);
catch (ParseException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
byte[] theImage = getProductList().get(index).getImage();
image.setIcon(resizeImage(theImage));
// و التي سنقوم باستدعائها كلما تم تحديد منتج جديد في الجدول بهدف مسحه نهائياً deleteProduct() هنا قمنا ببناء الدالة
// مختلف id عند إجراء عملية الحذف, لأن كل منتج يملك رقم id ملاحظة: سيتم الإعتماد على رقم الـ
// بعد أن تتم عملية المسح بنجاح, سيتم تحديد أقرب منتج كان قريب للمنتج الذي تم حذفه, بهدف عرض معلوماته
// في حال تم مسح جميع المنتجات و لم يعد هناك أي عنصر آخر, عندها لن يتم عرض معلومات أي منتج, و لا حتى آخر منتج تم حذفه
private void deleteProduct()
if(table.getSelectedRow() == -1) {
JOptionPane.showMessageDialog(this,
"Please select the product that you want to delete from the table and try again");
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM products WHERE id = ?");
int id = Integer.parseInt(idField.getText());
int nextSelectedRowIndex = table.getSelectedRow();
viewProductsInTheTable();
if(table.getRowCount() == 1) {
table.setRowSelectionInterval(0, 0);
else if(table.getRowCount() > 1 && nextSelectedRowIndex < table.getRowCount()) {
table.setRowSelectionInterval(nextSelectedRowIndex, nextSelectedRowIndex);
showProduct(nextSelectedRowIndex);
else if(table.getRowCount() > 1 && nextSelectedRowIndex == table.getRowCount()) {
table.setRowSelectionInterval(nextSelectedRowIndex, nextSelectedRowIndex);
showProduct(nextSelectedRowIndex);
if(table.getRowCount() == 0) {
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
// لتحديد أول منتج في الجدول ثم عرض معلوماته showFirstProduct() هنا قمنا ببناء الدالة
private void showFirstProduct()
if(table.getRowCount() != 0) {
table.setRowSelectionInterval(0, 0);
// لتحديد آخر منتج في الجدول ثم عرض معلوماته showlastProduct() هنا قمنا ببناء الدالة
private void showLastProduct()
if(table.getRowCount() != 0) {
table.setRowSelectionInterval(table.getRowCount()-1, table.getRowCount()-1);
showProduct(table.getRowCount()-1);
// لتحديد المنتج التالي في الجدول ثم عرض معلوماته showNextProduct() هنا قمنا ببناء الدالة
private void showNextProdut()
if(table.getSelectedRow() < table.getRowCount()-1) {
int currentSelectedRow = table.getSelectedRow()+1;
table.setRowSelectionInterval(currentSelectedRow, currentSelectedRow);
showProduct(currentSelectedRow);
// لتحديد المنتج السابق في الجدول ثم عرض معلوماته showPreviousProduct() هنا قمنا ببناء الدالة
private void showPreviousProduct()
if(table.getSelectedRow() > 0) {
int currentSelectedRow = table.getSelectedRow()-1;
table.setRowSelectionInterval(currentSelectedRow, currentSelectedRow);
showProduct(currentSelectedRow);
// لإظهار المنتجات التي تتطابق مع جملة البحث search() هنا قمنا ببناء الدالة
String keyword = searchField.getText();
TableRowSorter<DefaultTableModel> tr = new TableRowSorter<>(model);
tr.setRowFilter(RowFilter.regexFilter(keyword));
// هذه الدالة يتم إستدعاءها إذا تم النقر على أي زر موجود في النافذة
public void actionPerformed(ActionEvent e) {
// و التي ستظهر نافذة منبثقة لإختيار صورة جديدة للمنتج updateImage() سيتم إستدعاء الدالة updateImageButton إذا تم النقر على الزر
if (e.getSource() == updateImageButton){
// و التي ستظهر نافذة منبثقة لإضافة منتج addNewProduct() سيتم إستدعاء الدالة addNewProduct إذا تم النقر على الزر
else if (e.getSource() == insertButton){
// و التي ستقوم بتحديث بيانات المنتج updateProduct() سيتم إستدعاء الدالة updateButton إذا تم النقر على الزر
else if (e.getSource() == updateButton){
// و التي ستقوم بحذف المنتج نهائياً deleteProduct() سيتم إستدعاء الدالة deleteButton إذا تم النقر على الزر
else if (e.getSource() == deleteButton){
// و التي ستقوم بعرض معلومات أول منتج في الجدول showFirstProduct() سيتم إستدعاء الدالة selectFirstProduct إذا تم النقر على الزر
else if (e.getSource() == selectFirstButton){
// و التي ستقوم بعرض معلومات آخر منتج في الجدول showLastProduct() سيتم إستدعاء الدالة selectLastProduct إذا تم النقر على الزر
else if (e.getSource() == selectLastButton){
// و التي ستقوم بعرض معلومات المنتج التالي في الجدول showNextProduct() سيتم إستدعاء الدالة selectNextButton إذا تم النقر على الزر
else if (e.getSource() == selectNextButton){
// و التي ستقوم بعرض معلومات المنتج التالي في الجدول showPreviousProduct() سيتم إستدعاء الدالة selectPreviousButton إذا تم النقر على الزر
else if (e.getSource() == selectPreviousButton){
// سيتم إغلاق البرنامج exitButton إذا تم النقر على الزر
else if (e.getSource() == exitButton){
// company_products_manager موجود بداخل المجلد Main.java هنا ذكرنا أن الملف
package company_products_manager;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import com.toedter.calendar.JDateChooser;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
// و بالتالي أصبح إنشاء كائن منه يمثل إنشاء نافذة JFrame يرث من الكلاس Main هنا جعلنا الكلاس
public class Main extends JFrame implements DBInfo, ActionListener {
// هنا قمنا بتعريف جميع الأشياء التي سنضيفها في النافذة
JPanel panel;
JLabel image, idLabel, nameLabel, priceLabel, dateLabel, searchLabel, moveFastLabel;
JTextField idField, nameField, priceField, searchField;
JDateChooser dateField;
JButton updateImageButton, insertButton, updateButton, deleteButton ,exitButton,
selectFirstButton, selectNextButton, selectPreviousButton, selectLastButton;
JTable table;
JScrollPane tableScroller;
DefaultTableModel model;
String currentImagePath = null;
AddNewProductDialog addProductDialog;
// فقط createAndShowGUI() سيقوم الكونستركتور بإستدعاء الدالة Main عند إنشاء كائن من الكلاس
public Main() {
createAndShowGUI();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// التي ستنشئ النافذة createAndShowGUI() و بالتالي سيتم إستدعاء الدالة Main هنا قمنا بإنشاء كائن من الكلاس
new Main();
}
});
}
// هنا نضع كود إنشاء النافذة و محتوياتها
private void createAndShowGUI() {
// لجعل محتوى االنافذة يظهر بشكل أجمل Nimbus إلى الـ UIManager هنا قمنا بتغير الـ
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException ex) { }
// هنا قمنا بإنشاء جميع الأشياء التي سنضيفها في النافذة
panel = new JPanel(null);
model = new DefaultTableModel();
table = new JTable(model);
tableScroller = new JScrollPane(table);
image = new JLabel();
idLabel = new JLabel("ID");
nameLabel = new JLabel("Name");
priceLabel = new JLabel("Price");
dateLabel = new JLabel("Date");
searchLabel = new JLabel();
moveFastLabel = new JLabel("Move Fast", JLabel.CENTER);
idField = new JTextField();
nameField = new JTextField();
priceField = new JTextField();
dateField = new JDateChooser();
searchField = new JTextField();
updateImageButton = new JButton("Update Image");
insertButton = new JButton("Add New", new ImageIcon(this.getClass().getResource("/images/insert.png")));
updateButton = new JButton("Update", new ImageIcon(this.getClass().getResource("/images/update.png")));
deleteButton = new JButton("Delete", new ImageIcon(this.getClass().getResource("/images/delete.png")));
searchLabel = new JLabel("Search");
selectFirstButton = new JButton("First", new ImageIcon(this.getClass().getResource("/images/first.png")));
selectLastButton = new JButton("Last", new ImageIcon(this.getClass().getResource("/images/last.png")));
selectNextButton = new JButton("Next", new ImageIcon(this.getClass().getResource("/images/next.png")));
selectPreviousButton = new JButton("Previous", new ImageIcon(this.getClass().getResource("/images/previous.png")));
exitButton = new JButton("Exit", new ImageIcon(this.getClass().getResource("/images/exit.png")));
addProductDialog = new AddNewProductDialog(this, model);
// هنا قمنا بتحديد حجم و مكان كل شيء سيتم إضافته في النافذة
image.setBounds(80, 41, 270, 250);
updateImageButton.setBounds(150, 300, 130, 34);
idLabel.setBounds(20, 355, 50, 40);
idField.setBounds(80, 355, 270, 40);
nameLabel.setBounds(20, 405, 50, 40);
nameField.setBounds(80, 405, 270, 40);
priceLabel.setBounds(20, 455, 50, 40);
priceField.setBounds(80, 455, 270, 40);
dateLabel.setBounds(20, 505, 50, 40);
dateField.setBounds(80, 505, 270, 40);
deleteButton.setBounds(80, 575, 130, 40);
updateButton.setBounds(220, 575, 130, 40);
tableScroller.setBounds(377, 40, 520, 505);
searchField.setBounds(530, 577, 255, 36);
searchLabel.setBounds(460, 575, 115, 40);
insertButton.setBounds(920, 40, 130, 60);
moveFastLabel.setBounds(890, 150, 190, 30);
selectFirstButton.setBounds(920, 200, 130, 40);
selectLastButton.setBounds(920, 250, 130, 40);
selectNextButton.setBounds(920, 300, 130, 40);
selectPreviousButton.setBounds(920, 350, 130, 40);
exitButton.setBounds(920, 575, 130, 40);
// هنا قمنا بتحديد نوع و حجم خط الأشياء التي سيتم إضافتها في النافذة
updateImageButton.setFont(new Font("Arial", Font.BOLD, 14));
idLabel.setFont(new Font("Arial", Font.BOLD, 16));
idField.setFont(new Font("Arial", Font.BOLD, 15));
nameLabel.setFont(new Font("Arial", Font.BOLD, 16));
nameField.setFont(new Font("Arial", Font.BOLD, 15));
priceLabel.setFont(new Font("Arial", Font.BOLD, 16));
priceField.setFont(new Font("Arial", Font.BOLD, 15));
dateLabel.setFont(new Font("Arial", Font.BOLD, 16));
dateField.setFont(new Font("Arial", Font.BOLD, 13));
deleteButton.setFont(new Font("Arial", Font.BOLD, 16));
updateButton.setFont(new Font("Arial", Font.BOLD, 16));
insertButton.setFont(new Font("Arial", Font.BOLD, 16));
searchField.setFont(new Font("Arial", Font.BOLD, 15));
searchLabel.setFont(new Font("Arial", Font.BOLD, 17));
moveFastLabel.setFont(new Font("Arial", Font.BOLD, 22));
selectFirstButton.setFont(new Font("Arial", Font.BOLD, 16));
selectLastButton.setFont(new Font("Arial", Font.BOLD, 16));
selectNextButton.setFont(new Font("Arial", Font.BOLD, 16));
selectPreviousButton.setFont(new Font("Arial", Font.BOLD, 16));
exitButton.setFont(new Font("Arial", Font.BOLD, 16));
// هنا قمنا بإضافة خط أسود حول الصورة و الحقول لإظهار التصميم بشكل أجمل
image.setBorder(BorderFactory.createLineBorder(Color.gray, 1, true));
idField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
nameField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
priceField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
searchField.setBorder(BorderFactory.createLineBorder(Color.gray, 2, true));
// غير قابل للتعديل و جعلنا لون الخلفية رمادي idField هنا جعلنا الرقم الظاهر في الحقل
idField.setEditable(false);
idField.setBackground(new Color(240, 240, 240));
// و إظهار تصميمه بشكل أجمل dateField هنا قمنا بتحديد طريقة ظهور التاريخ في الحقل
dateField.setDateFormatString("yyyy-MM-dd");
dateField.setBackground(Color.gray);
dateField.getCalendarButton().setIcon(new ImageIcon(this.getClass().getResource("/images/calendar.png")));
dateField.getCalendarButton().setBackground(Color.gray);
// و جعلنا لون خلفيته أبيض table هنا قمنا بتعديل بعض خصائص الجدول
table.setColumnSelectionAllowed(false);
table.getParent().setBackground(Color.white);
tableScroller.setViewportView(table);
// table هنا قمنا بتحديد أسماء الأعمدة في الجدول
model.addColumn("ID");
model.addColumn("Name");
model.addColumn("Price ($)");
model.addColumn("Date Of Add");
// عند تشغيل البرنامج سيتم إظهار جميع المنتجات المخزنة سابقاً و إظهار معلومات أول منتج فيه
try {
viewProductsInTheTable();
}
catch(Exception e) { }
// هنا قلنا أنه عند النقر على أي منتج في الجدول بواسطة الفأرة سيتم عرض جميع معلوماته
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent evt) {
int index = table.getSelectedRow();
showProduct(index);
currentImagePath = null;
}
});
// هنا قلنا أنه عند تحديد منتج في الجدول بواسطة لوحة المفاتيح سيتم عرض جميع معلوماته
table.addKeyListener(new KeyListener() {
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN )
showProduct(table.getSelectedRow());
}
@Override
public void keyTyped(KeyEvent e) { }
@Override
public void keyPressed(KeyEvent e) { }
});
// لإظهار المنتجات التي تطابقت مع البحث فقط search() هنا قلنا أنه عند إدخال أي نص في مربع البحث سيتم إستدعاء الدالة
searchField.addKeyListener(new KeyListener() {
@Override
public void keyReleased(KeyEvent e) {
search();
}
@Override
public void keyTyped(KeyEvent e) { }
@Override
public void keyPressed(KeyEvent e) { }
});
// actionPerformed() هنا قلنا أنه عند النقر على أي زر في النافذة سيتم إستدعاء الدالة
updateImageButton.addActionListener(this);
insertButton.addActionListener(this);
updateButton.addActionListener(this);
deleteButton.addActionListener(this);
selectFirstButton.addActionListener(this);
selectLastButton.addActionListener(this);
selectNextButton.addActionListener(this);
selectPreviousButton.addActionListener(this);
exitButton.addActionListener(this);
// panel هنا قمنا بإضافة جميع الأشياء التي قما بتعريفها في الحاوية
panel.add(image);
panel.add(updateImageButton);
panel.add(idLabel);
panel.add(idField);
panel.add(idField);
panel.add(nameLabel);
panel.add(nameField);
panel.add(priceLabel);
panel.add(priceField);
panel.add(dateLabel);
panel.add(dateField);
panel.add(insertButton);
panel.add(updateButton);
panel.add(deleteButton);
panel.add(tableScroller);
panel.add(searchField);
panel.add(searchLabel);
panel.add(moveFastLabel);
panel.add(selectFirstButton);
panel.add(selectLastButton);
panel.add(selectNextButton);
panel.add(selectPreviousButton);
panel.add(exitButton);
// هنا قمنا بإظهار معلومات أول منتج في الجدول
showFirstProduct();
// المفضل و في حال تم تصيغر النافذة panel هنا قمنا بتحديد حجم الحاوية
panel.setPreferredSize(new Dimension(1070, 640));
panel.setMinimumSize(new Dimension(1070, 640));
// لترتيب الأشياء التي ستوضع فيها. و جعلناها تمثل الحاوية الأساسية في النافذة GridBagLayout هنا قمنا بإنشاء حاوية جديدة تستخدم الـ
setContentPane(new JPanel(new GridBagLayout()));
// التي تحتوي على كل ما أضفناه في النافذة في حاوية النافذة الأساسية و هكذا سيظل محتوى النافذة يظهر في الوسط panel هنا قمنا بإضافة الحاوية
add(panel);
// هنا قمنا بتحديد بعض خصائص النافذة و جعلناها مرئية
setTitle("Company Products Manager");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
// و التي سنستخدمها كلما أردنا الإتصال بقاعدة البيانات getConnection() هنا قمنا ببناء الدالة
private Connection getConnection()
{
Connection con;
try {
// DBInfo معلومات الإتصال بقاعدة البيانات قمنا بجلبها من الإنترفيس
con = DriverManager.getConnection(DBInfo.DB_NAME_WITH_ENCODING, DBInfo.USER, DBInfo.PASSWORD);
return con;
}
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Connection Error", JOptionPane.ERROR_MESSAGE);
return null;
}
}
// و التي سنقوم باستدعائها كلما تم تحديث أو حذف منتج في الجدول لإظهار جميع المنتجات المتوفرة viewProductsInTheTable() هنا قمنا ببناء الدالة
private void viewProductsInTheTable()
{
// لتخزين معلومات منتج واحد في كل عنصر فيه productقمنا بإنشاء المصفوفة
ArrayList<Product> product= new ArrayList();
// products هنا قمنا بالإتصال بقاعدة البيانات و بتجهيز الإستعلام الذي سيجلب جميع قيم الجدول
Connection con = getConnection();
String query = "SELECT * FROM products";
// لتخزين نتيجة الإستعلام rs لتنفيذ الإستعلام, و الكائن st هنا قمنا بإنشاء الكائن
Statement st;
ResultSet rs;
try {
// rs هنا قمنا بتنفيذ الإستعلام و تخزين نتيجته في الكائن
st = con.createStatement();
rs = st.executeQuery(query);
// في كل مرة rs لتخزين منتج واحد من المنتجات التي ستكون موجودة في الكائن product هنا قمنا بإنشاء الكائن
Product product;
// الحلقة التالية ترجع سطر واحد في كل مرة, أي معلومات منتج واحد
while(rs.next())
{
// product بيانات المنتج التي سيتم إرجاعها في كل مرة سيتم تخزينها بشكل مؤقت في الكائن
product = new Product(
rs.getInt("id"),
rs.getString("name"),
Float.parseFloat(rs.getString("price")),
rs.getString("add_date"),
rs.getBytes("image")
);
// productكعنصر واحد في المصفوفة product في الأخير سيتم إضافة الكائن
productList.add(product);
}
// هنا قمنا بإغلاق الإتصال مع قاعدة البيانات لأننا لم نعد بحاجة إليها
con.close();
}
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
// هنا قمنا بمسح جميع أسطر الجدول
model.setRowCount(0);
// لتخزين سطر واحد في الجدول يتألف من 4 أعمدة في كل مرة row هنا قمنا بإنشاء المصفوفة
Object[] row = new Object[4];
// row في المصفوفة productهنا في كل مرة سيتم تخزين معلومات منتج واحد من المنتجات المخزنة في المصفوفة
for(int i = 0; i<productList.size(); i++)
{
row[0] = productList.get(i).getId();
row[1] = productList.get(i).getName();
row[2] = productList.get(i).getPrice();
row[3] = productList.get(i).getAddDate();
// كسطر واحد في الجدول row بعدها سيتم إضافة عناصر المصفوفة
model.addRow(row);
}
}
// لفحص القيم التي أدخلها المستخدم في الحقول للتأكد من صحتها قبل إضافة المنتج في قاعدة البيانات checkInputs() قمنا ببناء الدالة
private boolean checkInputs()
{
if( nameField.getText().equals("") || priceField.getText().equals("") || dateField.getDate() == null )
{
JOptionPane.showMessageDialog(this,
"Product information are not updated because one or more fields are empty",
"Error",
JOptionPane.ERROR_MESSAGE);
return false;
}
else {
try {
Float.parseFloat(priceField.getText());
return true;
}
catch(NumberFormatException ex) {
return false;
}
}
}
// لتعديل حجم أي صورة يختارها المستخدم للمنتج resizeImage() قمنا ببناء الدالة
// لجعله يساوي حجم المكان المخصص لعرض الصورة التي تم إختيارها
// تمثل الصورة التي يجب تعديل حجمها bytes عند إستدعائها يجب تمرير مصفوفة من الـ
// no-image.jpg في حال لم يتم تمرير مصفوفة لها, سترجع صورة معدلة الحجم من الصورة الإفتراضية
private ImageIcon resizeImage(byte[] pic)
{
// لحفظ الصورة التي سيتم تعديل حجمها myImage قمنا بتعريف الكائن
ImageIcon myImage;
// myImage في الكائن no-image.jpg سيتم تخزين الصورة pic في حال لم يتم تمرير مصفوفة تمثل صورة مكان البارامتير
if(pic == null)
myImage = new ImageIcon(this.getClass().getResource("/images/no-image.jpg"));
// myImage تمثل صورة, سيتم تخزين هذه المصفوفة في الكائن bytes في حال تم تمرير مصفوفة من الـ
else
myImage = new ImageIcon(pic);
// tempImage ثم قمنا بتخزينها بشكل مؤقت في الكائن myImage هنا قمنا بإنشاء صورة معدلة الحجم من الصورة المخزنة في الكائن
Image tempImage = myImage.getImage().getScaledInstance(image.getWidth(), image.getHeight(), Image.SCALE_SMOOTH);
// tempImage في الأخير قمنا بإرجاع الصورة المعدلة الحجم في الكائن
return new ImageIcon(tempImage);
}
// لجعل المستخدم قادر على تحديث صورة المنتج من حاسوبه updateImage() قمنا ببناء الدالة
// updateImage سيتم إستدعاء هذه الدالة عندما يقوم المستخدم بالنقر على الزر
private void updateImage()
{
// و الذي سيمثل نافذة منبثقة لإختيار صورة من الجهاز JFileChooser هنا قمنا بإنشاء كائن من الكلاس
JFileChooser file = new JFileChooser();
file.setCurrentDirectory(new File(System.getProperty("user.home")));
// هنا قمنا بتحديد نوع الصور التي يمكنك للمستخدم إختيارها من جهازه
FileNameExtensionFilter filter = new FileNameExtensionFilter("Select a .JPG .PNG .GIF image", "jpg", "png", "gif");
file.setFileFilter(filter);
// هنا قمنا بإظهار النافذة و تخزين قيمة الزر الذي تم النقر عليه و أدى إلى إغلاق النافذة
int result = file.showOpenDialog(this);
// سيتم تعديل حجمها ليوافق حجم المربع, ثم ستوضع فيه Open بعد إختيار الصورة, إذا قام المستخدم بالنقر على الزر
// update لإرسالها لاحقاَ عند النقر على زر التحديث currentImagePath و سيتم حفظ مسار الصورة التي تم اختيارها في المتغير
if(result == JFileChooser.APPROVE_OPTION)
{
try{
byte[] selectedImage = Files.readAllBytes(file.getSelectedFile().toPath());
image.setIcon(resizeImage(selectedImage));
currentImagePath = file.getSelectedFile().toPath().toString();
}
catch(IOException ex) {
image.setIcon(resizeImage(null));
}
}
}
// لإظهار النافذة التي تسمح بإدخال منتج جديد عندما يتم إستدعاءها addNewProduct() قمنا ببناء الدالة
private void addNewProduct()
{
addProductDialog.show();
}
// قمنا ببناء هذه الدالة لتحديث معلومات المنتج
private void updateProduct()
{
// إذا تم التشييك على الحقول و كان لا يوجد أي خطأ أو نقص في المعلومات المطلوب إدخالها
// سيتم تحديث معلومات المنتج في قاعدة البيانات و في الجدول أيضاً
if(checkInputs() && idField.getText() != null)
{
if(currentImagePath != null)
{
try {
InputStream img = new FileInputStream(new File(currentImagePath));
String query = "UPDATE products SET name = ?, price = ?, add_date = ?, image = ? WHERE id = ?";
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, nameField.getText());
ps.setString(2, priceField.getText());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String addDate = dateFormat.format(dateField.getDate());
ps.setString(3, addDate);
ps.setBlob(4, img);
ps.setInt(5, Integer.parseInt(idField.getText()));
ps.executeUpdate();
con.close();
viewProductsInTheTable();
JOptionPane.showMessageDialog(this, "Product information has been successfully updated");
}
catch(HeadlessException | FileNotFoundException | NumberFormatException | SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
else
{
try {
String query = "UPDATE products SET name = ?, price = ?, add_date = ? WHERE id = ?";
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, nameField.getText());
ps.setString(2, priceField.getText());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String addDate = dateFormat.format(dateField.getDate());
ps.setString(3, addDate);
ps.setInt(4, Integer.parseInt(idField.getText()));
ps.executeUpdate();
con.close();
viewProductsInTheTable();
JOptionPane.showMessageDialog(this, "Product information are successfuly updated");
}
catch(HeadlessException | NumberFormatException | SQLException ex){
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
// لتخزين جميع المعلومات المتوفرة حول المنتجات في قاعدة البيانات getProductList() قمنا ببناء الدالة
private ArrayList<Product> getProductList()
{
ArrayList<Product> product= new ArrayList();
Connection con = getConnection();
String query = "SELECT * FROM products";
Statement st;
ResultSet rs;
try {
st = con.createStatement();
rs = st.executeQuery(query);
Product product;
while(rs.next())
{
product = new Product(
rs.getInt("id"),
rs.getString("name"),
Float.parseFloat(rs.getString("price")),
rs.getString("add_date"),
rs.getBytes("image")
);
productList.add(product);
}
con.close();
}
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
return productList;
}
// و التي سنقوم باستدعائها كلما تم تحديد منتج جديد في الجدول showProduct() هنا قمنا ببناء الدالة
// الخاص بالمنتج id لعرض جميع المعلومات المتوفرة عنه. لاحظ أنه سيتم جلب جميع المعلومات من قاعدة البيانات بناءاً رقم
private void showProduct(int index)
{
idField.setText(Integer.toString(getProductList().get(index).getId()));
nameField.setText(getProductList().get(index).getName());
priceField.setText(Float.toString(getProductList().get(index).getPrice()));
try {
Date addDate = new SimpleDateFormat("yyyy-MM-dd").parse((String)getProductList().get(index).getAddDate());
dateField.setDate(addDate);
}
catch (ParseException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
byte[] theImage = getProductList().get(index).getImage();
image.setIcon(resizeImage(theImage));
}
// و التي سنقوم باستدعائها كلما تم تحديد منتج جديد في الجدول بهدف مسحه نهائياً deleteProduct() هنا قمنا ببناء الدالة
// مختلف id عند إجراء عملية الحذف, لأن كل منتج يملك رقم id ملاحظة: سيتم الإعتماد على رقم الـ
// بعد أن تتم عملية المسح بنجاح, سيتم تحديد أقرب منتج كان قريب للمنتج الذي تم حذفه, بهدف عرض معلوماته
// في حال تم مسح جميع المنتجات و لم يعد هناك أي عنصر آخر, عندها لن يتم عرض معلومات أي منتج, و لا حتى آخر منتج تم حذفه
private void deleteProduct()
{
if(table.getSelectedRow() == -1) {
JOptionPane.showMessageDialog(this,
"Please select the product that you want to delete from the table and try again");
}
else {
try {
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM products WHERE id = ?");
int id = Integer.parseInt(idField.getText());
ps.setInt(1, id);
ps.executeUpdate();
con.close();
int nextSelectedRowIndex = table.getSelectedRow();
viewProductsInTheTable();
if(table.getRowCount() == 1) {
table.setRowSelectionInterval(0, 0);
showProduct(0);
}
else if(table.getRowCount() > 1 && nextSelectedRowIndex < table.getRowCount()) {
table.setRowSelectionInterval(nextSelectedRowIndex, nextSelectedRowIndex);
showProduct(nextSelectedRowIndex);
}
else if(table.getRowCount() > 1 && nextSelectedRowIndex == table.getRowCount()) {
nextSelectedRowIndex--;
table.setRowSelectionInterval(nextSelectedRowIndex, nextSelectedRowIndex);
showProduct(nextSelectedRowIndex);
}
if(table.getRowCount() == 0) {
image.setIcon(null);
idField.setText("");
nameField.setText("");
priceField.setText("");
dateField.setDate(null);
}
}
catch (SQLException ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
// لتحديد أول منتج في الجدول ثم عرض معلوماته showFirstProduct() هنا قمنا ببناء الدالة
private void showFirstProduct()
{
if(table.getRowCount() != 0) {
table.setRowSelectionInterval(0, 0);
showProduct(0);
}
}
// لتحديد آخر منتج في الجدول ثم عرض معلوماته showlastProduct() هنا قمنا ببناء الدالة
private void showLastProduct()
{
if(table.getRowCount() != 0) {
table.setRowSelectionInterval(table.getRowCount()-1, table.getRowCount()-1);
showProduct(table.getRowCount()-1);
}
}
// لتحديد المنتج التالي في الجدول ثم عرض معلوماته showNextProduct() هنا قمنا ببناء الدالة
private void showNextProdut()
{
if(table.getSelectedRow() < table.getRowCount()-1) {
int currentSelectedRow = table.getSelectedRow()+1;
table.setRowSelectionInterval(currentSelectedRow, currentSelectedRow);
showProduct(currentSelectedRow);
}
}
// لتحديد المنتج السابق في الجدول ثم عرض معلوماته showPreviousProduct() هنا قمنا ببناء الدالة
private void showPreviousProduct()
{
if(table.getSelectedRow() > 0) {
int currentSelectedRow = table.getSelectedRow()-1;
table.setRowSelectionInterval(currentSelectedRow, currentSelectedRow);
showProduct(currentSelectedRow);
}
}
// لإظهار المنتجات التي تتطابق مع جملة البحث search() هنا قمنا ببناء الدالة
private void search()
{
String keyword = searchField.getText();
TableRowSorter<DefaultTableModel> tr = new TableRowSorter<>(model);
table.setRowSorter(tr);
tr.setRowFilter(RowFilter.regexFilter(keyword));
}
// هذه الدالة يتم إستدعاءها إذا تم النقر على أي زر موجود في النافذة
@Override
public void actionPerformed(ActionEvent e) {
// و التي ستظهر نافذة منبثقة لإختيار صورة جديدة للمنتج updateImage() سيتم إستدعاء الدالة updateImageButton إذا تم النقر على الزر
if (e.getSource() == updateImageButton){
updateImage();
}
// و التي ستظهر نافذة منبثقة لإضافة منتج addNewProduct() سيتم إستدعاء الدالة addNewProduct إذا تم النقر على الزر
else if (e.getSource() == insertButton){
addNewProduct();
}
// و التي ستقوم بتحديث بيانات المنتج updateProduct() سيتم إستدعاء الدالة updateButton إذا تم النقر على الزر
else if (e.getSource() == updateButton){
updateProduct();
}
// و التي ستقوم بحذف المنتج نهائياً deleteProduct() سيتم إستدعاء الدالة deleteButton إذا تم النقر على الزر
else if (e.getSource() == deleteButton){
deleteProduct();
}
// و التي ستقوم بعرض معلومات أول منتج في الجدول showFirstProduct() سيتم إستدعاء الدالة selectFirstProduct إذا تم النقر على الزر
else if (e.getSource() == selectFirstButton){
showFirstProduct();
}
// و التي ستقوم بعرض معلومات آخر منتج في الجدول showLastProduct() سيتم إستدعاء الدالة selectLastProduct إذا تم النقر على الزر
else if (e.getSource() == selectLastButton){
showLastProduct();
}
// و التي ستقوم بعرض معلومات المنتج التالي في الجدول showNextProduct() سيتم إستدعاء الدالة selectNextButton إذا تم النقر على الزر
else if (e.getSource() == selectNextButton){
showNextProdut();
}
// و التي ستقوم بعرض معلومات المنتج التالي في الجدول showPreviousProduct() سيتم إستدعاء الدالة selectPreviousButton إذا تم النقر على الزر
else if (e.getSource() == selectPreviousButton){
showPreviousProduct();
}
// سيتم إغلاق البرنامج exitButton إذا تم النقر على الزر
else if (e.getSource() == exitButton){
System.exit(0);
}
}
}