الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

قراءة صورة

بدأه mr.beshoy في 12 ديسمبر 2009 · 10 رد · 813 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

سلام للجميع

------------------

هنا تم عمل كود بسيط يقرأ صورة و يعرضها عل panel

المشكلة أن هناك بعض الصور لم تعرض بالضبط داخل ال panel (( قد يعُرض جزء منها فى البانل و الاخر خارجها نظراً لكب الإتساع و الإرتفاع ))

رغم أنى واضع شرط أن لو كان إتساع و إرتفاع الصورة أكبر من ال panl ، يرسم طبقاً ل إتساع و ارتفاع ال paenl

ال code :

----------------

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class TestImage extends JFrame {

    private JPanel mainPanel;
    private Box displayPanel;
    private JButton openButton;
    private JFileChooser fileChooser;
    private BufferedImage bufferedImage = null;

    public TestImage() {
        intializeingPanel();
        intializeingButtons();
        fileChooser = new JFileChooser();
        getContentPane().add(mainPanel);
        MyActionListener actionListener = new MyActionListener();
        openButton.addActionListener(actionListener);
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
        }
        TestImage testImage = new TestImage();
        testImage.setDefaultCloseOperation(TestImage.EXIT_ON_CLOSE);
        testImage.setSize(new Dimension(600, 300));
        testImage.setLocationRelativeTo(null);
        testImage.setVisible(true);
        testImage.setExtendedState(MAXIMIZED_BOTH);

    }

    private void intializeingPanel() {
        mainPanel = new JPanel(null);
        mainPanel.setBounds(100, 10, 600, 300);

        displayPanel = Box.createVerticalBox();
        displayPanel.setBounds(350, 150, 500, 300);
        displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
        displayPanel.setOpaque(true);
        displayPanel.setBackground(Color.WHITE);

        mainPanel.add(displayPanel, BorderLayout.CENTER);
    }

    private void intializeingButtons() {
        openButton = new JButton("Open");
        openButton.setBounds(50, 10, 100, 50);
        mainPanel.add(openButton, BorderLayout.NORTH);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        if (bufferedImage.getWidth() > displayPanel.getWidth() || bufferedImage.getHeight() > displayPanel.getHeight()) {
            int imageWidth = displayPanel.getWidth();
            int imageHeight = displayPanel.getHeight();
            g.drawImage(bufferedImage, imageWidth, imageHeight, null);
        }else{
            g.drawImage(bufferedImage, displayPanel.getWidth(), displayPanel.getHeight(), null);
        }
    }

    private class MyActionListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == openButton) {
                int returnValue = fileChooser.showOpenDialog(TestImage.this);
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    File file = fileChooser.getSelectedFile();
                    try {
                        bufferedImage = ImageIO.read(file);
                        repaint();
                    } catch (Exception exception) {
                    }
                }
            }
        }
    }
}

و للعلم البرناج بيطلع nullpointerexception

من لديه طريقة غير هذه يعلمنا بها

شكرا ً

#2
 	mainPanel = new JPanel(null);
................
 	mainPanel.add(displayPanel, BorderLayout.CENTER);

؟؟؟ :blink:

في السطر الأول تحدد أنك لن تستعمل اي layout، ثم في الأخير تضيف الpanel على أساس أنك تستعمل BorderLayout!!!! لا فائدة من إضافة BorderLayout.CENTER.

بما أنك تريد رسم الصورة في displayPanel وليس مباشرة في النافذة JFrame، فيفضل عمل كلاس مستقلة ترث من JPanel ثم تعيد كتابة paintComponent، فلا فائدة من كتابة كود الرسم داخل paint الخاصة بالنافذة

كما أنك يجب أن تتحقق من أن bufferedImage تخالف null، فسواء paint أو paintComponent يتم المناداة عليها عند أول ظهور للنافذة، ووقتها لم يتم اختيار الصورة بعد، لذلك تحصل على NullPointerException

if (bufferedImage.getWidth() > displayPanel.getWidth() || bufferedImage.getHeight() > displayPanel.getHeight()) {
	int imageWidth = displayPanel.getWidth();
	int imageHeight = displayPanel.getHeight();
	g.drawImage(bufferedImage, imageWidth, imageHeight, null);
} else {
	g.drawImage(bufferedImage, displayPanel.getWidth(), displayPanel.getHeight(), null);
}

في هذا الكود، فأنت تمرر نفس القيمة في كلتا الحالتين، أي displayPanel.getWidth() و displayPanel.getHeight()، الفرق الوحيد أنك تخزنهما في متغيرين قبل تمريرهما إلى drawImage في الحالة الأولى، لذلك فما فائدة ال if/else ؟؟؟!!!!!

