I am not super-familiar with swing but I am slowly learning. Basically, I have a viewer that extends JPanel. That viewer has two areas: the top is a pane that has a bunch of buttons in it, and the rest of it is a JLayeredPane (it is not necessary that it be a JLayeredPane; I am just using that right now because I thought maybe it will help me do what I need to do). The JLayeredPane contains a JScrollPane, which contains a TiledImage from JAI (the TiledImage could also be a RenderedOp).
What I am trying to achieve is for someone to be able to add graphics over the top of the image, without changing the image itself. The two things I want to do are: (1) someone can click a button in the menu pane and then drag the mouse across the image, creating a rectangle. Once the mouse button was released the rectangle would turn into a semi-translucent, colored rectangle, giving the appearance that part of the image has been "highlighted" in that color; (2) someone can click a different button in the menu pain and then click on the image. The person would then be able to type in text wherever he clicked on the image, and then change the size or color of that text.
I want the information for the highlights and text to be separate from the image, so the person could print the image with or without the additions, or go back later and change or delete the highlights or text notes.
Can anyone put me on the path of a mechanism that might be the right way to do this? I cannot find a lot of information about this kind of stuff out there. I have a "GlassPane" demo I picked up on one of the Java sites that seemed like it might work along the same lines, but it requires a Frame and Swing components don't seem to have similar functionality. I can get the "look" of what I want for highlighting with "fillRect" on the Graphics object, but I think that once I have one or more rectangles like that I cannot differentiate between them (e.g., it cannot allow a person to delete, resize or change the color of a specific rectangle in the Graphics object). However, I may be wrong.
I'm not exactly good at swing myself, but i would suggest making it so that each rectangle is a new object, and then allow the user to change the properties of it... You could make a "Rectangle" class and make the starting point and the ending point or however they're called be located at wherever the mouse starts dragging and wherever the mouse stopped dragging. You're going to have to add MouseListener in order to achieve this. Then, by pushing a button the user could choose one of the rectangles and then edit the x and y coordinates in a text field.
You might be able to pick up some ideas about drawing / selecting / manipulating properties of geometrical shapes here.
For adding text over an image, you can try a null layout and add a JTextField at a suitable location and set it opaque(false) and remove its border on focusLost. I had once posted an example of this somewhere but Google can't find it, and I lost my local copy to a disk crash. Take a try, post your best efforts and we'll take a look. To keep it short enough for members here to read, focus on one feature at a time, either rectangles or text.
There are no new questions, but there may be new answers.
posted 8 years ago
Okay, I am still working on this but the functionality is working now. I would appreciate any comments/suggestions/insights, especially anything that would make my methods more elegant or my code more efficient and streamlined; here is what I came up with:
My component tree now looks like: JApplet -> JPanel -> JScrollPane -> JLayeredPane -> [DisplayJAI (contains a rendered PDF image; in DEFAULT layer) & JPanel (extended; in PALETTE layer)]
So at its core the functionality relies on a layered pane, the bottom layer containing a DisplayJAI displaying a PDF and the next layer up containing my custom JPanel. The layered pane, DisplayJAI and the custom JPanel all resize with the image (the application allows you to zoom in and out by scaling the image), so the problem I am working on next is getting the highlights and the text notes to resize along with everything else.
At any rate, the text notes and the highlighting are both implemented in the custom JPanel (called "edits" in my code). First I created a mouse listener, in the parent JPanel and listening to the custom JPanel (it might make more sense to eventually move this to the custom JPanel), and overrode mousePressed:
Then for highlighting, I also added mouseDragged and mouseReleased overrides:
In my custom JPanel I have an inner class called "Highlight" because I need to allow users to edit or delete highlights, and I need to save them in a database. All it does is save the information about the highlight (x, y, width, height, color, etc.). All the Highlight instances are stored in a HashMap. On a side note, I think I want to eventually use translucent components instead of fillRect(), but for now it works. Here are the highlight-related methods in my custom JPanel:
And, last but not least, I overrode the paintComponent method to draw all of my highlights, though I am not sure if this ruins the efficiency I was trying to achieve in passing dimension parameters into my repaint() methods:
The text notes are a little more straightforward, though I have had a very hard time getting the Swing components to do what I want them to do. I am kind of disappointed in the apparent lack of built-in functionality in Swing, from things like the variety of built-in events to more decorative things like the absence of drop shadows and other things indicative of a more modern GUI language. (I say "apparent" because I am still quite new to Swing and I still have a lot to learn.) The saving grace is that I can usually (eventually) add the non-decorative functionality I need (I am no graphic designer), but it would be nice if Swing straight out of the box was more up-to-par with some of the newer languages.
Any thoughts, suggestions, criticisms?
"To do good, you actually have to do something." -- Yvon Chouinard