سؤال

لدي JPanel الذي أود أن أضيف JPEG و PNG الصور التي لا تولد على الطاير.

كل الأمثلة التي رأيتها حتى الآن في البديل الدروس, خاصة في البديل أمثلة استخدام ImageIcons.

أنا توليد مثل هذه الصور بايت المصفوفات, أنها عادة ما تكون أكبر من المشترك أيقونة أنها تستخدم في الأمثلة في 640x480.

  1. هل هناك أي (الأداء أو غيرها) مشكلة في استخدام ImageIcon فئة لعرض صورة بهذا الحجم في JPanel?
  2. ما المعتاد طريقة لفعل ذلك ؟
  3. كيفية إضافة صورة إلى JPanel دون استخدام ImageIcon الصف ؟

تحرير:أكثر متأنية من الدروس و API يظهر أنه لا يمكنك إضافة ImageIcon مباشرة إلى JPanel.لكنهم بدلا من تحقيق نفس التأثير من خلال وضع صورة كرمز من JLabel.هذا فقط لا يشعر الحق...

هل كانت مفيدة؟

المحلول

هنا هو كيف نفعل ذلك (مع القليل على مزيد من المعلومات حول كيفية تحميل صورة):

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ImagePanel extends JPanel{

    private BufferedImage image;

    public ImagePanel() {
       try {                
          image = ImageIO.read(new File("image name and path"));
       } catch (IOException ex) {
            // handle exception...
       }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters            
    }

}

نصائح أخرى

إذا كنت تستخدم JPanels ، ثم ربما العمل مع سوينغ.جرب هذا:

BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);

الصورة الآن البديل المكون.يصبح الموضوع إلى تخطيط ظروف مثل أي مكون آخر.

فريد هاسلام طريقة يعمل بشكل جيد.لدي مشكلة مع أسم دليل الرغم من ذلك أنا أريد أن المرجعية صورة داخل جرة بلدي.أن تفعل هذا:

BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));

منذ ليس لدي سوى عدد محدود (حوالي 10) الصور التي لا تحتاج إلى تحميلها باستخدام هذا الأسلوب يعمل بشكل جيد جدا.فإنه يحصل على الملف دون الحاجة إلى الصحيح النسبي أسم دليل.

أعتقد أن هناك حاجة إلى فئة فرعية من أي شيء.مجرد استخدام Jlabel.يمكنك تعيين صورة في Jlabel.لذا حجم Jlabel ثم ملء مع صورة.موافق.هذه هي الطريقة التي كنت تفعل.

يمكنك تجنب المتداول الخاصة بك عنصر فرعية تماما باستخدام JXImagePanel فئة من الحر SwingX المكتبات.

تحميل

JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
  1. يجب أن لا يكون هناك أي مشكلة (غير أي مشاكل قد تكون لديكم مع الصور كبيرة جدا).
  2. إذا كنت تتحدث عن إضافة صور متعددة إلى لوحة واحدة, وأود أن استخدام ImageIcons.للحصول على صورة واحدة ، وأود أن تفكر في صنع مخصص فرعية من JPanel و تجاوز paintComponent طريقة لرسم الصورة.
  3. (انظر 2)

يمكنك فرعية JPanel - هنا مقتطف من ImagePanel الذي يضع صورة في أي واحد من 5 مواقع, أعلى/يسار, أعلى/يمين, الشرق الأوسط/أسفل/يسار أو أسفل/يمين:

protected void paintComponent(Graphics gc) {
    super.paintComponent(gc);

    Dimension                           cs=getSize();                           // component size

    gc=gc.create();
    gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
    if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2)       +mmHrzShift),(((cs.height-mmSize.height)/2)        +mmVrtShift),null); }
    if(tlImage!=null) { gc.drawImage(tlImage,(insets.left                       +tlHrzShift),(insets.top                           +tlVrtShift),null); }
    if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top                           +trVrtShift),null); }
    if(blImage!=null) { gc.drawImage(blImage,(insets.left                       +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
    if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
    }

JPanel هو دائما تقريبا الخاطئ فئة فرعية.لماذا لم فرعية JComponent?

هناك مشكلة بسيطة مع ImageIcon في أن منشئ كتل قراءة الصورة.ليس حقا مشكلة عند التحميل من التطبيق jar, ولكن ربما لو كنت قد تكون القراءة عبر شبكة اتصال.هناك الكثير من AWT-عصر أمثلة على استخدام MediaTracker, ImageObserver والأصدقاء حتى في JDK العروض.

أنا أفعل شيء مشابه جدا في مشروع أعمل عليه.حتى الآن لقد ولدت الصور تصل إلى 1024x1024 دون أي مشاكل (إلا ذكرى) و يمكن عرضها بشكل سريع جدا وبدون أي مشاكل في الأداء.

تجاوز الطلاء طريقة JPanel فرعية مبالغة و يتطلب العمل أكثر مما كنت بحاجة إلى القيام به.

طريقتي هي:

Class MapIcon implements Icon {...}

أو

Class MapIcon extends ImageIcon {...}

الرمز الذي يستخدم لتوليد الصورة سوف تكون في هذه الفئة.يمكنني استخدام BufferedImage رسم على ثم عندما paintIcon() ويسمى استخدام غرام.drawImvge(bufferedImage);هذا يقلل من كمية وامض في حين يتم توليد الصور الخاصة بك, ويمكنك الموضوع.

أنا القادم تمديد JLabel:

Class MapLabel extends Scrollable, MouseMotionListener {...}

هذا هو لأنني أريد أن أضع صورة على انتقل جزء الأول-هاء.عرض جزء من الصورة و يكون المستخدم انتقل في جميع أنحاء حسب الحاجة.

ثم يمكنني استخدام JScrollPane لعقد MapLabel الذي يحتوي فقط على MapIcon.

MapIcon map = new MapIcon (); 
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();

scrollPane.getViewport ().add (mapLabel);

ولكن السيناريو الخاص بك (فقط تظهر الصورة كاملة في كل مرة).تحتاج إلى إضافة MapLabel إلى أعلى JPanel, و تأكد من أن حجم كل منهم إلى كامل حجم الصورة (قبل تجاوز GetPreferredSize()).

إنشاء مجلد مصدر في دليل المشروع في هذه الحالة لا يسمى ذلك الصور.

JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();

هذا الجواب هو مكمل @shawalli الجواب...

أردت الإشارة صورة داخل جرة بلدي جدا, ولكن بدلا من وجود BufferedImage أنا بسيطة فعل هذا:

 JPanel jPanel = new JPanel();      
 jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));