كما أن الarguments الثاني والثالث يمثلان الإحداثيات، أي x و y، وليس العرض والطول، إذا كنت تريد تحديد هاذين الاخيرين فيجب تمريرهما بعد الإحداثيات. هذا واضح جدا في الjavadoc لو كنت قرأتها

try {
 	bufferedImage = ImageIO.read(file);
 	repaint();
 	} catch (Exception exception) {
 	}

كما أنك تترك الcatch bloc فارغا، مثل الكود في الاعلى وهذا خطأ فادح، لأنك لن تعرف أبدا مصدر الخطأ إذا ما حدث، إذا كنت لا تريد القيام بشيء محدد عند حصول الخطأ، فعلى الأقل قم بطباعة رسالة الخطأ

هذا الكود بعد التعديل.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class TestImage extends JFrame {

	private JPanel mainPanel;
	private DiplayPanel displayPanel;
	private JButton openButton;
	private JFileChooser fileChooser;
	private BufferedImage bufferedImage = null;

	public TestImage() {
		intializeingPanel();
		intializeingButtons();
		fileChooser = new JFileChooser();
		getContentPane().add(mainPanel);
		MyActionListener actionListener = new MyActionListener();
		openButton.addActionListener(actionListener);
	}

	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {}
		TestImage testImage = new TestImage();
		testImage.setDefaultCloseOperation(TestImage.EXIT_ON_CLOSE);
		testImage.setSize(new Dimension(600, 300));
		testImage.setLocationRelativeTo(null);
		testImage.setVisible(true);
		testImage.setExtendedState(MAXIMIZED_BOTH);
	}

	private void intializeingPanel() {
		mainPanel = new JPanel(null);
		displayPanel = new DiplayPanel();
		displayPanel.setBounds(350, 150, 500, 300);
		displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
		displayPanel.setOpaque(true);
		displayPanel.setBackground(Color.WHITE);
		mainPanel.add(displayPanel);
	}

	private void intializeingButtons() {
		openButton = new JButton("Open");
		openButton.setBounds(50, 10, 100, 50);
		mainPanel.add(openButton, BorderLayout.NORTH);
	}

	private class DiplayPanel extends JPanel {

		@Override
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (bufferedImage != null) {
				g.drawImage(bufferedImage, 0, 0, displayPanel.getWidth(), displayPanel.getHeight(), null);
			}
		}
	}

	private class MyActionListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == openButton) {
				int returnValue = fileChooser.showOpenDialog(TestImage.this);
				if (returnValue == JFileChooser.APPROVE_OPTION) {
					File file = fileChooser.getSelectedFile();
					try {
						bufferedImage = ImageIO.read(file);
						repaint();
					} catch (Exception exception) {
						exception.printStackTrace();
					}
				}
			}
		}
	}
}

تم تعديل هذه المشاركة بواسطة herch في 12 ديسمبر 2009 في 15:33

1
#3

أسف على تأخرى فى الرد ..

شكرأً على المعلومات القيمة ...

----------------------------------

لكن أنا حبيت أضع الكلاسين فى ملفين مختلفين

طبعاً هيعترض على المتغير bufferedImage فا عملت دالة فى ال class testImageترجعه

بس مش شغال عندى

الكود مرفق فى المرفقات

شكراً

code.rar

#4

لماذا أنشأت object من فئة TestImage داخل DisplayImage؟؟ فأنت تستعمل object آخر داخل الmain method لا علاقة له بالذي أنشأت في DisplayPanel

كان يكفي أن تضيف متغير من صنف BufferedImage وتضيف method تقوم بتغيير قيمة هذا المتغير داخل DisplayPanel، وداخل الactionPerformed تنادي على هذه الmethod

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

class DisplayPanel extends JPanel {

	private BufferedImage image;

	public void setImage(BufferedImage image) {
		this.image = image;
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (image != null) {
			g.drawImage(image, 0, 0, this);
		}
	}
}

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class TestImage extends JFrame {

	private JPanel mainPanel;
	private DisplayPanel displayPanel;
	private JButton openButton;
	private JFileChooser fileChooser;

	public TestImage() {
		intializeingPanel();
		intializeingButtons();
		fileChooser = new JFileChooser();
		getContentPane().add(mainPanel);
		MyActionListener actionListener = new MyActionListener();
		openButton.addActionListener(actionListener);
	}

	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) { }
		TestImage testImage = new TestImage();
		testImage.setDefaultCloseOperation(TestImage.EXIT_ON_CLOSE);
		testImage.setSize(new Dimension(600, 300));
		testImage.setLocationRelativeTo(null);
		testImage.setVisible(true);
		testImage.setExtendedState(MAXIMIZED_BOTH);

	}

	private void intializeingPanel() {
		mainPanel = new JPanel(null);
		mainPanel.setBounds(100, 10, 600, 300);

		displayPanel = new DisplayPanel();
		displayPanel.setBounds(350, 150, 500, 300);
		displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
		displayPanel.setOpaque(true);
		displayPanel.setBackground(Color.WHITE);

		mainPanel.add(displayPanel);
	}

	private void intializeingButtons() {
		openButton = new JButton("Open");
		openButton.setBounds(50, 10, 100, 50);
		mainPanel.add(openButton, BorderLayout.NORTH);
	}

	private class MyActionListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == openButton) {
				int returnValue = fileChooser.showOpenDialog(TestImage.this);
				if (returnValue == JFileChooser.APPROVE_OPTION) {
					File file = fileChooser.getSelectedFile();
					try {
						displayPanel.setImage(ImageIO.read(file));
						repaint();
					} catch (Exception exception) {
						exception.printStackTrace();
					}
				}
			}
		}
	}
}
#5

