Saya memiliki JPanel yang ingin saya tambahkan gambar JPEG dan PNG yang saya hasilkan dengan cepat.
Semua contoh yang saya lihat sejauh ini dalam Tutorial Swing , khususnya dalam contoh Swing menggunakan ImageIcon
s.
Saya menghasilkan gambar-gambar ini sebagai array byte, dan mereka biasanya lebih besar dari ikon umum yang mereka gunakan dalam contoh, di 640x480.
- Apakah ada masalah (kinerja atau lainnya) dalam menggunakan kelas ImageIcon untuk menampilkan gambar sebesar JPanel?
- Apa cara yang biasa dilakukan?
- Bagaimana cara menambahkan gambar ke JPanel tanpa menggunakan kelas ImageIcon?
Sunting : Pemeriksaan tutorial dan API yang lebih cermat menunjukkan bahwa Anda tidak dapat menambahkan ImageIcon langsung ke JPanel. Sebaliknya, mereka mencapai efek yang sama dengan mengatur gambar sebagai ikon JLabel. Rasanya tidak benar ...
MemoryImageSource
daripada mengubahnya menjadi format JPEG atau PNG dan kemudian membaca denganImageIO
seperti yang disarankan sebagian besar jawaban. Anda dapat memperolehImage
dari hasilMemoryImageSource
konstruksi dengan data gambar Anda dengan menggunakancreateImage
, dan menampilkan seperti yang disarankan dalam salah satu jawaban.Jawaban:
Inilah cara saya melakukannya (dengan sedikit info lebih lanjut tentang cara memuat gambar):
sumber
Principle of Encapsulation
sementara Super Class, Penentu Akses daripaintComponent(...)
protected
public
Principle of Encapsulation
. Hanya ingat saat pemrograman, apa yang harus disembunyikan dari sisa kode, perlu dipertahankan seperti itu, daripada terlihat oleh semuanya dalam kode. Sepertinya itu adalah sesuatu yang datang dengan pengalaman, seperti yang dipelajari setiap hari. Buku apa pun dapat memberikan ide dasar apa itu enkapsulasi, tetapi bagaimana kami menerapkan kode kami yang memutuskan seberapa banyak kami berpegang pada konsep tersebut.Jika Anda menggunakan JPanels, maka mungkin bekerja dengan Swing. Coba ini:
Gambar sekarang merupakan komponen ayun. Itu menjadi tunduk pada kondisi tata letak seperti komponen lainnya.
sumber
Cara Fred Haslam bekerja dengan baik. Saya mengalami masalah dengan filepath, karena saya ingin referensi gambar dalam toples saya. Untuk melakukan ini, saya menggunakan:
Karena saya hanya memiliki jumlah gambar terbatas (sekitar 10) yang saya perlu memuat menggunakan metode ini, itu bekerja dengan cukup baik. Ia mendapat file tanpa harus memiliki relatif relatif file yang benar.
sumber
BufferedImage previewImage = ImageIO.read(new URL(imageURL));
untuk mendapatkan gambar saya dari server.Saya pikir tidak perlu subkelas apa pun. Cukup gunakan Jlabel. Anda dapat mengatur gambar menjadi Jlabel. Jadi, ubah ukuran Jlabel lalu isi dengan gambar. Tidak apa-apa. Inilah yang saya lakukan.
sumber
Anda dapat menghindari menggulirkan subkelas Komponen Anda sepenuhnya dengan menggunakan kelas JXImagePanel dari SwingX gratis pustaka .
Unduh
sumber
sumber
Anda dapat mensubklasifikasikan JPanel - ini adalah ekstrak dari ImagePanel saya, yang menempatkan gambar di salah satu dari 5 lokasi, atas / kiri, atas / kanan, tengah / tengah, bawah / kiri atau bawah / kanan:
sumber
ImageIcon
s. Untuk satu gambar, saya akan berpikir tentang membuat subkelas kustomJPanel
dan menggantipaintComponent
metodenya untuk menggambar.sumber
JPanel
hampir selalu kelas yang salah untuk subkelas. Mengapa Anda tidak akan subkelasJComponent
?Ada sedikit masalah dengan
ImageIcon
konstruktor yang memblokir membaca gambar. Tidak terlalu masalah saat memuat dari toples aplikasi, tetapi mungkin jika Anda berpotensi membaca melalui koneksi jaringan. Ada banyak contoh era AWT untuk menggunakanMediaTracker
,ImageObserver
dan teman-teman, bahkan dalam demo JDK.sumber
Saya melakukan sesuatu yang sangat mirip dalam proyek pribadi yang sedang saya kerjakan. Sejauh ini saya telah menghasilkan gambar hingga 1024x1024 tanpa masalah (kecuali memori) dan dapat menampilkannya dengan sangat cepat dan tanpa masalah kinerja.
Mengganti metode cat subclass JPanel adalah berlebihan dan membutuhkan lebih banyak pekerjaan daripada yang harus Anda lakukan.
Cara saya melakukannya adalah:
ATAU
Kode yang Anda gunakan untuk menghasilkan gambar akan berada di kelas ini. Saya menggunakan BufferedImage untuk menarik ketika paintIcon () dipanggil, gunakan g.drawImvge (bufferedImage); Ini mengurangi jumlah flashing yang dilakukan saat Anda menghasilkan gambar, dan Anda dapat mengaitkannya.
Berikutnya saya memperpanjang JLabel:
Ini karena saya ingin meletakkan gambar saya pada panel gulir, yaitu menampilkan bagian dari gambar dan meminta pengguna untuk menggulirkan sesuai kebutuhan.
Jadi saya menggunakan JScrollPane untuk memegang MapLabel, yang hanya berisi MapIcon.
Tapi untuk skenario Anda (hanya perlihatkan seluruh gambar setiap waktu). Anda perlu menambahkan MapLabel ke JPanel atas, dan pastikan untuk mengukur semuanya ke ukuran penuh gambar (dengan menimpa GetPreferredSize ()).
sumber
Buat folder sumber di direktori proyek Anda, dalam hal ini saya menyebutnya Gambar.
sumber
Anda dapat menghindari menggunakan
Component
perpustakaan danImageIO
kelas milik sendiri dan SwingX :sumber
Jawaban ini adalah pelengkap dari jawaban @ shawalli ...
Saya ingin referensi gambar di dalam toples saya juga, tetapi alih-alih memiliki BufferedImage, saya sederhana melakukan ini:
sumber
Saya bisa melihat banyak jawaban, tidak benar-benar menjawab tiga pertanyaan OP.
1) Sebuah kata pada kinerja: array byte cenderung tidak efisien kecuali jika Anda dapat menggunakan pemesanan byte pixel yang tepat yang cocok dengan display adapter Anda resolusi saat ini dan kedalaman warna.
Untuk mencapai kinerja gambar terbaik, cukup konversikan gambar Anda ke BufferedImage yang dihasilkan dengan jenis yang sesuai dengan konfigurasi grafis Anda saat ini. Lihat createCompatibleImage di https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Gambar-gambar ini akan secara otomatis di-cache pada memori kartu tampilan setelah menggambar beberapa kali tanpa upaya pemrograman (ini adalah standar dalam Swing sejak Java 6), dan oleh karena itu gambar yang sebenarnya akan memakan waktu yang dapat diabaikan - jika Anda tidak mengubah gambar .
Mengubah gambar akan disertai dengan transfer memori tambahan antara memori utama dan memori GPU - yang lambat. Hindari "menggambar ulang" gambar menjadi BufferedImage karena itu, hindari melakukan getPixel dan setPixel dengan segala cara.
Misalnya, jika Anda mengembangkan game, alih-alih menarik semua aktor game ke BufferedImage dan kemudian ke JPanel, jauh lebih cepat untuk memuat semua aktor sebagai BufferedImages yang lebih kecil, dan menggambar mereka satu per satu dalam kode JPanel Anda di posisi yang tepat - dengan cara ini tidak ada transfer data tambahan antara memori utama dan memori GPU kecuali transfer awal gambar untuk caching.
ImageIcon akan menggunakan BufferedImage di bawah tenda - tetapi pada dasarnya mengalokasikan BufferedImage dengan mode grafis yang tepat adalah kuncinya, dan tidak ada upaya untuk melakukan ini dengan benar.
2) Cara yang biasa dilakukan adalah dengan menggambar BufferedImage dalam metode paintComponent dari JPanel yang diganti. Meskipun Java mendukung sejumlah barang tambahan yang bagus seperti rantai penyangga yang mengendalikan VolatileImages yang di-cache dalam memori GPU, tidak perlu menggunakan semua ini karena Java 6 yang melakukan pekerjaan yang cukup baik tanpa memaparkan semua detail akselerasi GPU ini.
Perhatikan bahwa akselerasi GPU mungkin tidak berfungsi untuk operasi tertentu, seperti peregangan gambar yang tembus cahaya.
3) Jangan menambahkan. Cukup cat seperti yang disebutkan di atas:
"Menambahkan" masuk akal jika gambar merupakan bagian dari tata letak. Jika Anda membutuhkan ini sebagai gambar latar atau latar depan yang mengisi JPanel, cukup menggambar paintComponent. Jika Anda lebih suka membuat komponen Swing umum yang dapat menampilkan gambar Anda, maka itu adalah cerita yang sama (Anda dapat menggunakan JComponent dan mengganti metode paintComponentnya) - dan kemudian menambahkan ini ke tata letak komponen GUI Anda.
4) Cara mengonversi array menjadi Bufferedimage
Mengubah byte array Anda ke PNG, kemudian memuatnya cukup banyak sumber daya. Cara yang lebih baik adalah mengonversi array byte yang ada ke BufferedImage.
Untuk itu: jangan gunakan untuk loop dan menyalin piksel. Itu sangat lambat. Sebagai gantinya:
sumber