يمكنك تجنب استخدام الخاص Components SwingX المكتبة ImageIO الدرجة:

File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));

أستطيع أن أرى العديد من الإجابات ، وليس حقا معالجة ثلاثة أسئلة من البروتوكول الاختياري.

1) كلمة على الأداء:صفائف بايت من المرجح unefficient إلا إذا كنت يمكن استخدام الدقيق بكسل بايت الطلب الذي مباريات محولات العرض الحالية القرار وعمق الألوان.

لتحقيق أفضل أداء رسم, ببساطة تحويل الصور الخاصة بك إلى BufferedImage التي يتم إنشاؤها مع نوع المقابلة الحالي الرسومات التكوين.انظر createCompatibleImage في https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html

هذه الصور سوف يكون مؤقتا تلقائيا على الشاشة بطاقة الذاكرة بعد رسم عدة مرات دون أي البرمجة الجهد (هذا هو المعيار في البديل منذ جافا 6) ، وبالتالي فإن الرسم الفعلي سوف تأخذ كمية ضئيلة من الوقت - إذا لم تتغير الصورة.

تغيير الصورة سوف تأتي مع ذاكرة إضافية نقل بين الذاكرة الرئيسية و GPU الذاكرة - التي هي بطيئة.تجنب "إعادة رسم" صورة في BufferedImage وبالتالي تجنب القيام getPixel و setPixel في كل الوسائل.

على سبيل المثال ، إذا كنت تقوم بتطوير لعبة, بدلا من رسم جميع الأطراف الفاعلة إلى BufferedImage ثم إلى JPanel هو أسرع لتحميل جميع الجهات الفاعلة أصغر BufferedImages ، ورسم لهم واحدا تلو الآخر في JPanel رمز في الموقف الصحيح من هذا الطريق لا يوجد إضافية لنقل البيانات بين الذاكرة الرئيسية و GPU الذاكرة إلا من المرحلة الأولى من نقل الصور من أجل التخزين المؤقت.

ImageIcon استخدام BufferedImage تحت غطاء محرك السيارة - ولكن أساسا تخصيص BufferedImage مع السليم وضع الرسومات هو المفتاح ، وليس هناك أي جهد للقيام بذلك الحق.

2) بالطريقة المعتادة من يفعل هذا هو رسم BufferedImage في تجاوز paintComponent طريقة JPanel.على الرغم من أن جافا يدعم كمية جيدة من الأشياء الجيدة إضافية مثل العازلة سلاسل السيطرة على VolatileImages مؤقتا في الذاكرة GPU ، هناك حاجة إلى استخدام أي من هذه منذ جافا 6 الذي يقوم بعمل جيدة إلى حد معقول دون تعريض كل هذه التفاصيل من تسريع GPU.

علما بأن GPU تسارع قد لا تعمل بعض العمليات مثل تمتد شفافة الصور.

3) لا إضافة.مجرد رسمه كما ذكر أعلاه:

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

"مضيفا" من المنطقي إذا كانت الصورة هي جزء من التخطيط.إذا كنت بحاجة إلى هذا بمثابة الخلفية أو الأمامية صورة ملء JPanel, مجرد رسم في paintComponent.إذا كنت تفضل تختمر عامة البديل المكون الذي يمكن أن تظهر الصورة ، ثم إنها نفس القصة (يمكنك استخدام JComponent و تجاوز لها paintComponent طريقة) - ثم يضاف هذا إلى التصميم الخاص بك من مكونات واجهة المستخدم الرسومية.

4) كيفية تحويل المصفوفة إلى Bufferedimage

تحويل البايت صفائف PNG, ثم التحميل جدا كثيفة الموارد.أفضل طريقة لتحويل الخاصة بك الموجودة في صفيف بايت إلى BufferedImage.

لذلك: لا تستخدم الحلقات ونسخ بكسل.التي هي بطيئة جدا جدا.بدلا من ذلك:

  • تعلم المفضل بايت هيكل BufferedImage (في الوقت الحاضر فمن الأسلم أن نفترض RGB أو رغبا ، والتي هي 4 بايت لكل بكسل)
  • تعلم scanline و scansize في الاستخدام (مثلا ، قد يكون لديك 142 بكسل صورة واسعة - ولكن في الحياة الحقيقية التي سيتم تخزين 256 بكسل واسعة صفيف بايت لأنه أسرع في عملية وقناع غير المستخدمة pixes من قبل الأجهزة GPU)
  • ثم مرة واحدة لديك مجموعة بناء وفقا لهذه المبادئ ، setRGB طريقة مجموعة من BufferedImage يمكن نسخ الصفيف الخاص بك إلى BufferedImage.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top