কীভাবে কোনও জেপ্যানেলে একটি চিত্র যুক্ত করবেন?


341

আমার একটি জেপ্যানেল রয়েছে যাতে আমি JPEG এবং PNG চিত্রগুলি যুক্ত করতে চাই যা আমি ফ্লাইতে উত্পন্ন করি।

সুইং টিউটোরিয়ালগুলিতে আমি এখনও দেখা সমস্ত উদাহরণ , বিশেষত সুইং উদাহরণগুলিতেImageIcon এস ব্যবহার করে ।

আমি এই চিত্রগুলি বাইট অ্যারে হিসাবে উত্পন্ন করছি এবং এগুলি উদাহরণগুলিতে তারা ব্যবহৃত সাধারণ আইকন থেকে 640x480 এ সাধারণত বড় হয় larger

  1. জেপ্যানেলে আকারের চিত্রটি প্রদর্শন করতে ইমেজ আইকন ক্লাসটি ব্যবহার করার ক্ষেত্রে কোনও (পারফরম্যান্স বা অন্যান্য) সমস্যা আছে কি?
  2. এটি করার স্বাভাবিক উপায় কী ?
  3. ইমেজ আইকন ক্লাসটি ব্যবহার না করে কীভাবে কোনও জেপ্যানেলে একটি চিত্র যুক্ত করবেন?

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


1
আপনি কীভাবে বাইট অ্যারে তৈরি করছেন তার উপর নির্ভর করে MemoryImageSourceএগুলিকে জেপিজি বা পিএনজি ফর্ম্যাটে রূপান্তর করা এবং তারপরে ImageIOসর্বাধিক উত্তরের পরামর্শ অনুসারে পড়ার চেয়ে কোনওটি ব্যবহার করা আরও দক্ষ । আপনি ব্যবহার করে আপনার চিত্রের ডেটা দিয়ে তৈরি একটি Imageথেকে পেতে পারেন এবং উত্তরগুলির মধ্যে একটি হিসাবে প্রস্তাবিত হিসাবে প্রদর্শন করুন। MemoryImageSourcecreateImage
অ্যালডেন

আমার উত্তর চেক করুন stackoverflow.com/questions/43861991/...
tommybee

উত্তর:


252

আমি এটি কীভাবে করব তা এখানে (কোনও চিত্র কীভাবে লোড করবেন সে সম্পর্কে আরও কিছু তথ্যের সাথে):

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            
    }

}

17
-1 paintComponent অবৈধ বাস্তবায়নের (@Dogmatixed সম্ভবত যে কেন আপনি ঐ redrawing সমস্যা রয়েছে) - এটা উচিত নয় তার সম্পূর্ণ এলাকায় আবরণ যদি এটা হচ্ছে অস্বচ্ছ (যা ডিফল্ট) রিপোর্ট garantee, সবচেয়ে সহজ পদ্ধিতি হল super.paintComponent কল করে অর্জন
ক্লিওপাত্রা

5
@ ক্লিওপাত্রা, ধন্যবাদ, আমি বুঝতে পারি নি ... জাভাদোকের মতে: "আপনি যদি সুপারার প্রয়োগটি চালিত না করেন তবে আপনাকে অবশ্যই অস্বচ্ছ সম্পত্তিটিকে সম্মান করতে হবে, এটি যদি এই উপাদানটি অস্বচ্ছ হয় তবে আপনাকে অবশ্যই সম্পূর্ণ পূরণ করতে হবে একটি অস্বচ্ছ বর্ণযুক্ত ব্যাকগ্রাউন্ড। যদি আপনি অস্বচ্ছ সম্পত্তিটিকে সম্মান না করেন তবে আপনি সম্ভবত ভিজ্যুয়াল শিল্পকর্মগুলি দেখতে পাবেন "" আমি এখনই উত্তর আপডেট করব।
ব্রেন্ডন ক্যাশম্যান

