creating a JDialog with multiple, selectable image items - java

I'm attempting to create a JDialog frame that will have a background image and an interactive JPanel above that. In this context, the JDialog would represent a 'combat' field where units would be able to be selected and moved. The game is space based so there will be an ArrayList of ships and possibly a planet object to defend.
I've been able to override paintComponent to draw a rough circle representing a 'planet' but couldn't get the background JLabel image to show. Then I could get the background JLabel to show but couldn't see the circles. Ideally, I want to replace the circles with actual images for each ship type and unique for planets. I'm open to other methods than using this JDialog/JLayered/Customer JPanel if there is a better way to accomplish this. I've been working on this for more hours than I can count.
I've created a JDialog, added a JLayeredPane and set a JLabel within that for the background. I've written a custom class extending JPanel that would be added to the JLayeredPane above the JLabel, which draws circles for the planet and units.
The reason I chose a JPanel is so I can check for mouse events to determine what the player is selecting (the planet to add resources) or a ship (for movement and attack).
for the custom JPanel I've written this simple extension:
public class SectorPnl extends javax.swing.JPanel implements MouseInputListener, ActionListener {
private int circleY, circleX, circleRadius;
private Sector sector;
private Shape planetShape;
private Shape shipShape;
private Ship ship;
private Planet planet;
private Invasion inv;
private ArrayList<ShipType> shipBuild;
public SectorPnl(Sector sector, Invasion inv)
{
initComponents();
this.sector = sector;
this.inv = inv;
this.planet = sector.getPlanet();
shipBuild = new ArrayList();
Timer update = new Timer(28, this);
update.start();
if ( sector.hasPlanet() )
{
circleRadius = (int) sector.getPlanet().getPlanetRadius();
circleX = (int) sector.getPlanet().getPositionX();
circleY = (int) sector.getPlanet().getPositionY();
planetShape = new Ellipse2D.Double(circleX, circleY, circleRadius,
circleRadius);
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
if ( planetShape != null)
{
g2.setColor(Color.red);
g2.fill(planetShape);
g2.draw(planetShape);
}
if ( shipShape != null )
{
g2.setColor(Color.white);
g2.fill(shipShape);
g2.draw(shipShape);
}
}
And this is the lines for adding it to the JDialog:
sectorDlg.setTitle(sector.getName());
sectorDlg.setVisible(true);
sectorDlg.setSize(800,800);
SectorPnl sectorPnl = new SectorPnl(sector, inv);
sectorPnl.addMouseListener(sectorPnl);
sectorPnl.addMouseMotionListener(sectorPnl);
sectorLayer.setLayer(sectorPnl, 100);
sectorLayer.setBounds(0, 0, 800, 800);

It's possible for a JLabel to show both an icon and text, but I think you have to specify the relative position of the icon and the text.
ImageIcon icon = createImageIcon("images/middle.gif");
. . .
label1 = new JLabel("Image and Text",
icon,
JLabel.CENTER);
//Set the position of the text, relative to the icon:
label1.setVerticalTextPosition(JLabel.BOTTOM);
label1.setHorizontalTextPosition(JLabel.CENTER);
This was taken from Oracle's How to use labels.
I don't know what happens if you try to set the background and foreground colors.
I think you would be better off if you used a JPanel as a canvas, and just drew the icons and text where you wanted them. You can process mouse clicks on the JPanel.

I've got the background image displaying now and having the 'ship' and 'planet' painted on top. I'm still trying to determine how to pick a mouse event when an Image is clicked though.
I've added a few new variables:
private Image bgImage;
private Image shipImage;
For correcting the background issue I added these lines after initComponents();
ImageIcon ii = new ImageIcon(this.getClass().getResource("sector_Bg1.png"));
bgImage = ii.getImage();
I've changed my paintComponent method to add ship icons (in .png or .jpg format) and paint them as well.
#Override
public void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
Graphics2D g3 = (Graphics2D) g;
Graphics2D g4 = (Graphics2D) g;
g3.drawImage(bgImage, 0, 0, null);
if ( planetShape != null)
{
g2.setColor(Color.red);
g2.fill(planetShape);
g2.draw(planetShape);
}
for ( Ship s : sector.getShips() )
{
ImageIcon si = new ImageIcon(this.getClass().getResource("isd.png"));
shipImage = si.getImage();
g3.drawImage(shipImage, (circleX + shipImage.getHeight(null)), circleY, null);
}
}
Now....how to pick up mouse events within a drawn Image?

Related

JButton paintComponent() to paint Graphic Shape slow?

I created a customized Class which extends JButton to create buttons with a Graphic image for a button panel, I override paintComponenet() which also calls a method drawColoredShape().
The Graphic images are mostly GeneralPath Shapes.
When running the application, paintComponent() of each Button is repeatedly called.
Question: Does Overriding paintComponent to add custom GeneralPath graphics on the JButton significantly slow down the application. Is there a way to make it more efficient?
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
drawColoredShape(g2, getText());
g2.setColor(new Color(myColor));
g2.dispose();
}
/**
* Draws Custom Shape for this button.
*/
private void drawColoredShape(Graphics2D g2, String txt) {
Shape sh = null;
case "Cat":
this.setForeground(Color.BLUE);
g2.setPaint(Color.Blue);
g2.draw(SPECIAL_SHAPE); // from General Path defined somewhere
break;
case "Dog":
break;
... etc
}

