Java GUI drawing an image on mouse event - java

I'm making a program where hovering over a grid will place an image into the cell hovered over. Currently I have it working so that only a color is filled in, but I have no idea how to make it so an image is drawn in instead. Here's my program:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class Test
{
Image img=Toolkit.getDefaultToolkit().getImage("img.gif");
public static void main(String[]args)
{
new Test();
}
public Test()
{
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PixelGrid());
frame.setSize(new Dimension(364,357));
frame.setVisible(true);
}
public class PixelGrid extends JPanel
{
private List<Shape>grid,square;
public PixelGrid()
{
grid=new ArrayList<>();
square=new ArrayList<>();
addMouseMotionListener(new MouseAdapter()
{
public void mouseMoved(MouseEvent e)
{
for(Shape shape:grid)
{
if(shape.contains(e.getPoint()))
square.add(shape);
}
repaint();
}
}
);
for(int row=0;row<5;row++)
{
for(int col=0;col<5;col++)
grid.add(new Rectangle(col*25+112,row*25+50,25,25));
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawLine(112,50,237,50);
g.drawLine(112,75,237,75);
g.drawLine(112,100,237,100);
g.drawLine(112,125,237,125);
g.drawLine(112,150,237,150);
g.drawLine(112,175,237,175);
g.drawLine(112,50,112,175);
g.drawLine(137,50,137,175);
g.drawLine(162,50,162,175);
g.drawLine(187,50,187,175);
g.drawLine(212,50,212,175);
g.drawLine(237,50,237,175);
Graphics2D g2=(Graphics2D)g;
for(Shape cell:square)
g2.fill(cell);
}
}
}
I want to make the image "img" become the "pixel" that is filled in. However, I'm confused on how to do this as I don't think I can use for-each loops and Graphics2D. If anyone can help, thanks so much!

Define ImageHolder class which has 2 fields shape and image.
class ImageHolder {
Shape shape;
Image img;
public void paint(Graphics2D g2) {
if (img!=null) {
g2.drawImage(img);
}
else {
g2.fill(shape);
}
}
}
Your grid should be List. On init all the ImageHolders have squares and null images. On click image is assigned to the clicked holder.
In the paintComponent() you just call the holder's paint() method

take a look at this one.
all you need to do is repalce your g2.fill(cell); with g2.drawImage(img,cell.getBounds().x,cell.getBounds().y,null);
read drawimage api here
for (Shape cell : square) {
//g2.fill(cell);
g2.drawImage(img,cell.getBounds().x,cell.getBounds().y,null);
System.out.println(cell.getBounds().x);
}
however use Dimention list or 2D list instead Shape in this case
complete code
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class Test {
Image img = Toolkit.getDefaultToolkit().getImage("img.gif");
public static void main(String[] args) {
new Test();
}
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PixelGrid());
frame.setSize(new Dimension(364, 357));
frame.setVisible(true);
}
public class PixelGrid extends JPanel {
int x=0;
int y=0;
private List<Shape> grid, square;
public PixelGrid() {
grid = new ArrayList<>();
square = new ArrayList<>();
addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
for (Shape shape : grid) {
if (shape.contains(e.getPoint())) {
square.add(shape);
}
}
repaint();
}
}
);
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 5; col++) {
grid.add(new Rectangle(col * 25 + 112, row * 25 + 50, 25, 25));
}
}
}
public void paintComponent(Graphics g) {
System.out.println(x);
g.drawLine(112, 50, 237, 50);
g.drawLine(112, 75, 237, 75);
g.drawLine(112, 100, 237, 100);
g.drawLine(112, 125, 237, 125);
g.drawLine(112, 150, 237, 150);
g.drawLine(112, 175, 237, 175);
g.drawLine(112, 50, 112, 175);
g.drawLine(137, 50, 137, 175);
g.drawLine(162, 50, 162, 175);
g.drawLine(187, 50, 187, 175);
g.drawLine(212, 50, 212, 175);
g.drawLine(237, 50, 237, 175);
Graphics2D g2 = (Graphics2D) g;
//g2.drawImage(img,x,y,null);
for (Shape cell : square) {
//g2.fill(cell);
g2.drawImage(img,cell.getBounds().x,cell.getBounds().y,null);
System.out.println(cell.getBounds().x);
}
}
}
}
output>>

