Changing the min and max value of JSlider depanding on condition - java

I'm creating a Swing GUI in Netbeans. The purpose of this GUI is to open an (buffered)image (in a JLabel as icon) and apply Affine transforms on it. Now there are 4 transforms that I'm doing as follows.
Now, each transform requires two sliders to change the X and Y value, except that of rotate, which will require only one. I did it this way since its much better than having to do four tabs for all 4 types of transforms. Also I want it to be such that , for example, if an image is rotated, the same rotated image can be sheared by selecting shear from the Drop down list.
The problem is (are):
How do i repaint the label icon and apply different transform on the same repainted image?
Also, how do i change the minimum and maximum value of JSlider depanding on the effect selected?

You should store originally loaded BufferedImage, and create its copy - that way you won't "destroy" it.
As for the changing value there are methods setMaximum and setMinimum - add listener to list, as stated in Oracle tutorial and modify the values.

As a concrete example of #Daniel's answer, the article Image processing with Java 2D describes the program ImageDicer. It constructs a TreeMap<String, BufferedImageOp> each of which may be selected from a JComboBox and applied to a BufferedImage.
See also related examples here and here.

Related

CPU/Memory Efficiency in Multi-tabbed Map/Tile Level Editor (many HashMaps/ArrayLists)

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.

Java image library - turn grid image into array

If I have an image of a table of boxes, with some coloured in, is there an image processing library that can help me turn this into an array?
Thanks
You can use a thresholding function to binarize the image into dark/light pixels so dark pixels are 0 and light ones are 1.
Then you would want to remove image artifacts using dilation and erosion functions to remove noise (all these are well defined on Wikipedia).
Finally if you know where the boxes are, you can just get the value in the center of each box to determine the array value, or possibly use an area near the center and take the prevailing value (i.e. more 0's is a filled in square, more 1's is and empty square).
If you are scanning these boxes and there is a lot of variation in the position of the boxes, you will have to perform some level of image registration using known points, or fiducials.
As far as what tools to use to do this, I'd recommend first trying this manually using a tool like ImageJ, which has a UI and can also be used programatically since it is written all in Java.
Other good libraries for this include OpenCV and the Java Advanced Imaging API.
Your results will definitely vary depending on the input images and how consistenly lit and positioned they are.
The best way to see how it will do for your data is to try applying these processing steps manually to see where your threshold value should be, how much dilating/eroding you need to get consistent results.

drawing layers using java graphics API

I'm doing a simulator project that tests several A* based algorithms and show how they work and their results.
The algorithms are all multi-agent and run on a grid map environment.
I used a JPanel for the grid which contains a two dimensional array of Cells where each Cell is a custom class that extends the Component class and use the paint method to draw the stuff i need inside each cell.
For the drawing inside the cell I use method such as Graphics.fillRect or Graphics.drawImage to fill each cell with a certain color or icon).
I'm using a special Icon for the start position and goal position of every agent on the grid.
My problem is that I want to be able to draw more than one item on the same cell.
For example I want to be able to show the path of one of the agents by painting the cells along the path in a special color and the path might go through a start position of a different agent, so I want to be able to fill the cell with the color and have an icon drawn on top.
In another example I want to be able to mix two colors using alpha blending.
If I use graphics.fillRect() with one color that has alpha and then use it again with a different color with alpha value it won't work since the last fillRect() will override the first call.
Is there a way I can achieve what I need using the same Cell Component I created or should I implement it differently?
Perhaps there is a better solution to this problem?
I would really appreciate any advice on this matter.
If you draw a rectangle with 50% alpha and then draw another one, the second one will override it instead of blending with it.
It depends on the mode. This convenient utility shows the result of blending different colors using the modes defined in AlphaComposite. The available source code may offer some insights for your project.
Addendum:
the stuff I was trying to composite was on the same Component.
The example cited does exactly this, as does this example. If AlphaComposite does not meet your requirements, you can always vary hue, saturation and/or value; this example composes a color table based on saturation.

Zoom in Java Swing application