فعلاً كان خطاً يُعاقِب عليه القانون :lol:

---------------------------------------

الصور بتُعرض مضبوطة فى مكان ال panel لكن أحياناً الصورة - التى حجمها أكبر من حجم ال panel - يكون لها بقية لا تظهر ففكرت فى استعمال ال JScrollPane الأفقى و الرأسى كالأتى :

private void intializeingPanel() {
        mainPanel = new JPanel(null);
        mainPanel.setBounds(100, 10, 600, 300);

        displayPanel = new DisplayPanel();
        displayPanel.setBounds(50, 150, 300, 500);
        displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
        displayPanel.setBackground(Color.WHITE);
        scrollPane = new JScrollPane(displayPanel,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        mainPanel.add(scrollPane);
    }

و لكنه يعطينى

Exception in thread "main" java.lang.IllegalArgumentException: invalid verticalScrollBarPolicy

لماذا ؟؟ أنا ممر parameter صح كما يقول ال JavaDoc

شكراً مقدماً

#6

ماذا تريد بالضبط، لأن الكود الأول كان يضع كامل الصورة داخل الjpanel بعد أن يقوم بتصغيرها

هل تريد أن تحافظ الصورة على حجمها الأصلي أم أنك تريدها أن تأخد حجم الpanel؟؟

public JScrollPane(Component view, int vsbPolicy, int hsbPolicy)

vertical متبوعة بhorizontal وليس العكس كما كتبت

#7

نعم أريدها تأخذ حجم ال JPanel

و هدفى من عمل ال JScrolPane أنا لو مش كل الصورة ظاهرة كما فى بعض الصور أقدر أتحرك بال JScrollPane

لكن لما عملت كده

         private void intializeingPanel() {
        mainPanel = new JPanel(null);
        mainPanel.setBounds(100, 10, 600, 300);

        displayPanel = new DisplayPanel();
        displayPanel.setBounds(50, 150, 300, 500);
        displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
        displayPanel.setBackground(Color.WHITE);
        scrollPane = new JScrollPane(displayPanel,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        mainPanel.add(scrollPane);
    }

اختفت ال panel تماماُ

شكرا مقدماً

تم تعديل هذه المشاركة بواسطة mr.beshoy في 13 ديسمبر 2009 في 21:43

#8

اختفى الpanel لأنك تضيف الscrollpane الذي يحويه إلى الmainPanel ولم تقم بتحديد حجمه وإحداثياثه بواسطة setBounds، كما أنه لا داعي للمناداة على setBounds بالنسبة لdisplayPanel، فهو يأخذ حجم وإحداثيات الscrollpane

بالنسبة لعمل scolling على الpanel عند إضافة صورة أكبر منه، فيكفي تغيير الpreferredsize الخاص بالpanel ليكون مساويا لحجم الصورة، وهذا سيرغم الscrollpane على إضافة scrollbars

	private void intializeingPanel() {
		mainPanel = new JPanel(null);
		mainPanel.setBounds(100, 10, 600, 300);

		displayPanel = new DisplayPanel();
		displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
		displayPanel.setOpaque(true);
		displayPanel.setBackground(Color.WHITE);

		JScrollPane scrollPane = new JScrollPane(displayPanel,
						JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
						JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scrollPane.setBounds(350, 150, 500, 300);

		mainPanel.add(scrollPane);
	}

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

class DisplayPanel extends JPanel {

	private BufferedImage image;
	private Dimension panelDimension = new Dimension();

	public void setImage(BufferedImage image) {
		this.image = image;
		panelDimension.setSize(image.getWidth(), image.getHeight());
		setPreferredSize(panelDimension);
		revalidate();
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (image != null) {
			g.drawImage(image, 0, 0, this);
		}
	}
}
#9

ِشكراً يا عصام على ردك الدسم بالمعلومات

#10

الدسم مضر بالصحة :sleep:

مغلوماتي خفيفة وصحية وبدون دسم :D

#11

شكلك رايق ياعم :lol:

اسخن شوية عشان فى سوال احتمال يكون قرب فى الطريق

------------

مواضيع مشابهة