8
সবসময় সম্মান দয়া করে Principle of Encapsulationসুপার ক্লাস এর সময় অগ্রাহ্য পদ্ধতি, অ্যাক্সেস সুনির্দিষ্টভাবে উল্লেখ করা paintComponent(...)পদ্ধতি protectedএবং public:-)
NICE গাভী

1
এটি কোনও ভাল নয়, এটি চিত্রটিতে প্যানেলটি আকার দেওয়ার বিষয়ে কিছু করে না। এর সাথে ডিল করার পরে আরও কোড যুক্ত করতে হবে। জেলাবেল উত্তরটি ব্যবহার করা অনেক সহজ।
কেইলি

2
@ জোনাথন: এর কিছু উত্স সম্পর্কে আমি সত্যিই দুঃখিত Principle of Encapsulation। প্রোগ্রামিংয়ের সময় কেবল মনে রাখবেন, কোডের বাকী সমস্ত কিছু থেকে কী লুকানো উচিত, কোডটিতে সব কিছু দৃশ্যমান হওয়ার পরিবর্তে সেভাবেই বজায় রাখা দরকার। দেখে মনে হচ্ছে এটি এমন একটি জিনিস যা অভিজ্ঞতার সাথে আসে, যেহেতু প্রতিদিন একজন শেখা হয়। যে কোনও বই এনক্যাপসুলেশন কী তা একটি মৌলিক ধারণা দিতে পারে তবে আমরা আমাদের কোডটি কীভাবে বাস্তবায়িত করি তা স্থির করে যে আমরা ধারণাকে কতটা মেনে চলি।
নি

520

আপনি যদি জেপ্যানেল ব্যবহার করছেন তবে সম্ভবত সুইংয়ের সাথে কাজ করছেন। এটা চেষ্টা কর:

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

চিত্রটি এখন একটি দোল উপাদান। এটি অন্যান্য উপাদানগুলির মতো বিন্যাসের শর্ত সাপেক্ষে পরিণত হয়।


16
JLabel এর আকার অনুযায়ী চিত্রটি কীভাবে স্কেল করবেন?
কোডিং_ইডিয়ট

1
দুর্দান্ত কোড! আমি সুইং নিয়ে খুব বেশি অভিজ্ঞ নই তবে কাজটি করতে পারছি না। কেউ কি jdk 1.6.0_16 এ চেষ্টা করেছে?
এটোরাস

3
@ এ্যাটোরাস আমি জানি আপনি কিছুক্ষণ আগে এই কথা জিজ্ঞাসা করেছিলেন তবে অন্য কোনও নবজাতকের যদি আমার সমস্যা হয় তবে পিকেলবেল.সেটবাউন্ডস () মনে রাখবেন;
কাইল

যখনই কোনও ফটো পুনরায় লোড করা হয় তখন কি আমাকে প্রতিবার নতুন জেবেল অবজেক্ট তৈরি করতে হবে?
0x6B6F77616C74

2
@ কোডিং_ইডিয়ট নতুন জেএলবেল (নতুন চিত্র-আইকন (ব্যাকগ্রাউন্ড ইমেজ.সেটসেল্ডইনস্ট্যান্স (প্রস্থ, উচ্চতা, চিত্র। এসসিএএলএফএইএসএটি))));
ডেভিড

37

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

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

যেহেতু আমার কাছে কেবলমাত্র একটি সীমাবদ্ধ নম্বর (প্রায় 10) চিত্র রয়েছে যা এই পদ্ধতিটি ব্যবহার করে আমার লোড করা দরকার, এটি বেশ ভাল কাজ করে। এটি সঠিক আপেক্ষিক ফাইলপথ না রেখে ফাইল পায়।


1
আমি BufferedImage previewImage = ImageIO.read(new URL(imageURL));একটি সার্ভার থেকে আমার ছবি পেতে প্রথম লাইন প্রতিস্থাপন ।
ইনক্রিটর