I am looking for ways to zoom in a Java Swing application. That means that I would like to resize all components in a given JPanel by a given factor as if I would take an screenshot of the UI and just applied an "Image scale" operation. The font size as well as the size of checkboxes, textboxes, cursors etc. has to be adjusted.
It is possible to scale a component by applying transforms to a graphics object:
protected Graphics getComponentGraphics(Graphics g) {
Graphics2D g2d=(Graphics2D)g;
g2d.scale(2, 2);
return super.getComponentGraphics(g2d);
}
That works as long as you don't care about self-updating components. If you have a textbox in your application this approach ceases to work since the textbox updates itself every second to show the (blinking) cursor. And since it doesn't use the modified graphics object this time the component appears at the old location. Is there a possibility to change a components graphics object permanently? There is also a problem with the mouse click event handlers.
The other possibility would be to resize all child components of the JPanel (setPreferredSize) to a new size. That doesn't work for checkboxes since the displayed picture of the checkbox doesn't change its size.
I also thought of programming my own layout manager but I don't think that this will work since layout managers only change the position (and size) of objects but are not able to zoom into checkboxes (see previous paragraph). Or am I wrong with this hypothesis?
Do you have any ideas how one could achieve a zoomable Swing GUI without programming custom components? I looked for rotatable user interfaces because the problem seems familiar but I also didn't find any satisfying solution to this problem.
Thanks for your help,
Chris
You could give a try to the JXLayer library.
There are several tools in it, which could help you to make a zoom. Check the examples shown here. I would recommend you to read more about the TransformUI, from this library. From the example, it seems like it could help solving your problem.
Scaling the view is easy enough; transforming mouse coordinates is only slightly more difficult. Here's an elementary example. I'd keep JComponents out, although it might make sense to develop an analogous ScaledComponent that knows about the geometry. That's where #Gnoupi's suggestion of using a library comes in.
hey you can try this if you want to zoom a image like any other image viewer the use a JPanel draw an image using drawImage() method now create a button and when you click the button increase the size of the panel on the frame it appears as if the image is being viewed in Zoom
You might find Piccolo2D.java API useful: http://code.google.com/p/piccolo2d/
It is very simple.
It touts in particular its smooth zooming. You essentially make a "canvas" that can contain various elements, and can then zoom by just holding right-click and panning the mouse back and forth.
I worked on a team that used it to create this: http://sourceforge.net/apps/mediawiki/guitar/index.php?title=WebGuitar#EFG.2FGUI_Visualizer
The nodes you see there are clickable links themselves.
Since Java 9, there are VM arguments (actually meant to be used for high dpi scaling) that can render a application with a higher scaling factor:
java -Dsun.java2d.uiScale=2.0 -jar MyApplication.jar
Or:
java -Dsun.java2d.win.uiScaleX=2.0 -Dsun.java2d.win.uiScaleY=2.0 -jar MyApplication.jar

Dynamically changing the tooltip of a draw2d figure

We are currently using Eclipse Draw2D/GEF for an information page describing a process in our application. This basically consists of a matrix of large squares, each containing a matrix of smaller squares. We originally had all the squares as GEF objects, but because of the large volume of them being shown, we found that this did not scale very well and the view took a very long time to open. We then changed it so that only the large squares are Figures and we then draw the smaller squares using the graphic in paintFigure.
The problem that we are running into is that we still want the tooltip to change depending on which small square you are hovering over. I tried to do this by adding a mouseMotionListener and setting the tooltip, through setTooltip, depending on where the mouse currently is. The problem is that once the tooltip is displayed, it does not change any more when setTooltip is called.
Does any one know of an alternative way of doing this? Is there a way of getting the viewpart's PopupHelper and using that? Any help would be appreciated.
Thanks
Hmnn.. interesting problem. Since you paint your own Grid within the Figure, I would think that you have two options.
Try posting SWT events to fool Eclipse. I'd try a focus lost followed by a focused gained, to trigger tooltip machinery, at which point you could get the coordinates and display the appropriate contents.
Don't use the Figure#getTooltip strategy at all. Just show your own composite.
To dynamically change the tooltip, you can hold an instance of the tooltip Figure in your parent Figure. In the constructor of the parent Figure, create a new tooltip Figure (e.g. a Label) and use setToolTip() method to set the tooltip Figure to parent Figure.
When data model is changed, the updated tooltip text/icon can be set to the tooltip Figure. Then you just call setToolTip(tooltipFigure) method again.
You can have a method like:
protected Label toolTipLabel;
protected void updateToolTip(String text, Image icon){
toolTipLabel.setText(text);
toolTipLabel.setIcon(icon);
setToolTip(toolTipLabel);
}
The updateToolTip() method can be invoked in parent Figure's conturctor to initialize the tooltip. And this method can be invoked each time after the data model is changed.
I encountered the same problem in my code and solved it with that method. In my code, I invoked the updateToolTip() in the parentFigure.paintFigure() method.

Categories

Resources