Related

How Can This Stickman Be Made to Be Interactive?

So, I need to make the stick-man movable by a user-input. When the user clicks on a part (Head, hands, feet and posterior) and he should move, and have no idea how to go about this..
If possible, there also needs to be a confine around the character, likely rectangular, so that there is a limit to how far each part can be pulled.
See below for my code;
// Created by Charlie Carr - (28/11/17 - /11/17)
import java.awt.*;
import java.applet.Applet;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
//Imports complete
//Suppress warning about undeclared static final serialVersionUID field in VS Code
#SuppressWarnings("serial")
public class Animator extends JPanel {
public static class AnimatorWindow extends JPanel {
public void paint(Graphics page) {
setBackground(Color.gray);
setForeground(Color.white);
super.paintComponent(page);
page.drawString("Stickmen Animation Station", 150, 15);
//draw the head
//x1, y1, x2, y2
page.drawOval(90, 60, 20, 20);
// draw the body
page.drawLine(100, 80, 100, 110);
// draw the hands
page.drawLine(100, 90, 80, 105);
page.drawLine(100, 90, 120, 105);
//draw the legs, he hasn't a leg to stand on..
page.drawLine(100, 110, 85, 135);
page.drawLine(100, 110, 115, 135);
}
}
public static void main(String[] args) {
AnimatorWindow displayPanel = new AnimatorWindow();
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
//declare window size
int x = 480;
int y = 240;
JFrame window = new JFrame("GUI");
window.setContentPane(content);
window.setSize(x, y);
window.setLocation(101, 101);
window.setVisible(true);
}
}
Use MouseListenerto deal with mouse events.
Also, you should override the paintComponent() method instead of paint(), because paint() also paints the border and other stuff.
public static class AnimatorWindow extends JPanel implements MouseListener{
public AnimatorWindow(){
setBackground(Color.gray);
setForeground(Color.white);
//add the listener
addMouseListener(this);
}
public void paintComponent(Graphics page) {
super.paintComponent(page);
//You should not alter the Graphics object passed in
Graphics2D g = (Graphics2D) page.create();
//draw your stuff with g
g.drawString("Stickmen Animation Station", 150, 15);
.......
//finish
g.dispose();
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseClicked(MouseEvent e){
//implement your clicking here
//Use e.getX() and e.getY() to get the click position
}
}
For more on swing events, check this site
EDIT: Your problem also includes animation, and you can use a javax.swing.Timer to do that.

Adding a JLabel to my clock face isn't working

I tried, adding the flowlayout as seen in other answers, but it still doesn't work.
I've also tried moving around my JLabel code into a constructor but that doesn't work either.
public class Paint {
public static void main(String[] args) {
JFrame frame = new JFrame("Paint");
frame.setSize(500,500);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
Draw draw = new Draw();
frame.add(draw);
frame.setVisible(true);
}
}
public class Draw extends JPanel{
public Draw(){
JLabel one = new JLabel("12",JLabel.CENTER);
setLayout(new FlowLayout());
add(one);
}
public void paint(Graphics g){
g.drawOval(70, 60, 190, 190);
g.setColor(Color.BLACK);
g.drawLine(90, 160, 170, 160);
g.drawLine(120, 190,170 , 160);
g.setColor(Color.GRAY);
g.fillOval(155, 153, 20, 20);
}
}
Change paint to override paintComponent
Call super.paintComponent before doing any custom painting
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Paint {
public static void main(String[] args) {
JFrame frame = new JFrame("Paint");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
Draw draw = new Draw();
frame.add(draw);
frame.setVisible(true);
}
public static class Draw extends JPanel {
public Draw() {
JLabel one = new JLabel("12", JLabel.CENTER);
setLayout(new FlowLayout());
add(one);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(70, 60, 190, 190);
g.setColor(Color.BLACK);
g.drawLine(90, 160, 170, 160);
g.drawLine(120, 190, 170, 160);
g.setColor(Color.GRAY);
g.fillOval(155, 153, 20, 20);
}
}
}

Saving JTable values to array

I wrote the self contained example below and I have it working pretty much the way I want except for one thing. Currently, if the user clicks an Ellipse2D it will highlight a cell in the JTable and allow them to input strings. The problem is that when you close the program it doesn't save the values to Object[][] data.
How do I save the input to Object[][] data so that the next time I run the application it is present?
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class SelfContainedExample extends JPanel implements MouseListener {
private Map<Ellipse2D.Double, Point> shapesMap = new HashMap<>();
private Ellipse2D.Double[] ellipses = new Ellipse2D.Double[] {
new Ellipse2D.Double(50, 100, 30, 30),
new Ellipse2D.Double(175, 100, 30, 30),
new Ellipse2D.Double(300, 100, 30, 30),
new Ellipse2D.Double(50, 160, 30, 30),
new Ellipse2D.Double(175, 160, 30, 30),
new Ellipse2D.Double(300, 160, 30, 30)};
static Object[][] data = {{"1_1", "1_2", "1_3"},
{"2_1", "2_2", "2_3"},
{"3_1", "2_2", "2_3"},
{"4_1", "2_2", "2_3"},
{"5_1", "2_2", "2_3"},
{"6_1", "2_2", "2_3"}};
static Object[] columnNames = {"1", "2", "3"};
static JTable jtable = new JTable(data, columnNames);
public static void main(String[] args)
{
EventQueue.invokeLater(() -> createAndShowGUI());
}
public SelfContainedExample() {
int row = 0;
int column = 0;
for (Ellipse2D.Double ellipse : ellipses) {
shapesMap.put(ellipse, new Point(row, column));
row++;
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(Color.BLACK);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2d.fill(ellipse);
}
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.GRAY);
for (Ellipse2D ellipse : ellipses) {
g2d.draw(ellipse);
}
addMouseListener(this);
g2d.dispose();
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Example");
JPanel panel = new JPanel();
JPanel tablePanel = new JPanel();
JScrollPane jScrollPane = new JScrollPane(jtable);
jScrollPane.setPreferredSize(new Dimension(385, 119));
tablePanel.add(jScrollPane);
tablePanel.setSize(200, 200);
panel.setLayout(new BorderLayout());
panel.add(new SelfContainedExample(), BorderLayout.CENTER);
panel.add(tablePanel, BorderLayout.SOUTH);
panel.setOpaque(true);
panel.setVisible(true);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationByPlatform(false);
frame.setLocationRelativeTo(null);
frame.setContentPane(panel);
frame.setVisible(true);
}
#Override
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
for (Ellipse2D.Double ellipse : ellipses) {
if (ellipse.contains(e.getPoint())) {
jtable.requestFocusInWindow();
Point p = shapesMap.get(ellipse);
jtable.editCellAt(p.x, p.y);
break;
}
}
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
}