জার থেকে চিত্রগুলি উল্লেখ করার জন্য, এই স্ট্যাকওভারফ্লো.com
a

33

আমি মনে করি কোনও কিছুর সাবক্লাস করার দরকার নেই। শুধু একটি Jlabel ব্যবহার করুন। আপনি একটি জ্লেবেলে একটি চিত্র সেট করতে পারেন। সুতরাং, জ্লেবেলকে আকার দিন এবং তারপরে এটি একটি চিত্র দিয়ে পূর্ণ করুন। ঠিক আছে. আমি এইভাবেই করি।


20

আপনি ফ্রি সুইংএক্স লাইব্রেরি থেকে জেএক্সআইমেজপ্যানেল ক্লাসটি ব্যবহার করে আপনার নিজস্ব উপাদান সাবক্লাস সম্পূর্ণরূপে ঘূর্ণন এড়াতে পারবেন ।

ডাউনলোড


11
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));

8

আপনি জেপ্যানেল সাবক্লাস করতে পারেন - এখানে আমার ইমেজপ্যানেল থেকে একটি নির্যাস রয়েছে, যা উপরের / বাম, উপরের / ডান, মাঝারি / মাঝারি, নীচে / বাম বা নীচে / ডানে যে কোনও একটিতে একটি চিত্র রাখে:

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); }
    }

8
  1. কোনও সমস্যা হওয়া উচিত নয় (খুব সাধারণ চিত্রগুলির সাথে আপনার হতে পারে এমন সাধারণ সমস্যা ব্যতীত)।
  2. আপনি যদি একটি একক প্যানেলে একাধিক চিত্র যুক্ত করার কথা বলছেন তবে আমি ব্যবহার করব ImageIcon। একটি একক চিত্রের জন্য, আমি চিত্রটি আঁকার জন্য একটি কাস্টম সাবক্লাস তৈরি JPanelএবং এর paintComponentপদ্ধতিটি ওভাররাইড করার বিষয়ে ভাবব ।
  3. (দেখুন 2)

6

JPanelসাবক্লাসে প্রায় সর্বদা ভুল শ্রেণি। কেন আপনি সাবক্লাস করবেন না JComponent?

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


6

আমি কাজ করছি এমন একটি বেসরকারী প্রকল্পে খুব অনুরূপ কিছু করছি। এখনও অবধি আমি কোনও সমস্যা ছাড়াই 1024x1024 অবধি চিত্র তৈরি করেছি (মেমরি ব্যতীত) এবং খুব দ্রুত এবং কোনও পারফরম্যান্স সমস্যা ছাড়াই সেগুলি প্রদর্শন করতে পারি।

জেপানেল সাবক্লাসের পেইন্টের পদ্ধতিটি ওভাররাইড করা ওভারকিল এবং আপনার আরও বেশি কাজ করা দরকার।

আমি যেভাবে এটি করি তা হ'ল:

Class MapIcon implements Icon {...}

অথবা

Class MapIcon extends ImageIcon {...}

আপনি চিত্রটি তৈরি করতে যে কোডটি ব্যবহার করেন তা এই শ্রেণিতে থাকবে। আমি তখন আঁকার জন্য একটি বাফারডেমেজ ব্যবহার করি যখন পেইন্টআইকন () বলা হয়, তখন g.drawImvge (বাফারডেমেজ) ব্যবহার করুন; এটি আপনার চিত্রগুলি তৈরি করার সময় করা ফ্ল্যাশিংয়ের পরিমাণ হ্রাস করে এবং আপনি এটি থ্রেড করতে পারেন।

এরপরে আমি জেবেলকে প্রসারিত করব:

Class MapLabel extends Scrollable, MouseMotionListener {...}

