I have an application, in which I want to displaying a number of image components. Each item of this will be a custom jcomponent which will has the image in a BufferedImage object to draw it in paintcomponents(Graphics g) overrided method. I will also use a JPanel for the grid with a gridlayout or flowlayout for place the custom image jcomponents, also the grid's layout will be inside an JscrollPane.
My question is what happens, when the number of the images I must to put into the grid will become big. With use of the jscrollpane, the number of the components so the number of the images must be draw will be smaller like 20-30 components, but each component inserted into the grid will have an object of BufferedImage to keep the corresponding image. This is bad for the perfomance and the memory consuption? May can use some pattern? for example if I use a main point of reference to load the images from disk to bufferedimage and depending of which rectangle of the scrollpane the user then release some bufferedimage where they putted away in the grid from the current position of the jscrollpane?
Thank you.
You're going to have to prototype the essential variables and profile the results. Then compare those results to the capabilities available on your lowest common denominator target platform. An sscce is invaluable. This one, for example, will let you easily vary N, the number of images.
Some view alternatives are mentioned here.
Noted in comment: To conserve memory, consider an LRU cache.
Thread the loading of the images, so that the UI isn't delayed by the loading
Scale the images, probably to fit the size of the panel, no point in wasting memory
Related
My scenario is basically that I am drawing a mathematical type plot with horizontal and vertical scales. For any given window size, the scales remain static. I only need to change the scales if the user resizes the window. I was therefore debating whether drawing the scales on a BufferedImage and calling drawImage is better than doing all of the individual drawXXX calls to construct the scales on each paint. The latter does not sound very efficient since the user will likely resize the window once at startup (if that) but the trade off would be the memory required to maintain a BufferedImage that could be as big as 4K display resolution
If anyone has any thoughts/opinions/suggestions, I would appreciate hearing them
Assuming you would be using TYPE_INT_ARGB for the BufferedImage format, an image that is of "4k" resolution (3840x2160) would be 33.18 MBs in size (that's megaBytes) + maybe a few bytes for header info.
So, really, it wouldn't be that much of a memory concern. But, remember, either way, you will have to be repainting to either the BufferedImage or to the Graphics object every time it calls paint(). Truly, I see no significant difference in efficiency.
The only real difference I see here is that with BufferedImage you get the added comforts of its built in resizing capabilities. This way you can always paint your scales onto the image the same way (Not have to do calculations based on window size) then resize the BufferedImage to the window size and it takes care of resizing the scales to fit the window on its own.
I got me 90 odd images that form an explosion animation. When I come to 'play' the animation, I use a Swing Timer to set a new Icon for a JLabel, and cycle through until I reach the last image.
My question is this: is it better to have loaded and stored all the ImageIcons in some static form somewhere, or load them from file every time I need them?
Explosions are quite common in the game, and I have two sizes of them (scaling each image for every size of explosion seemed rather inefficient when I want them to swap very quickly) which makes for 200 images (roundabout).
Store or load?
For a game, using Swing components to represent game objects (Sprites) is probably not the best way. I would use a single JPanel as the rendering component and override its paintComponent() method to do rendering for my own game objects.
This way you avoid dealing with Swing components intricacies (e.g. they may add unwanted gaps / offsets where they really paint, as well they make it harder to control the painting order - important when two objects overlap).
I wouldn't use any type of Icon, just use java.awt.Image, or you own type to represent an image (e.g. to render part of an underlying image - as sprite sheet requires). Icon doesn't really add any value for a game.
If the image data fits easily into memory, I would load all the images before even starting. If there are too many images to preload them all, I would use some sort of cache that retains as many images as possible - the cache may use an LRU based scheme to decide which images to retain when it gets full.
I use a SwingTimer to set a new Icon for a JLabel, and cycle through until I reach the last image.
You may want to consider using an Animated Icon. It can be used anywhere an Icon can be used.
The AnimatedIcon class uses loaded Icons, so I guess my answer would be to pre-load for ease of use and CPU efficiency.
I'm developing on a machine from 2008, and unfortunately cannot upgrade at the moment. I really need to optimize performance in this tool I am building.
My entire project is fairly large, and I'm currently creating my own Map Editor for use to create Maps for my main project later on down the road. It's fairly simple, and is being designed to load, save, and edit Arrays of 'Tiles' possessed by a Map. It's basically a 2D-Map Editor, customized for my needs.
When a Map is loaded into the Editor, its Tileset (one large BufferedImage), is broken down into each individual Tile (with a smaller BufferedImage), loaded into the right side of the GUI into a large bunch of JLabels with icons. I've used various Swing LayoutManagers to achieve my desired positioning.
Inside the MapCanvas area, essentially the same thing is done. Each Tile, whether empty or not, has a JLabel with an Icon, loaded onto the Grid. I've asked around before about whether using Swing components would be more efficient than using Java2D to design and draw, and the consensus was that it didn't really matter (and to be honest, Swing probably does it better than what I would write myself).
I believe my problem is stemming from the way that I interconnect each JLabel and their icons.
My goal was to reduce the number of duplicate Icons I have to create, which in theory should reduce memory usage and CPU usage. Tiles in the Editor are interacted with as follows:
If no tile is selected to be 'stamped,' there will just be an alpha composite of a color painted over the JLabel's icon to denote that it is being hovered, and will revert upon a MouseExit
If there is a tile on the active Stamp tool, that tile's image will replace the JLabel's icon -temporarily- to denote that it is being hovered, and will revert upon a MouseExit
If there is a tile on the active Stamp tool, and a JLabel is clicked, that JLabel's icon will be set to the active Stamp tile "permanently" unless reverted
If the option to have Grid Lines is toggled on, each JLabel's icon will be processed through the ImageFactory to have dashed lines running along the top and left edges (forms a grid, as seen in the picture)
If the Zoom level is changed, each JLabel's preferredSize is set to accomodate, and the icon has to be resized in the ImageFactory (grid lines applied depending)
Upon loading a Map into the Editor, each JLabel is created, given its corresponding BufferedImage (be that empty or not), and thrown into the Map's field ArrayList. The preferredSize is set so the Layout looks right, and it is added to the MapCanvas (which is just a JPanel).
I created various ArrayList and HashMap objects, so that I could pass a JLabel as a Key, and get back a BufferedImage. That way, when hovering iver a JLabel, the MouseEvent can send the event's source back to the listener, and it can grab the correct BufferedImage based on the JLabel it receives. The image can then be processed by my ImageFactory class in one of the ways listed above.
So basically when a JLabel recieves a MouseEvent, this happens:
MouseEvent sends source JLabel to ActionListener
Listener uses source JLabel as Key to grab desired BufferedImage chunk
BufferedImage chunk is then processed accordingly (which could be a color Alpha composite, a Zoom factor applied to it, or grid lines added to it, or a combination of these)
Is there any better way to do this? This doesn't take any noticeable toll on my 2 year old Laptop, but there is very noticeable lag when the Mouse interacts with the JLabels on my older Desktop machine.
Seeing as I will be actively developing on both, I want the environment to run smoothly, and if that means I have to be stricter on memory and CPU usage, then so be it.
But I can't really seem to come up with a system that is more memory efficient.
Are the ArrayLists and HashMaps the problems? Are the many image operations the problems?
I've taken advantage of JLabel's "setName(String)" method in various ways already (for example, each JLabel has a name containing its location in the single-dimension Array of JLabels, and its x-and-y coordintes on the graph, i.e. "maptile#24:1,9"), but that requires iterating through Arrays, and my hope was that specifically grabbing the BufferedImages with Keys would be more efficient.
Java collections are dynamic, meaning they resize as you add data. The actual model for their sizing function (used by ArrayList and presumably HashMap) is something similar to when they reach capacity they double their capacity, which consists of declaring a new block in memory and copying across all the stored data.
If you know the maximum possible size for each of your HashMaps and ArrayLists you may benefit from using the constructors that take an initial capacity. Here & Here This will prevent them using more memory than necessary. And will prevent any possible delays from increasing capacity.
You may also benefit from reading the top few paragraphs of the documentation for each type as they can provide good explanations of efficient usage (e.g. HashMaps loadfactor).
It may also be useful for you to consider other types of List and Map (if you are not aware of the difference in their implementations), e.g LinkedList has far more efficient delete and insert operations than ArrayList, however it is much slower for random access to an index than an ArrayList as it must traverse each prior index to reach the desired index, whereas an ArrayList can directly access the desired index.
However it's hard to guess how noticeable any changes you make based on these recommendations would be.
We are having a Swing application which we plan to port to SWT/JFace. The Swing application draws a lot of icons (javax.swing.Icon implementations) in trees and tables (icon left to the text). If I understood it correctly, SWT only can draw images (aka graphic files). What would be the simplest solution to paint the icon or entire table/tree cell? Thanks in advance.
Images can be loaded from graphic files, or they can be drawn in-memory.
Image image = new Image(Display.getCurrent(), width, height);
GC gc = new GC(image);
// draw icon using GC
gc.dispose();
As far as displaying them in tables/trees, the most direct approach is to set the image on the table/tree item:
TableItem item = ...
item.setImage(theImage);
There is one significant drawback to this approach however: on Windows, the first time you set an image on a table item, that image's height becomes the standard height for all items in the table. So if you set a larger image, it will be scaled down to the first image's size. If you set a smaller image, it will be scaled up.
If all your images are the same size, this will not be a problem.
However if you can not predict the size of the images in advance, I recommend using the custom draw API to render your table/tree items. This approach is definitely more intensive but gives you fine-grained control over the result.
So I have this chart that's a little special. Kind of like an XY plot of points but my boss wanted to look like a bunch of boxes rather than dots connected by lines. And I basically made a chart using gridlayout and a whole bunch of cells that I'll be colouring in black or white depending on the data.
Now he sorta wants it to be outputted to a image file. Is there any way to save a Panel into a picture? He wants to display not only the data but also save a visual representation of the data into an image file.
Is there any way to save a Panel into
a picture?
Screen Image
You can create a Graphics context which paints to an image. This technique is often used with animations to prepare drawings offline and swap them in place to avoid artifacts.
Typically you can use the same paint methos as used to paint your canvas.
Here are more details