Java Graphics on a null layout

My end game for this panel is that I have an img icon be able to move around the screen and when they land on one of my what are currently buttons the new panel opens up and you get a mini game, i.e. true/false, maze, or word find.
Where I am currently at...
I made a basic null layout and put buttons as place holders where the players icon will go to to open the next panel.
I was working on putting a simple rectangle on the screen that would use arrow keyboard listener to move around. I watched tutorials online about creating this as well as searched this data base.
My current code still shows my null layout with with my map img background and buttons with img icons on those buttons. It will not show my rectangle.
Yes I am a student and this is a project from school, my hope is that you give me guidance in the right direction for the 3 main things I am trying to do here.
A. Get rectangle on screen and move it.
B. Get image icon on rectangle.
C. Where should I start with looking into making it so when the object that moves hits a certain spot JLable,Jbutton,Janything I can't think of how to bring up my new panel that I already have made.
Thank you for any help you all can provide.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class map extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5,this);
int x = 0, y = 0, velX = 0, velY = 0;
JButton mapButton, worldCampusB, universityParkB, fayetteB, erieB, yorkB,
hazeltonB;
JLabel background;
ImageIcon img;
public map(){
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setBackground(new Color(9, 49, 98));
setLayout(new BorderLayout());
ImageIcon oldmain = new ImageIcon("images/oldmain.jpg");
ImageIcon hazelton = new ImageIcon("images/hazelton.jpeg");
ImageIcon york = new ImageIcon("images/york.jpg");
ImageIcon erie = new ImageIcon("images/erie.jpg");
ImageIcon fayette = new ImageIcon("images/fayette.jpg");
ImageIcon worldcampus = new ImageIcon("images/worldcampus.png");
background = new JLabel(new ImageIcon("images/pennmap.jpg"));
add (background);
background.setLayout(null);
mapButton = new JButton("Map Menu: Click to return to main menu.");
mapButton.setBounds(new Rectangle(300,20,300,50));
worldCampusB = new JButton("World Campus");
worldCampusB.setIcon(worldcampus);
universityParkB = new JButton("University Park");
universityParkB.setIcon(oldmain);
fayetteB = new JButton("Fayette");
fayetteB.setIcon(fayette);
erieB = new JButton ("Erie");
erieB.setIcon(erie);
yorkB = new JButton ("York");
yorkB.setIcon(york);
hazeltonB = new JButton ("Hazelton");
hazeltonB.setIcon(hazelton);
background.add(mapButton);
background.add(worldCampusB);
background.add(universityParkB);
background.add(fayetteB);
background.add(erieB);
background.add(yorkB);
background.add(hazeltonB);
//adjusted the button locations on the map - jpk5816
worldCampusB.setBounds(new Rectangle (750,20,195,150));
worldCampusB.setHorizontalTextPosition(JButton.CENTER);
worldCampusB.setVerticalTextPosition(JButton.BOTTOM);
universityParkB.setBounds(new Rectangle(380,250,175,140));
universityParkB.setHorizontalTextPosition(JButton.CENTER);
universityParkB.setVerticalTextPosition(JButton.BOTTOM);
fayetteB.setBounds(new Rectangle(40,445,200,150));
fayetteB.setHorizontalTextPosition(JButton.CENTER);
fayetteB.setVerticalTextPosition(JButton.BOTTOM);
erieB.setBounds(new Rectangle(50,100,175,170));
erieB.setHorizontalTextPosition(JButton.CENTER);
erieB.setVerticalTextPosition(JButton.BOTTOM);
yorkB.setBounds(new Rectangle(625,460,185,130));
yorkB.setHorizontalTextPosition(JButton.CENTER);
yorkB.setVerticalTextPosition(JButton.BOTTOM);
hazeltonB.setBounds(new Rectangle(690,190,170,140));
hazeltonB.setHorizontalTextPosition(JButton.CENTER);
hazeltonB.setVerticalTextPosition(JButton.BOTTOM);
}
public void paintCompent(Graphics g){
super.paintComponent(g);
g.setColor(new Color(9, 49, 98));
g.fillRect(x, y, 50, 30);
}
public void actionPerformed(ActionEvent e){
repaint();
x += velX;
y += velY;
}
public void up(){
velY = -1;
velX = 0;
}
public void down(){
velY = 1;
velX = 0;
}
public void left(){
velX = -1;
velY = 0;
}
public void right(){
velX = 1;
velY = 0;
}
public void keyPressed(KeyEvent e){
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP){
up();
}
if (code == KeyEvent.VK_DOWN){
down();
}
if (code == KeyEvent.VK_LEFT){
left();
}
if (code == KeyEvent.VK_RIGHT){
right();
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}
Your JLabel's ImageIcon is being added to the drawing JPanel, the this or map JPanel (should be re-named "Map"), so that none of the drawing within map will display. But why do this? Why use a JLabel with ImageIcon as a background image when you're already overriding map's paintComponent? A better solution is to get rid of the background JLabel and simply draw that image within the paintComponent method of map, and then draw the rectangle after that.
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImg, 0, 0, this); // draw image
g.setColor(new Color(9, 49, 98));
g.fillRect(x, y, 50, 30);
}
// rename this to Map so that it complies with Java standards
public class Map extends JPanel implements ActionListener, KeyListener {
private static String IMAGE_PATH = "images/pennmap.jpg";
// ..... other code here
// JLabel background; // **** get rid of this ****
// ImageIcon img;
private BufferedImage backgroundImg;
// constructor needs to be re-named
public Map(){
backgroundImg = ImageIO.read(new File(IMAGE_PATH)); // read in image. Better to use resources though
// .... code here
// background = new JLabel(new ImageIcon("images/pennmap.jpg")); // again get rid of
// add (background); // get rid of
// .... code here
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImg, 0, 0, this); // draw image
g.setColor(new Color(9, 49, 98));
g.fillRect(x, y, 50, 30);
}
// .....
}
Found a way to draw the image that isn't the odd idea for a beginner in the other answer.
in myJPanel
public class myJPanel extends JPanel implements ActionListener {
ImageIcon img; //declare
public myJPanel(){
super();
setBackground(Color.white);
setLayout (new BorderLayout());
credits = new credits();
instructions = new instructions();
characterTheme = new characterTheme();
img = new ImageIcon("images/pennmap.jpg");//grab from images foler.
in map.java which is where I wanted the img drawn.
public class map extends JPanel {
ImageIcon img;
public map (ImageIcon img){
this.img = img;
Dimension size = new Dimension(getWidth(),getHeight());
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g){
g.drawImage(img.getImage(), 0, 0, null);
}
There was much more to the question but it appears there isn't much interest in it so I will close it at this. As this was my first hurdle in this mini project of making this game.

How to make button like music player using java.swing

Now I create gui music player with java. In java.swing.JButton, there are square buttons , but I want to customize that button like music player's button. How to make buttons like 'Play Button' in music player? And I also want stop and reset buttons, too.
play button is like ▶ this shape in circle.
stop button is like || this shape in circle.
reset button is like ■ this shape in circle.
thanks for your comment
You could simply set the text of the JButton as the symbol ▶
JButton button = new JButton("▶");
You need to save the .java file with UTF-8 character set though, in eclipse it's really easy as you get a popup.
It's the easiest but least customizable solution.
Another workaround would be to create an image with whatever symbol you wish the button to show. Then add a rectangle to the image's bounds. To check for mouse clicks, simply use a MouseListener and do something similar to this:
if(mouse.isClicked() && rect.contains(mouse.x, mouse.y) { //do stuff }
You can set the play like image to the JButton.
Save your image named "playname" to "path/to/image/" and call as shown in this code:
// JButton play = new JButton();
// assuming play is the place where you've added your JButton
ImageIcon playimg = new ImageIcon("path/to/image/playname");
play.setIcon(playimg);
You can similarly add the same logic for other buttons too.
You could make the button have an image in i, or make the image a button itself.
You can do it by setting the immage you want to the Button. This way you can have a button with Play Icon!
Example:
JButton button= new JButton();
ImageIcon img = new ImageIcon("imgfolder/name.png");
button.setIcon(img);
If you want to make custom button, there is only one easy way to do it. First way is find a custom button library or make your button from image.
Else you can try look on this another post.
Alternatively to using rendered images (like a PNG) and an ImageIcon, you could use Java2D Shapes/Areas.
E.g. to create a Play Area, do something like this:
final GeneralPath play = new GeneralPath();
play.moveTo(1.0/5.0, 1.0/5.0);
play.lineTo(1.0/5.0, 1.0*4.0/5.0);
play.lineTo(1.0*4.0/5.0, 1.0/2.0);
play.closePath();
final Area playArea = new Area(play);
To draw the shape as Icon, use this custom class:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
public class ShapeIcon implements Icon {
private final Shape shape;
private final Paint paint;
private final Color color;
private final int size;
private final boolean fill;
private final Stroke stroke;
public ShapeIcon(final Shape shape, final Color color, final int size) {
this(shape, color, size, true, new BasicStroke(0.5f));
}
public ShapeIcon(final Shape shape, final Color color, final int size, final boolean fill, final Stroke stroke) {
this.stroke = stroke;
this.fill = fill;
this.color = color;
// allow for customization of fill color/gradient
// a plain color works just as well—this is a little fancier
this.paint = new GradientPaint(0, 12, color.brighter(), 0, 20, color);
this.size = size;
// you could also define different constructors for different Shapes
if (shape instanceof Path2D) {
this.shape = ((Path2D)shape).createTransformedShape(AffineTransform.getScaleInstance(size, size));
} else if (shape instanceof Area) {
this.shape = ((Area) shape).createTransformedArea(AffineTransform.getScaleInstance(size, size));
} else {
this.shape = new Area(shape).createTransformedArea(AffineTransform.getScaleInstance(size, size));
}
}
#Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
final Graphics2D g2d = (Graphics2D)g.create();
g2d.translate(x, y);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (fill) {
g2d.setPaint(paint);
g2d.fill(shape);
}
g2d.setPaint(color);
g2d.setStroke(stroke);
g2d.draw(shape);
g2d.dispose();
}
#Override
public int getIconWidth() {
return size;
}
#Override
public int getIconHeight() {
return size;
}
}
Use the setBorder method of JButton.
roundButton.setBorder(new RoundedBorder(10));

How can I rotate rectangle in Java?

My rectangle code:
class Rectangle extends JPanel {
int x = 105;
int y= 100;
int width = 50;
int height = 100;
public void paint(Graphics g) {
g.drawRect (x, y, width, height);
g.setColor(Color.WHITE);
}
Rectangle r = new Rectangle();
and I have a button "rotate". When the user presses the button with the mouse, the rectangle must rotate 15 degrees.
This is my action code:
public void actionPerformed(ActionEvent e){
Object source = e.getSource();
if( source == rotate){
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(15), r.getX() + r.getWidth()/2, r.getY() + height/2);
r.add(transform);
}
}
But the code doesn't work. I don't know why? What do you think?
My edited-action-code part:
public void actionPerformed(ActionEvent e){
Object source = e.getSource();
if( source == rotate){
Paint p = new Paint();
panel1.add(r);
repaint();
}
}
class Paint extends JPanel {
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.WHITE);
g2d.translate(r.getX()+(r.WIDTH/2), r.getY()+(r.HEIGHT/2));
g2d.rotate(Math.toRadians(15));
r.equals(g2d);
repaint();
}
}
Custom painting is done by overriding the paintComponent() method, not paint(). Don't forget the super.paintComponent() at the start.
The paintComponent() method is where the painting is done so that is were you need the rotation code. So you could set a variable to indicate if you need to do the rotation or not. So all the ActionListener does is set the variable and then invoke repaint().
Or, I've never tried applying a rotation directly to the Rectangle (I've always applied it to the Graphics object in the painting method). Maybe you just need to invoke repaint() on the panel in your ActionListener. The panel won't know you've changed the Rectangle, so you need to tell it to repaint itself.

java.awt.Graphics change color after drawing

I have asked a similar question a while ago here, but didn't get an answer. The original question was about changing the color of a shape after clicking on it. But I am puzzled on how to access the shape at all after it is drawn.
This is my paintComponent method
#Override
protected void paintComponent(Graphics graph) {
super.paintComponent(graph);
Graphics2D g = (Graphics2D) graph;
// smooth graphics
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// moving to the middle of the panel
g.translate(this.getWidth()/2, this.getHeight()/2);
// painting colored arcs
for(int i = 0; i < 4; i++) {
g.setColor(dimColors[i]);
g.fill(arcs[i]);
}
// painting borders
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(5F));
g.drawLine(-98, 0, 98, 0);
g.drawLine(0, -98, 0, 98);
g.draw(circle);
// painting central white circle
g.setColor(Color.WHITE);
g.fill(smallCircle);
g.setColor(Color.BLACK);
g.draw(smallCircle);
}
the arcs[] array contains a bunch of Arc2D's that are drawn on the panel. My question is now, if I want to change the color of, for example arcs[0], how do I do that?
Thanks!
EDIT: I now have this MouseAdapter event
private class MyMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Component c = getComponentAt(p);
Graphics g = c.getGraphics();
dimColors[1] = Color.RED;
paintComponent(g);
}
}
And it works, it changes the color of arc[1] because arcs[1] has dimColors[1] set as color when drawing it.
However, I still can't figure out how to check wether the right arc was clicked. Right now you just click anywhere on the graphics panel and it changes the color of that specific arc
This doesn't answer your earlier question, however it does answer your question of click detection. To do this it is best to use Graphics2D because it is a lot easier to write than most other options. Here is an example:
public class GraphicsPanel extends JPanel implements MouseListener
{
private Rectangle2D rect;
First we create our Graphics2D rectangle rect.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)(g);
g2d.setColor(Color.GREEN);
rect = new Rectangle2D.Double(70, 70, 100, 100);
g2d.fill(rect);
this.addMouseListener(this);
}
And then we override the paintComponent method and create our new Rectangle2D.Double object.
We then fill the rectangle with g2d.fill() and then add a mouse listener to the JPanel.
public void mousePressed(MouseEvent e)
{
if(rect.contains(e.getX(), e.getY()))
System.out.println("Rectangle clicked");
}
}
Finally, we need to see if that rectangle contains the point where the user clicked. To do this, simply see if the rectangle we created contains the user's click location by using the Rectangle2D.double's contains(int x, int y) method. That's it!
if I want to change the color of, for example arcs[0], how do I do that?
A line (or whatever) only exists as a bunch of pixels that were painted in the original color. To change its color you must change the current color and draw it again.

Categories

Resources