এটি কারণ আমি আমার চিত্রটি একটি স্ক্রোল ফলকে রাখতে চাই, অর্থাৎ চিত্রটির অংশটি প্রদর্শন করি এবং ব্যবহারকারীকে প্রয়োজন মতো স্ক্রোলটি রাখতে পারি।

সুতরাং আমি ম্যাপল্যাবেল ধরে রাখতে একটি জেএসক্রোলপ্যান ব্যবহার করি, যার মধ্যে কেবলমাত্র মানচিত্র রয়েছে।

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

scrollPane.getViewport ().add (mapLabel);

তবে আপনার দৃশ্যের জন্য (কেবল প্রতিটি সময় পুরো চিত্রটি দেখান)। আপনাকে উপরে JPanel এ মানচিত্রটি যুক্ত করতে হবে এবং এগুলি সমস্ত চিত্রের পূর্ণ আকারের (গেটপ্রেফারড সাইজ () ওভাররাইড করে) আকারের বিষয়ে নিশ্চিত করা দরকার।


5

আপনার প্রকল্প ডিরেক্টরিতে একটি উত্স ফোল্ডার তৈরি করুন, এই ক্ষেত্রে আমি এটিকে চিত্রগুলি বলেছি called

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

5

আপনি নিজস্ব Componentও সুইংএক্স লাইব্রেরি এবং ImageIOক্লাস ব্যবহার এড়াতে পারেন :

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

4

এই উত্তরটি @ শাওলির উত্তরের পরিপূরক ...

আমি আমার জারের মধ্যেও একটি চিত্রের রেফারেন্স দিতে চেয়েছিলাম, তবে একটি বাফার্ডআইমেজ না করে, আমি সহজ করেছিলাম:

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

1

আমি অনেক উত্তর দেখতে পাচ্ছি, ওপির তিনটি প্রশ্নের উত্তরই দিচ্ছি না।

1) পারফরম্যান্সে একটি শব্দ: বাইট অ্যারেগুলি সম্ভবত অপ্রতুল, যদি না আপনি সঠিক পিক্সেল বাইট ক্রম ব্যবহার করতে পারেন যা আপনার ডিসপ্লে অ্যাডাপ্টারের বর্তমান রেজোলিউশন এবং রঙের গভীরতার সাথে মেলে।

সেরা অঙ্কন কর্মক্ষমতা অর্জন করতে, আপনার চিত্রটিকে কেবল একটি বুফেরডেমেজে রূপান্তর করুন যা আপনার বর্তমান গ্রাফিক্স কনফিগারেশনের সাথে সম্পর্কিত এক ধরণের মাধ্যমে উত্পন্ন হয়। এ createCompatibleImage দেখুন https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html

এই চিত্রগুলি কোনও প্রোগ্রামিংয়ের প্রচেষ্টা ছাড়াই কয়েকবার আঁকার পরে ডিসপ্লে কার্ডের মেমরিতে স্বয়ংক্রিয়ভাবে ক্যাশে হবে (জাভা 6 এর পরে এটি সুইংয়ের মধ্যে স্ট্যান্ডার্ড), এবং সেইজন্য আসল অঙ্কনটি সময় নগণ্য পরিমাণে নেবে - আপনি যদি চিত্রটি পরিবর্তন না করেন তবে ।

চিত্র পরিবর্তন করা মূল স্মৃতি এবং জিপিইউ মেমরির মধ্যে একটি অতিরিক্ত মেমরি স্থানান্তর নিয়ে আসবে - যা ধীর। বাফারডিম্যাজেজে চিত্রটিকে "পুনরায় আঁকুন" এড়িয়ে চলুন, গেটপিক্সেল এবং সেটপিক্সেলটি কোনও উপায়ে করা এড়িয়ে চলুন।

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

ইমেজআইকন হুডের নীচে একটি বাফারডিমেজ ব্যবহার করবে - তবে মূলত যথাযথ গ্রাফিক্স মোডের সাহায্যে একটি বাফারডিমেজ বরাদ্দ করা মূল বিষয়, এবং এই অধিকারটি করার কোনও প্রচেষ্টা নেই।

