I’m writing code for drawing in a JPanel as if it’s a canvas, where I can create shapes by clicking inside the panel. When I click, it places the dots where I want them to go, however if I scroll and then click, it places the dots where the mouse would be if I hadn’t scrolled. I assume this is because the mouse coordinates don’t change, so I’m guessing I need to add the number of pixels I’ve scrolled (horizontally and vertically). Is there a command I can use to refer to these values?
It's been a while since I've worked with Swing, but I believe you want to call:
JScrollPane sp = ...
Point viewPosition = sp.getViewport().getViewPosition();
The viewPosition.x and .y will return the offset in pixels from the top left corner.
I have an assignment where I am supposed to create a prototype drawing program to display and manipulate faces. It is supposed to use 2 windows, one to draw the face and the other to control the drawing. It is supposed to initially show the image of a face (drawn with shapes).
The face consists of a head, two eyes, a nose, and a mouth. Each of these parts is selected by clicking the mouse within the border of the object. The eyes are selected as a pair, so clicking either eye selects them both. when one face part is selected, all previous selections are forgotten.
The control window operates only upon the selected object. A click on the Change image button performs the following tasks (depending on the selected face part):
Head: Head changes from green to yellow to purple to purple, and back to green
Nose: The nose image changes another of three possible nose images
Mouth: Mouth image changes to another of three possible mouth images
Eyes: eye image changes to another of four possible eye images
Include a scroll bar with behavior:
Selected Head: Head gets wider and narrower with scroll bar value change
Selected Nose: Nose image moves up or down with scroll bar value change
Selected Mouth: Mouth gets wider or narrower with scroll bar value change
Selected Eyes: Eyes move closer together or farther apart with scroll bar value change
My problem is, I have no idea where to even start. I have watched many a tutorial on swing and awt and have even tried playing around with the palette manager in NetBeans. Can anyone point me in the right direction or maybe walk me through the code?
Your question is not a good fit here. Also, despite your instructors alleged inaccuracies, it is still conceivably possible for a person to do the research on their own to go from the rather nice set of specific requirements you have to a functioning program. I don't mean that to be as critical as it may sound.
However, out of appreciation of the fact that you approached your instructor, and also out of pity, maybe I can give you some starting points and hints.
First of all, Swing is the right way to start. Read through the relevant sections of the tutorial at http://zetcode.com/tutorials/javaswingtutorial/ and follow along with some of the projects.
You can code Swing interfaces by hand quite easily, and for your relatively simple application, and for the learning experience, it is a reasonable option. However, for future reference, many IDEs have GUI editors (NetBeans ships with the feature I think, Eclipse has the WindowBuilder plugin) - the caveat being that you have to add learning how to use the IDE to your task list (of course, this will ultimately save you time in the long run).
In any case, your first step should be to design your software. Determine what actions you need to perform, what user actions you need to respond to and how, and what information you are working with. You give the following requirements:
The control window operates only upon the selected object. A click on
the Change image button performs the following tasks (depending on the
selected face part):
Head: Head changes from green to yellow to purple to purple, and back
to green
Nose: The nose image changes another of three possible nose
images
Mouth: Mouth image changes to another of three possible mouth
images
Eyes: eye image changes to another of four possible eye images
Include a scroll bar with behavior:
Selected Head: Head gets wider and narrower with scroll bar value
change
Selected Nose: Nose image moves up or down with scroll bar
value change
Selected Mouth: Mouth gets wider or narrower with scroll
bar value change
Selected Eyes: Eyes move closer together or farther
apart with scroll bar value change
The basic component you are working with here is a face, so let's make a design decision here to have a face be an object with other properties (you could take a different approach and have the different parts of the face be your basic units). Based on your description of scroll bars, a face has the following modifiable properties:
Head width.
Vertical nose position.
Mouth width.
Distance between eyes.
A face also, of course, has other constant characteristics that are pretty much up to you to arbitrarily decide the value of, for example the diameter of the eyes, the color of the skin, etc. You will have to work those out.
In addition to modifying the above properties, there are a few things you need to be able to do with a face, also based directly on your requirements:
Draw (paint) the face.
Redraw (repaint) the face when a property changes.
Allow the user to select a part by clicking, which breaks down into:
Responding to mouse clicks.
Determining the component under the cursor given an XY location.
Providing information about the selection to the application.
The last part "providing information about the selection" is an implementation detail that you have a few options for, and you will have to decide. For example, you could create some type of event listener interface and tell the face about it, and let it call methods on that interface when the selection changes -- this is a very swing way to do it. You could also have the face internally maintain which property is currently selected, in which case you need to give it the ability to get/set the value of the currently selected property. You could also have the face directly call methods on your editor UI window. All of these ways have distinct advantages and disadvantages, and I'll leave it as an exercise to the reader to experiment.
Now, you also, as per your requirements, need to provide a scroll bar for the user to edit properties with, in a separate window. So now, think about what UI components you need and how you want them to tie together:
Face Window
Contains a single face component (or more if you want).
Editor Window
Contains a scroll bar.
Might contain a label describing the current selection, if you'd like.
Swing already provides most of these components. A window is a JFrame. A scroll bar is a JScrollBar. A label is a JLabel. Swing doesn't provide a face, so you'll need to write a custom component yourself.
As for how they tie together:
Changing the object selection in the face could:
Update the scrollbar to the current value, if you'd like.
Update the scrollbar range to appropriate values.
Update the label to describe the current selection, if you'd like.
Changing the scrollbar must:
Update the currently selected property on the face.
Ultimately cause the face to be redrawn.
The major task now, then, is to implement a Swing component that draws a face and responds to mouse clicks.
Since you are creating a new component, you'll want to pick an appropriate base, perhaps a JComponent or a JPanel, up to you. Exactly how to create new components can be easily found in many tutorials on Google (including some basics in the one I linked to above), and that is up to you to research. Essentially, though, reiterating what was said above, your custom face component has the following custom behaviors:
Draw a face.
Receive mouse events.
Determine clicked component from mouse X,Y coordinates. At its most basic level, this will require some math. If your head, eyes, mouth, and nose are ellipses, for example, it will be up to you to compute whether or not a given X,Y coordinate is within the bounds of one of those ellipses. However, you will want to look into Shape, which will allow you to easily define shapes and provides bounds checking methods already.
I think this is enough for you to get started and put it all together. The following general tasks are at hand:
Read that tutorial I linked to, a lot of basics should become clear. Try writing some simple "hello world" style applications.
Try writing some custom components; your requirements are basic and much of it is covered in the "Painting" section of that tutorial.
Check out a tutorial or some examples on how to use Shape and experiment.
If you have specific questions about code you've written, with a specific problem you may be trying to solve, you can always come back and post that on SO.
I hope this helps. More importantly, I hope this gives you at least some idea of how to go from requirements to implementation in general.
Edit:
It's been a while since I played with Shape so I put together this tiny example. Click / drag over the two shapes to select them, which will turn them yellow:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ShapeSelect extends JPanel {
private final Shape firstShape = new Rectangle2D.Float(60, 40, 70, 70);
private final Shape secondShape = new Ellipse2D.Float(30, 30, 90, 50);
private Shape selected = null;
public ShapeSelect () {
// set up the component
setPreferredSize(new Dimension(200, 200));
addMouseMotionListener(new MouseMotionAdapter() {
#Override public void mouseDragged (MouseEvent event) {
selectShapeUnder(event.getX(), event.getY());
}
});
addMouseListener(new MouseAdapter() {
#Override public void mousePressed (MouseEvent event) {
selectShapeUnder(event.getX(), event.getY());
}
});
}
// draw our shapes, selected shape is yellow.
#Override protected void paintComponent (Graphics g) {
Graphics2D graphics = (Graphics2D)g;
graphics.setColor((selected == firstShape) ? Color.YELLOW : Color.RED);
graphics.fill(firstShape);
graphics.setColor((selected == secondShape) ? Color.YELLOW : Color.GREEN);
graphics.fill(secondShape);
}
// updates 'selected' based on x,y coordinate and redraws component on change.
public void selectShapeUnder (int x, int y) {
Shape oldSelected = selected;
// note that since second shape is draw on top of first, we give second preference.
// for overlapping shapes the selection should be consistent with the gui display.
if (secondShape.contains(x, y))
selected = secondShape;
else if (firstShape.contains(x, y))
selected = firstShape;
else
selected = null;
if (selected != oldSelected)
repaint();
}
public static final void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run () {
JFrame frame = new JFrame("Shape Select");
frame.getContentPane().add(new ShapeSelect(), BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
I have a custom component displaying *.png image. The image has transparent and non-transparent area. If I add ActionListener(or MouseClickListener) to component, it will raise events even if I click on transparent area of component. Visually it looks like clicking outside the component.
How can I declare which area should react on clicks and which should not?
I've read about getting pixel from image your coordinates from event object and check its transparency. It seems difficult and ineffective.
Maybe define custom-border of this component or something else?
You answered your own question.
Within the mousePressed() event handler, you're going to have to check if you're within the JComponent, and then check the pixel at the x and y coordinate of the mouse click for transparency.
How can I declare which area should react on clicks and which should not?
This is done at the JComponent level by overriding the contains(...) method. So for example you extend JLabel to create a TransparentLabel which contain your image in the form of an icon.
Then whenever this method is invoked you only need to check this one location to determine if the pixel is transparent or not.
If your main issue about "overhead" is that you only want to make it opaque when the mouse enters a non-transparent part of the image, I'd consider pre-computing an image "mask".
On image load, make another image (or a 2d array, or something similar) that will be binary (i.e. black-and-white only, or 1 and 0 values only in an array). 0/white = transparent, 1/black = non-transparent.
Then, on mouse events, you can just check the exact pixel in the mask if it is set (value = black or 1), and trigger if it is.
Did you try to bunk two same pictures file and just for the second picture give it a short width ? Like that I think you will can to add differents listerners for the both pictures.
This is the scenario:
I have one image background set on an activity. On this background, a rectangle has been drawn (in other words, one image depicting a rectangle). I need to display text WITHIN this rectangle.
Right now, I have one solution in mind: since I'm going to optimize the UI for most screens (incl. tablets), I'm going to customize the main .xml layout for each screen size (multiple .xml layouts). Thus, I can manually set the place where the text area goes within the rectangle (+ its size).
I am most certain that this solution is NOT good. I'd like to hear some suggestions from more advanced developers. What would an elegant way of placing text over a background image showing a rectangle, so that the text stays within the rectangle's borders be?
Because I need to set particular positions for other UI elements (centered buttons (vertically/horizontally), I am currently using a Relative Layout.
By default if you have used dp as dimensional measure, your app should in theory work fine for all resoultions. Android by default scales the screen to fit different screens. AndroidDeveloper You just have to make sure that you have different images for resources (Rectangle image). There is another post in SO which you might be intrested to look into link
Cheers
RIchie
I am working on a project in which I have a background image with specific points of interest. Each of these specific points will have a custom button class overlaid on it so that when I click the point, I'm actually clicking the button. However, I would like to be able to rotate the background image and have the buttons rotate with the image so that the custom buttons are still overlaid on the specific points. Any tips as to how I should go about doing this?
Are you actually wanting to rotate 4 different images and move them around the square, but always keeping them upright? Or are you rotating a single image so that after one button click the single image is on its side? If the former, then that can be easily done by using a container (a JPanel) that uses BorderLayout, and having four JPanels with background images and JButtons held in the container JPanel at the four compass points of the BorderLayout: BorderLayout.EAST, BorderLayout.WEST, BorderLayout.NORTH, and BorderLayout.SOUTH (although Java gurus prefer you use the newer constants, i.e., BorderLayout.PAGE_START). Then when a button is pressed, remove components and re-add but in a rotated order.
If you want to do the latter, then things get a bit trickier in that you'll likely need to use AffineTransforms, rotate instance to rotate the container, and you'll need to perform the same transformation on the point of the mouse press/click/release, so that the rotated buttons receive correct clicks. If the container is not square, things get even trickier still.