I m making App in netbeans platform using java swing Technology.I want to do image processing oncaptured image.This image is capture by X-Ray Gun.after that i want to increase/decrease brightness of image using JSlider.I done this using paintComponent(Graphics g) method. but i want to do direct effect of increased/decreased brightnees of image without using paintComponenet(Graphics g) method.so how can i do that? My code is shown below. In my code i use PlanarImage and BufferedImage class of JAI library for load .tiff imge and after that i use statechange event of JSlider object for increase/decrease brightness of image.
enter code here
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main extends JPanel implements ChangeListener {
RescaleOp op;
PlanarImage image = JAI.create("fileload", "F:\\java\\aimages\\teeth1.tiff");
BufferedImage bufferedImage = image.getAsBufferedImage();
BufferedImage bImage;
int x1 = bufferedImage.getWidth();
int y1 = bufferedImage.getHeight();
JSlider slider = new JSlider(-10, 10);
public Main() {
bImage=bufferedImage;
slider.addChangeListener(this);
this.add(slider, BorderLayout.class);
// this.add(new JLabel(new ImageIcon(bufferedImage)), BorderLayout.NORTH);
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(bufferedImage, 0, 0, x1, y1, null);
}
public static void main(String[] argv) throws Exception {
JFrame jFrame = new JFrame();
jFrame.add(new Main());
jFrame.setVisible(true);
jFrame.setSize(200, 200);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void stateChanged(ChangeEvent e) {
JSlider slid = (JSlider) e.getSource();
float value = (float) slid.getValue();
setValue(value);
}
private void setValue(float value) {
bufferedImage=bImage;
float scaleFactor = (float) (1.0 + (value / 10.0));
op = new RescaleOp(scaleFactor, 0, null);
bufferedImage = op.filter(bufferedImage, null);
repaint();
}
}
It's not clear why you want to avoid paintComponent(), but you can always alter the BufferedImage in a JLabel's ImageIcon using RescaleOp.
Addendum: I sounds like you don't want to overwrite the original image, so naturally it makes sense to alter a copy. Unfortunately, your example merely copies a reference to the original. Instead, use two copies, passing the original as src and the copy as dst, as shown the example below. See also AlphaTest.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* #see https://stackoverflow.com/q/10208255/230513
* #see https://stackoverflow.com/questions/5838842
* #see https://stackoverflow.com/questions/5864490
*/
public class RescaleTest extends JPanel implements ChangeListener {
private static final String NAME = "image.jpg";
private BufferedImage image, copy;
private JSlider slider = new JSlider();
public RescaleTest() {
PlanarImage pi = JAI.create("fileload", NAME);
image = pi.getAsBufferedImage();
copy = pi.getAsBufferedImage();
this.setLayout(new BorderLayout());
this.add(new JLabel(new ImageIcon(copy)));
this.add(slider, BorderLayout.SOUTH);
slider.setValue(slider.getMaximum() / 2);
slider.addChangeListener(this);
}
#Override
public void stateChanged(ChangeEvent e) {
float value = (float) slider.getValue();
float scaleFactor = 2 * value / slider.getMaximum();
RescaleOp op = new RescaleOp(scaleFactor, 0, null);
copy = op.filter(image, copy);
repaint();
}
private void display() {
JFrame f = new JFrame("RescaleTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new RescaleTest().display();
}
});
}
}
Related
package imgscoring;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import static java.lang.System.exit;
public class IMGSCORING
{
private JButton button1;
private JPanel main;
private JButton button2;
private JLabel lblLed;
private JButton button3;
private JLabel label;
private JLabel logo;
private static Image i;
public IMGSCORING() {
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
try {
runProgam();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
exit(1);
}
});
Image i = Toolkit.getDefaultToolkit().createImage("C:\\Users\\djuwo\\Desktop\\icon.jpg");
}
public static void paint(Graphics g)
{
g.drawImage(i, 0, 0, null);
}
public void runProgam() throws IOException, InterruptedException {
QrScanner run = new QrScanner();
run.runProgram();
}
public JPanel getMain() {
return main;
}
public void setMain(JPanel main) {
this.main = main;
}
public static void main(String[] args) {
JFrame frame = new JFrame(" IMG FORMING Label Generator");
frame.setContentPane(new IMGSCORING().main);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ImageIcon img = new ImageIcon("C:\\Users\\djuwo\\Desktop\\icon.jpg");
frame.setIconImage(img.getImage());
}
private void createUIComponents() {
// TODO: place custom component creation code here
logo = new JLabel(new ImageIcon("icon.jpg"));
}
}
I am very new to using the gui for Java and based on looking around and seeing others code I can definitely tell mine is way off from how it should look.. Would appreciate feedback on how to properly format my code as well as how to add a background. The program works and buttons respond, icon are changed, etc. But I am unable to change the background. At first I tried the following but that obviously didn't work.
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\djuwo\\Desktop\\icon.jpg")))));
In the following solutions, you can see the following steps:
Override paintComponent of JPanel, in order to draw the image in its background.
Add any elements you want in the subclassed JPanel.
Add the subclassed JPanel to the content pane of the JFrame.
setOpaque(false) in the subclassed JPanel in order to show the background (where we paint the image).
In the first solution, I just paint the image once and not care about filling the frame when it is resized:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class RegularMain extends JPanel {
private final BufferedImage bimg;
public RegularMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
g.drawImage(bimg, 0, 0, this);
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RegularMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
But, another approach is to resize the image to correspond to the panel's size:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TransformMain extends JPanel {
private final BufferedImage bimg;
public TransformMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(getWidth() / (double) bimg.getWidth(), getHeight() / (double) bimg.getHeight());
g2d.drawImage(bimg, 0, 0, this);
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TransformMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
And finally another approach is to make the image a TexturePaint, if you want the image to be repeated:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TextureMain extends JPanel {
private final TexturePaint paint;
public TextureMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
paint = new TexturePaint(bimg, new Rectangle2D.Double(0, 0, bimg.getWidth(), bimg.getHeight()));
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(paint);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TextureMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The difference in the solutions above is visible when the frame/panel is resized. In the first case, the frame is not supposed to be resized so we only draw the image once, without changing it in size. In the second case the image size follows the panel's size. And in the final case we repeat the image vertically and horizontally up to the panel's size (by using TexturePaint).
All the cases have in common that we paint the image in paintComponent before everything else and that we setOpaque to false.
I have written a Java code to draw a polygon on an image. When I put my cursor inside the polygon it prints "Inside" otherwise "Outside". So the detection of the points inside the polygon is working fine.
But I want to implement the effect of setToolTipText inside the polygon i.e. at the time of mouse hover inside the polygon, it will show the floating text "Inside".
Similar to the effect in this image:
http://www.java2s.com/Code/Java/Swing-JFC/WorkingwithTooltipText.htm
What are the minimal changes to be made in the following code to get the desired effect?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.image.*;
import java.awt.Graphics.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
class page1 extends JFrame implements MouseListener,MouseMotionListener ,ActionListener
{
JFrame f;
JLabel l;
JPanel p1;
ImageIcon ii;
Image img;
int height;
int width;
Container c;
int pixels[];
PixelGrabber pg;
JPanel panel;
Graphics2D gg;
Polygon pp1=new Polygon();
boolean startHovercurrent,startHoverprev=false;
page1()
{
f=new JFrame("Sample Page");
ii=new ImageIcon("sample.jpg");
img=ii.getImage();
height=ii.getIconHeight();
width=ii.getIconWidth();
pixels=new int[ii.getIconWidth()*ii.getIconHeight()];
pg=new PixelGrabber(img,0,0,ii.getIconWidth(),ii.getIconHeight(),pixels,0,ii.getIconWidth());
try
{
pg.grabPixels();
}
catch(InterruptedException k)
{
}
//add points of polygon
pp1.addPoint(300,300);
pp1.addPoint(380,300);
pp1.addPoint(380,220);
pp1.addPoint(300,220);
l=new JLabel(ii,JLabel.CENTER);
c=f.getContentPane();
JDesktopPane desk = new JDesktopPane();
JInternalFrame p = new JInternalFrame("Image Frame",false, false, true, false);
JScrollPane scroll = new JScrollPane(l);
p.setContentPane(scroll);
p.setBounds(0, 0, 740, 600);
desk.add(p);
p.setVisible(true);
l.addMouseListener(this);
l.addMouseMotionListener(this);
c.add(desk, BorderLayout.CENTER);
f.setSize(1024,738);
f.setVisible(true);
}
public static void main(String args[])
{
new page1();
}
public void mouseClicked(MouseEvent me)
{
}
public void mouseEntered(MouseEvent me)
{
}
public void mouseExited(MouseEvent me)
{
}
public void mousePressed(MouseEvent me)
{
}
public void mouseReleased(MouseEvent me)
{
}
public void mouseMoved(MouseEvent me)
{
boolean contain1;
int mx,my;
gg=(Graphics2D)l.getGraphics();
gg.setColor(new Color(255,0,0) );
gg.fillPolygon(pp1);
mx = me.getX();
my = me.getY();
//check if mouse cursor is inside polygon or not
// do not print anything if next cursor position is in same state
contain1=pp1.contains(mx,my);
if (contain1) {
startHovercurrent = true;
if(startHovercurrent!=startHoverprev)
System.out.println("Inside");
startHoverprev=startHovercurrent;
}
else {
startHovercurrent = false;
if(startHovercurrent!=startHoverprev)
System.out.println("Outside");
startHoverprev=startHovercurrent;
}
}
public void mouseDragged(MouseEvent me)
{
}
public void actionPerformed(ActionEvent ae)
{
}
}
For this usage, How to Use Tool Tips suggests overriding the getToolTipText() method of the enclosing JComponent. This answer outlines the approach for JMapViewer and ChartPanel. In the example below, getToolTipText() simply returns the name of any Shape that contains() the triggering mouse event. For comparison, the JLabel at window's bottom gets a conventional too tip via setToolTipText().
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
/**
* #see https://stackoverflow.com/a/53609066/230513
* #see https://stackoverflow.com/a/25944439/230513
*/
public class ShapeToolTip {
private static class ShapePanel extends JPanel {
private final List<Shape> list = new ArrayList<>();
public ShapePanel() {
Polygon p = new Polygon();
p.addPoint(500, 100);
p.addPoint(500, 400);
p.addPoint(200, 400);
list.add(p);
list.add(new Ellipse2D.Double(100, 100, 200, 200));
ToolTipManager.sharedInstance().registerComponent(this);
}
#Override
public String getToolTipText(MouseEvent e) {
for (Shape shape : list) {
if (shape.contains(e.getX(), e.getY())) {
return shape.getClass().getName();
}
}
return "Outside";
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(2));
for (Shape shape : list) {
g2d.draw(shape);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}
private void display() {
JFrame f = new JFrame("ShapeToolTip");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new ShapePanel());
JLabel title = new JLabel("Shape Tool Tip", JLabel.CENTER);
title.setToolTipText("Title");
title.setFont(title.getFont().deriveFont(Font.BOLD, 24));
f.add(title, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new ShapeToolTip()::display);
}
}
I'm trying to make a 2d side scrolling game. I have been able to display the background but as soon as I add a sprite the only thing displayed on the frame is the sprite. (Sorry if this is a simple mistake but I am new to java)
Here is my main class
package com.projectelrond.main;
import javax.swing.JFrame;
import com.projectelrond.Sprites.Ranger;
public class Main {
public int WIDTH = 160, HEIGHT = WIDTH/12 *9, SCALE = 3;
public boolean running = false;
BackGround bg = new BackGround();
JFrame f = new JFrame("name");
public static void main(String[] args) {
new Main();
}
public Main() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(WIDTH * SCALE, HEIGHT * SCALE);
f.setResizable(false);
f.add(new BackGround());
f.add(new Ranger());
f.setVisible(true);
running = true;
run();
}
public void run() {
while (running) {
//handles in game events NPCs, Traps etc.
}
}
}
My Background class
package com.projectelrond.main;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class BackGround extends JPanel {
private static final long serialVersionUID = 1L;
public BufferedImage Bg;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(Bg, 0, 0, null);
}
public BackGround() {
try {
Bg = ImageIO.read(new File("src/Images/BG.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
and last but not least the sprite that I am trying to add
package com.projectelrond.Sprites;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Ranger extends JPanel{
private static final long serialVersionUID = 1L;
public BufferedImage RangerIm;
public Ranger() {
try {
RangerIm = ImageIO.read(new File("src/Images/Sprites/Ranger.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(RangerIm, 0, 0, null);
}
}
Thanks for all the help and if there are any tips that you wish to share they will be much obliged.
g.drawImage(RangerIm, 0, 0, null);
You are drawing the image at its actual size. There is no need to do custom painting for this. You would do custom painting if you want to scale the image.
Instead you can just use a JLabel with an ImageIcon:
BufferedImage rangerIm = ImageIO.read(new File("src/Images/Sprites/Ranger.png"));
JLabel ranger = new JLabel( new ImageIcon(rangerIm) );
ranger.setSize( ranger.getPreferredSize() );
BufferedImage backgroundIm = Bg = ImageIO.read(new File("src/Images/BG.png"));
JLabel background = new JLabel( new ImageIcon(rangerIm) );
background.add( ranger );
f.add(background, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.pack();
f.setVisible(true);
Now the ranger is added to the background which is added to the frame. Also, you need to add the components to the frame BEFORE the frame is visible(). The pack() method will make the frame the size of the background image.
In an attempt to make a very simple bullet-hell game to learn about java, I ran into a roadblock: repaint() wasn't calling paintComponent().
Here is the entire program, which for now simply draws an image I created 50 times per second onto a JPanel, which rests on a JFrame.
/*
* Bullet hell, by Nematodes
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class bulletHell extends JFrame
{
private static final long serialVersionUID = 0L;
JPanel gamePanel = new JPanel();
int gameTimerDelay = 20;
int x, y = 0;
BufferedImage lightOrb;
javax.swing.Timer gameTimer;
public static void main(String[] args)
{
bulletHell createFrame = new bulletHell();
createFrame.frameConstructor();
}
public void frameConstructor()
{
// Construct frame and frame components
setTitle("Bullet hell");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
getContentPane().setLayout(new GridBagLayout());
setVisible(true);
GridBagConstraints gridConstraints;
gridConstraints = new GridBagConstraints();
gridConstraints.gridx = 0;
gridConstraints.gridy = 0;
gamePanel.setBackground(Color.BLACK);
gamePanel.setPreferredSize(new Dimension(700, 700));
getContentPane().add(gamePanel, gridConstraints);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((int) (0.5 * (screenSize.width - getWidth())),
(int) (0.5 * (screenSize.height - getHeight())), getWidth(), getHeight());
try
{
lightOrb = ImageIO.read(new File("C:/Users/Owner/Downloads/orb.bmp"));
}
catch(IOException e)
{
System.out.println("An issue occurred while trying to read orb.bmp");
}
// Start timer that draws game objects 50 times per second (50 FPS)
gameTimer = new javax.swing.Timer(gameTimerDelay, gameTimerAction);
gameTimer.setInitialDelay(0);
gameTimer.start();
}
ActionListener gameTimerAction = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
};
class GraphicsPanel extends JPanel
{
public GraphicsPanel()
{
}
// Draw all of the components
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2D = (Graphics2D) g;
super.paintComponent(g2D);
g2D.drawImage(lightOrb, x, y, this);
g2D.dispose();
}
}
}
After some debugging with breakpoints and println methods, I can confirm that the correct image is being read, the timer in gameTimerAction is being called 50 times per second, and repaint() is not invoking paintComponent() at all.
I am somewhat new to Java programming, and might just be missing something simple.
Edit: Problem has been solved by changing gamePanel to a GraphicsPanel object. Unfortunately, this also means that my much larger pong project (which this project's flawed drawing logic was essentially copied from) only worked by a miracle, and might be unstable with certain code additions.
I can immediately see several problems:
Most Important: You never instantiate a GraphicsPanel object, nor do you add it to anything. The paintComponent(...) method will never be called on a JPanel that is neither rendered nor created. Why not make your gamePanel variable a GraphicsPanel object and not a JPanel object?
You never change x and y in your Timer, and so without change, no animation will occur.
Also you're calling dispose on a Graphics object given to you by the JVM, something you should never do. This breaks the Swing painting chain making the graphics of your GUI unstable.
So keep at it, you'll get there.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class BulletExample extends JPanel {
public static final String IMG_PATH = "http://www.i2clipart.com/cliparts/f/0/5/8/clipart-blue-circle-f058.png";
private static final int PREF_W = 700;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 20;
private BufferedImage bullet;
private int bulletX;
private int bulletY;
public BulletExample() throws IOException {
URL imgUrl = new URL(IMG_PATH);
bullet = ImageIO.read(imgUrl);
new Timer(TIMER_DELAY, new BulletListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bullet != null) {
g.drawImage(bullet, bulletX, bulletY, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class BulletListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
bulletX++;
bulletY++;
repaint();
}
}
private static void createAndShowGui() throws IOException {
// create the drawing JPanel
BulletExample mainPanel = new BulletExample();
JFrame frame = new JFrame("BulletExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// add it to the JFrame
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
I draw in my JComponent some curves, etc .. with Graphics G ( not 2D ).
Now I want to use the scroll wheel of my mouse to zoom in and out.
Any tracks ?
I heard talk about a BuferredImage ?
There are a few considerations you need to take into account...
The end result will depend on what you want to achieve. If you are drawing curves using the Graphics2D API, it might be simpler to simply scale the coordinates each time the component is rendered. You will need to make sure that any changes in the scale are reflected in the preferred size of the component itself.
You could also render the "default" output to a BufferedImage and simply use an AffineTransform to change the scaling the is used to render the result, for example.
This simple uses a BufferedImage and loads a picture from disk, but the basic concept is the same.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ZoomPane {
public static void main(String[] args) {
new ZoomPane();
}
public ZoomPane() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(new TestPane()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
private float scale = 1;
public TestPane() {
try {
img = ImageIO.read(new File("/path/to/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseWheelListener(new MouseAdapter() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
double delta = 0.05f * e.getPreciseWheelRotation();
scale += delta;
revalidate();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
Dimension size = new Dimension(200, 200);
if (img != null) {
size.width = Math.round(img.getWidth() * scale);
size.height = Math.round(img.getHeight() * scale);
}
return size;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = new AffineTransform();
at.scale(scale, scale);
g2d.drawImage(img, at, this);
g2d.dispose();
}
}
}
}
You could also scale the Graphics context passed to your paintComponent method directly.
The important thing here is to remember to reset the AffineTransform after you have completed, otherwise it will be passed to other components when they are rendered, which won't generate the expected output...
This example basically creates a copy of the Graphics context which we can manipulate and dispose of without effecting the original, making it simpler to mess with
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ZoomPane {
public static void main(String[] args) {
new ZoomPane();
}
public ZoomPane() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(new TestPane()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private float scale = 1;
public TestPane() {
addMouseWheelListener(new MouseAdapter() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
double delta = 0.05f * e.getPreciseWheelRotation();
scale += delta;
revalidate();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
Dimension size = new Dimension(200, 200);
size.width = Math.round(size.width * scale);
size.height = Math.round(size.height * scale);
return size;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = new AffineTransform();
at.scale(scale, scale);
g2d.setTransform(at);
g2d.setColor(Color.RED);
// This is for demonstration purposes only
// I prefer to use getWidth and getHeight
int width = 200;
int height = 200;
Path2D.Float path = new Path2D.Float();
int seg = width / 3;
path.moveTo(0, height / 2);
path.curveTo(0, 0, seg, 0, seg, height / 2);
path.curveTo(
seg, height,
seg * 2, height,
seg * 2, height / 2);
path.curveTo(
seg * 2, 0,
seg * 3, 0,
seg * 3, height / 2);
g2d.draw(path);
g2d.dispose();
}
}
}
Take a look at Transforming Shapes, Text and Images for more details
Try JFreeChart; the setMouseWheelEnabled() method, used to control zooming in ChartPanel, is illustrated in examples cited here.
I put this simple code to show you how to use mouse wheel mouving by adding a MouseWheelListener to a JPanel:
myJpanel.addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent mwe) {
jPanelMouseWheelMoved(mwe);
}
});
To implement the mouse wheel listener:
private void jPaneMouseWheelMoved(MouseWheelEvent mwe) {
if(Event.ALT_MASK != 0) {
if(mwe.getWheelRotation() > 0) {
//here you put your code to scrool douwn or to minimize.
System.out.println(" minimize by "+(-1*mwe.getWheelRotation()));
}
else if(mwe.getWheelRotation() < 0) {
//here you put your code to scrool up or to maximize.
System.out.println(" maximaze by "+(-1*mwe.getWheelRotation()));
}
}
}
You can adapt this exemple to zoom or to scrool what you want.