2) এটি করার স্বাভাবিক উপায়টি হল জেপ্যানেলের একটি ওভাররাইড পেইন্ট কম্পোনেন্ট পদ্ধতিতে একটি বাফার্ডআইমেজ আঁকুন। যদিও জাভা জিপিইউ মেমরিতে ক্যাশড ভোল্টাইলআইমেজেস নিয়ন্ত্রণকারী বাফার চেইনের মতো অতিরিক্ত পরিমাণে গুডিকে সমর্থন করে, তবে জাভা 6 এর পরে এগুলির কোনও ব্যবহার করার দরকার নেই যা জিপিইউ ত্বরণের এই সমস্ত বিবরণ প্রকাশ না করে যুক্তিসঙ্গত ভাল কাজ করে।

দ্রষ্টব্য যে জিপিইউ ত্বরণ কিছু নির্দিষ্ট ক্রিয়াকলাপের জন্য কাজ করতে পারে না, যেমন প্রসারিত চিত্রগুলি প্রসারিত করা।

3) যোগ করবেন না। কেবল উপরে বর্ণিত হিসাবে এটি আঁকা:

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

চিত্রটি বিন্যাসের অংশ হলে "যুক্ত করা" অর্থবোধ করে। আপনার যদি জ্যাপানেলটি পূরণ করে একটি পটভূমি বা সম্মুখভূমি চিত্র হিসাবে এটি প্রয়োজন হয় তবে কেবল চিত্রকোম্পোন্ট এ আঁকুন। এবং তারপর যুক্ত করুন - আপনি একটি জেনেরিক সুইং উপাদান আপনার ইমেজ দেখাতে পারেন যে বানানোর পছন্দ করেন, তাহলে এটি একই গল্প (যদি আপনি JComponent ব্যবহার করতে পারেন এবং তার paintComponent পদ্ধতি ওভাররাইড) হল এই GUI উপাদান আপনার লেআউটে।

4) অ্যারেকে কিভাবে একটি বুফেরিডেমে রূপান্তর করা যায়

আপনার বাইট অ্যারেগুলিকে পিএনজিতে রূপান্তর করা, তারপরে এটি লোড করা যথেষ্ট সংস্থান নিবিড়। আরও ভাল উপায় হ'ল আপনার বিদ্যমান বাইট অ্যারেটিকে একটি বুফারডেমেজে রূপান্তর করা।

তার জন্য: লুপগুলি এবং অনুলিপি পিক্সেলের জন্য ব্যবহার করবেন না । এটা খুব ধীর। পরিবর্তে:

  • বাফার্ডআইমেজের পছন্দসই বাইট স্ট্রাকচারটি শিখুন (আজকাল এটি আরজিবি বা আরজিবিএ, যা পিক্সেল প্রতি 4 বাইট হয় ধরে নেওয়া নিরাপদ)
  • স্ক্যানলাইন শিখুন এবং স্ক্যানাইজ ব্যবহার করুন (যেমন আপনার 142 পিক্সেল প্রশস্ত চিত্র থাকতে পারে - তবে বাস্তব জীবনে এটি 256 পিক্সেল প্রশস্ত বাইট অ্যারে হিসাবে সংরক্ষণ করা হবে যেহেতু এটি প্রসেস করা আরও দ্রুত এবং জিপিইউ হার্ডওয়্যার দ্বারা অব্যবহৃত পিক্সগুলি মাস্ক করুন) )
  • তারপরে একবারে এই নীতিগুলি অনুসারে আপনার অ্যারে তৈরি হয়ে গেলে, বাফার্ডআইমেজের সেটআরজিবি অ্যারে পদ্ধতিটি আপনার অ্যারে বাফার্ডআইমেজে অনুলিপি করতে পারে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.