Jbutton issues within my code

i have been working on a flashing beacon on java using Jpanel, paint component and timers, however i am having trouble trying to get the buttons within the code to function. when the code is run, the flash button is supposed to prompt the beacon to start blinking/flashing whereas the steady button keeps it on the same colour. the alternating colours for the beacon are orange and grey.As well as this i cant seem to get rid of a button that keeps appearing in the top left of the window when the code is run. so far, this is what i have
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
/**
* Created by Enoch on 26/03/2015.
*/
class BelishaBeacon extends JPanel {
Color startLight, stopLight, color;
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(color);
Ellipse2D firstOval = new Ellipse2D.Double(130, 70, 50, 50);
g2.draw(firstOval);
g2.fill(firstOval);
g2.setColor(Color.BLACK);
Rectangle rect1 = new Rectangle(150, 119, 10, 35);
g2.draw(rect1);
g2.fill(rect1);
g2.setColor(Color.WHITE);
Rectangle rect2 = new Rectangle(150, 150, 10, 35);
g2.draw(rect2);
g2.fill(rect2);
g2.setColor(Color.BLACK);
Rectangle rect3 = new Rectangle(150, 180, 10, 35);
g2.draw(rect3);
g2.fill(rect3);
g2.setColor(Color.WHITE);
Rectangle rect4 = new Rectangle(150, 210, 10, 35);
g2.draw(rect4);
g2.fill(rect4);
g2.setColor(Color.BLACK);
Rectangle rect5 = new Rectangle(150, 240, 10, 35);
g2.draw(rect5);
g2.fill(rect5);
g2.setColor(Color.WHITE);
Rectangle rect6 = new Rectangle(150, 270, 10, 35);
g2.draw(rect6);
g2.fill(rect6);
g2.setColor(Color.BLACK);
Rectangle rect7 = new Rectangle(150, 300, 10, 35);
g2.draw(rect7);
g2.fill(rect7);
g2.setColor(Color.WHITE);
Rectangle rect8 = new Rectangle(150, 330, 10, 35);
g2.draw(rect8);
g2.fill(rect8);
g2.setColor(Color.BLACK);
Rectangle rect9 = new Rectangle(150, 360, 10, 35);
g2.draw(rect9);
g2.fill(rect9);
g2.setColor(Color.WHITE);
Rectangle rect10 = new Rectangle(150, 390, 10, 35);
g2.draw(rect10);
g2.fill(rect10);
}
public BelishaBeacon() {
startLight = Color.ORANGE;
stopLight = Color.LIGHT_GRAY;
color = startLight;
new Blinker(this);
setBackground(Color.white);
}
public void blink()
{
color = (color == startLight ? stopLight : startLight);
repaint();
}
}
//
class Blinker
{
BelishaBeacon blinkPanel;
public Blinker(BelishaBeacon bp)
{
blinkPanel = bp;
new Timer(500, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
blinkPanel.blink();
}
}).start();
}
}
//
class BelishaBeaconViewer extends JFrame {
JButton jbtFlash = new JButton("Flash");
JButton jbtSteady = new JButton("Steady");
JPanel bPanel = new JPanel();
BelishaBeacon bBPanel = new BelishaBeacon();
public BelishaBeaconViewer() {
bPanel.add(jbtFlash);
this.add(bPanel, BorderLayout.SOUTH);
bPanel.add(jbtSteady);
this.add(bBPanel, BorderLayout.CENTER);
jbtFlash.addActionListener(new FlashListener());
jbtSteady.addActionListener(new SteadyListener());
}
class FlashListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
repaint();
}
}
class SteadyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
repaint();
}
}
public static void main(String[] args) {
JFrame bBFrame = new BelishaBeaconViewer();
bBFrame.setTitle("Belisha Beacon");
bBFrame.setSize(300, 300);
bBFrame.setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
bBFrame.setVisible(true);
}
}
i cant seem to get rid of a button that keeps appearing in the top left of the window
//super.paintComponents(g); // typo
super.paintComponent(g); // should be
Don't start the Timer automatically.
The FlashListener should start the Timer, no need for the repaint
The SteadyListner should stop the Timer, no need for the repaint.

JButton not shown on screen

Im trying to make an application that will change the state of a traffic light in the click of a button.
My code: Main
import javax.swing.*;
public class PP416
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Traffic light");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TrafficPanel());
frame.pack();
frame.setVisible(true);
}
}
JPanel Class:
import javax.swing.*;
import java.awt.*;
import java.awt.Event;
public class TrafficPanel extends JPanel
{
private JButton button;
private int indicator = 0; // Light is off
public TrafficPanel()
{
button = new JButton("Change");
this.add(button);
}
public void paint(Graphics g)
{
if (indicator == 0)
{
g.drawOval(30, 40, 30, 30);
g.drawOval(30, 70, 30, 30);
g.drawOval(30, 100, 30, 30);
}
}
}
the button just not appearing , just the ovalls.
anyone can help me with this?
Don't override paint but rather paintComponent and Most important, call the super's method. Your lack of a super call may be preventing your JPanel from drawing its child components well.
e.g.,
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (indicator == 0) {
g.drawOval(30, 40, 30, 30);
g.drawOval(30, 70, 30, 30);
g.drawOval(30, 100, 30, 30);
}
}

Categories