I am trying to create a panel where I will have the possibility to zoom on custom made JComponent objects.
I have tried to call the scale() method in the AffineTransform class with different values, but I have not succeeded. My objects just disappear.
Below is my component that is used in the main frame class. Everything works except the zooming. Could some of you explain the concepts of AffineTransform. I donĀ“t think the JavaDoc explenation is enough for me.
Here is an executable SSCCE:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class JavaApplication1 extends JFrame {
public static void main(String[] args) {
new JavaApplication1();
}
private MyComponent myComponent = new MyComponent();
public JavaApplication1() throws HeadlessException {
this.setSize(400,400);
this.setVisible(true);
this.add(myComponent);
}
class MyComponent extends JComponent {
private int x, y;
private double scale=1;
private MouseAdapter mouseAdapter = new MouseAdapter();
private AffineTransform transform = new AffineTransform();
public MyComponent() {
this.addMouseListener(mouseAdapter);
this.addMouseWheelListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.DARK_GRAY);
g2.fillRect(0, 0, 400, 400);
g2.setColor(Color.RED);
g2.setTransform(transform);
transform.scale(scale, scale);
g2.drawString("My String!", x, y);
}
private class MouseAdapter implements MouseWheelListener, MouseListener, MouseMotionListener {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
if(e.getWheelRotation() == 1) {
scale+=0.1;
}else {
scale-=0.1;
}
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
}
}
transform.scale accepts two double parameters, one for the x axis and the other for the y axis, being 1 the neutral value (no change in scale), and the two parameters the multipliers.
Ex: transform.scale(2,2) will show the component twice as big, while transform.scale(0.5,0.5) will show it twice as small.
http://docs.oracle.com/javase/6/docs/api/java/awt/geom/AffineTransform.html#scale(double, double)
Related
I am working on a pixel art editor and I am having some problems with the JScrollBar.
The problem is:
I render a image on my scroll bar track but it stretches every time so I have to draw over 30 individual scroll bar track images and I was wondering if it's possible to just create one image and having it be in the right size itself.
package oktay.notepad.GUI;
import oktay.notepad.ColorSheme;
import oktay.notepad.Main;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.plaf.basic.BasicScrollBarUI;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* Created by asame on 08.06.2017.
*/
public class UIScrollBar extends BasicScrollBarUI implements MouseListener {
public UIScrollBar() {
}
#Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
try {
g.drawImage(ImageIO.read(ClassLoader.getSystemResource("res/icons/scrolltrack.pn g")), trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height, null);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
super.paintThumb(g, c, thumbBounds);
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
----------------------CustomScrollBar Class----------------------------
package oktay.notepad.GUI;
import javax.swing.*;
/**
* Created by asame on 21.06.2017.
*/
public class CustomScrollBar extends JScrollBar {
public CustomScrollBar() {
setUI(new UIScrollBar());
}
}
----------------------CustomScrollPane Class--------------------------
package oktay.notepad.GUI;
import javax.swing.*;
import java.awt.*;
/**
* Created by asame on 21.06.2017.
*/
public class CustomScrollPane extends JScrollPane {
public CustomScrollPane () {
super (VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_ALWAYS);
//setUI(new UIScrollPane());
setHorizontalScrollBar(new CustomScrollBar());
setVerticalScrollBar(new CustomScrollBar());
}
}
Thanks for the help
You may use a TexturePaint, like this:
BufferedImage bi = ImageIO.read(ClassLoader.getSystemResource("res/icons/scrolltrack.png"));
TexturePaint paint = new TexturePaint(bi, new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(paint);
g2.fill(new Rectangle(trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height));
Problem is specified in the title. I hit run, make a few lines here and there. When I resize or minimize the window, everything except the last line that was drawn is erased from the jframe window. This is part of a much larger photo album program. Eventually, I want to be able to save the drawing and add to the album. I believe the below code is where the issue lies. I've been scratching my head all night on this one. I figured if I created two arraylists and iterated through them, repaint() would re draw everything back, but that doesn't seem to be the case. Please help! Here's my code:
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Draw extends JPanel implements MouseListener, MouseMotionListener, ActionListener
{
private static final long serialVersionUID = 1L;
private ArrayList<ArrayList<Point>> lines;
private ArrayList<Point> points;
private Graphics g;
private Button clearButton;
public Draw()
{
clearButton = new Button("Clear slate");
g = getGraphics();
points = new ArrayList<Point>();
lines = new ArrayList<ArrayList<Point>>();
setPreferredSize(new Dimension(500, 500));
setBounds(0,0,500,500);
addMouseListener(this);
addMouseMotionListener(this);
clearButton.addActionListener(this);
this.add(clearButton, BorderLayout.SOUTH);
}
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseDragged(MouseEvent e)
{
// TODO Auto-generated method stub
points.add(e.getPoint());
lines.add(points);
repaint();
}
public void paint(Graphics g)
{
super.paintComponents(g);
for(ArrayList<Point> p : lines)
{
for(int i = 0; i < points.size()-1; i++)
g.drawLine(points.get(i).x, points.get(i).y, points.get(i+1).x, points.get(i+1).y);
}
}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e)
{
points = new ArrayList<Point>();
points.add(e.getPoint());
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseMoved(MouseEvent e) {}
#Override
public void actionPerformed(ActionEvent evt)
{
if(evt.getSource()== clearButton)
{
lines.clear();
points.clear();
repaint();
}
}
}
Main method:
import javax.swing.JFrame;
public class MainDriver
{
public static void main(String a[])
{
JFrame frame = new JFrame();
Draw d = new Draw();
frame.add(d);
frame.pack();
frame.setVisible(true);
}
}
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;
import java.util.*;
public class test1 extends JFrame implements MouseListener {
private JPanel JP = new JPanel();
public test1() {
JP.setBorder(BorderFactory.createLineBorder(Color.black));
JP.addMouseListener(this);
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
this.add(JP);
this.pack();
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test1 frame = new test1();
frame.setSize(400,400);
frame.setVisible(true);
}
});
}
public void mouseClicked(MouseEvent e) {
//drawCircle(e.getX(), e.getY());
//repaint();
ballball ball;
ball = new ballball();
//ball.paintComponent(Graphics g);
System.out.println("ballball");
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
//this.mouseX=e.getX();
//this.mouseY=e.getY();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
}
class ballball extends test1 implements Runnable {
private int squareX = 50;
private int squareY = 50;
private int squareW = 100;
private int squareH = 100;
public boolean draw;
private Vector<Object> v = new Vector<Object>();
public ballball() {
/*addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
draw = true;
//Thread thread1 = new Thread(this.moveSquare(50, 50));
repaint();
//moveSquare(e.getX(),e.getY());
}
});*/
/*addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});*/
System.out.println("ball created");
this.repaint();
}
public void run() {
}
private void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
public void paint(Graphics g) {
g.drawString("abcasdfasffasfas", 10, 10);
}
//#Override
public void paintComponent(Graphics g) {
//if (draw) {
// existing code
System.out.println("paint");
//super.paintComponent(g);
//g.drawString("This is my custom Panel!",10,20);
//g.setColor(Color.RED);
//g.fillRect(squareX,squareY,squareW,squareH);
//g.setColor(Color.BLACK);
//g.drawRect(squareX,squareY,squareW,squareH);
Shape circle = new Ellipse2D.Float(squareX,squareY,100f,100f);
Graphics2D ga = (Graphics2D)g;
ga.draw(circle);
//}
}
}
The aim of the program is to click to create the circle, the ballball class extends the test1, when test1 detect the mouse click, the ballball object created. But the paint/paintComponent method is never be executed. In my program structure, is it possible to paint the circle to the super class JPanel?
JFrame is not a JComponent, it doesn't have a paintComponent method you can override. Instead you could extend a JPanel and add it to the frame.
i have created an circular strip using swing in java, and now i want to display some text on mouse click clicking a particular region of the strip such as region between 45 degrees and 135 degrees central angle can anybody help me out?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Test extends JFrame implements MouseListener
{
//public static final int MOUSE_CLICKED;
public static void main(String[] args)
{
new Test();
}
public Test()
{
this.setSize(400,400);
this.setVisible(true);
addMouseListener(this);
}
public void paint(Graphics g)
{
g.fillArc(50,50,230,270,45,90);
g.setColor(Color.red);
double radius1 = 230;
double theta=90;
double a1 = (Math.PI * radius1 * radius1*theta)/360;
System.out.println("area"+a1);
double radius2 = 200;
double a2 = (Math.PI * radius2 * radius2*theta)/360;
System.out.println("area2"+a2);
double a=a1-a2;
System.out.println("fin area"+a);
g.fillArc(50,50,230,270,135,90);
g.setColor(Color.blue);
g.fillArc(50,50,230,270,225,90);
g.setColor(Color.yellow);
g.fillArc(50,50,230,270,315,90);
g.setColor(Color.magenta);
Graphics2D comp2D=(Graphics2D)g;
comp2D.setColor(Color.white);
Ellipse2D.Float sign=new Ellipse2D.Float(90F,90F,150F,200F);
comp2D.fill(sign);
{
//System.out.println("hello");
}
}
//}
}
Don't extend JFrame and don't override paint. Instead, you should extend JPanel and override paintComponent. Additionally, you should create the GUI on the Event Dispatch Thread.
Concerning the actual question: There are different possible solutions for this. You'll have to implement the MouseListener interface in any case. And after a mouse click, you have to check whether the mouse position is contained in the respective region. You could to this manually, by comparing coordinates and computing angles, but this could be a hassle. It should be much easier to create Shape objects that you fill with the respective colors, and then just check whether any of the shapes contains the mouse position.
This approach is roughly sketched here, although I did not reproduce your exact shapes. (You may have to create them with help of the Area class and its methods for union and intersection).
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ShapeClickTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new ShapeClickTestPanel());
f.setSize(400, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class ShapeClickTestPanel extends JPanel implements MouseListener {
private final List<Shape> shapes;
private final List<Color> colors;
public ShapeClickTestPanel() {
addMouseListener(this);
shapes = new ArrayList<Shape>();
colors = new ArrayList<Color>();
shapes.add(new Arc2D.Double(50, 50, 230, 270, 45, 90, Arc2D.OPEN));
colors.add(Color.RED);
}
#Override
protected void paintComponent(Graphics gr) {
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr;
for (int i = 0; i < shapes.size(); i++) {
Shape shape = shapes.get(i);
Color color = colors.get(i);
g.setColor(color);
g.fill(shape);
}
}
#Override
public void mouseClicked(MouseEvent e) {
for (int i = 0; i < shapes.size(); i++) {
Shape shape = shapes.get(i);
if (shape.contains(e.getPoint())) {
System.out.println("Clicked shape " + i);
}
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
I want to enable the drag and drop feature over a JLabel by overriding mouse events over it , but when I define the drag and drop in mousePressed event ,the mouseReleased does not take effect on that JLabel. Am I doing something wrong ?
Thumbnails[I_Loop].setText("1");
Thumbnails[I_Loop].setTransferHandler(new TransferHandler("text"));
Thumbnails[I_Loop].addMouseListener( new MouseAdapter() {
public void mouseReleased(MouseEvent me) {
System.out.println("here mouse released");
}
public void mousePressed(MouseEvent me) {
System.out.println("here mouse pressed");
JComponent comp = (JComponent) me.getSource();
TransferHandler handler = comp.getTransferHandler();
handler.exportAsDrag(comp, me, TransferHandler.COPY);
});
*Thumbnails is array of JLabel
When running the program , the drag and drop works but the statement "here mouse released" does not get printed. However, When I remove the code responsible for DND from the mousePressed() method, "here mouse released" is printed.
What is the wrong in this code?
#Thomas is correct, but two alternatives are worth noting:
This example shows how to drag a component using JLayeredPane; this variation expands on the concept; this more recent example uses a similar approach.
The code below shows how to use a MouseMotionListener; this more complex example uses the same principle.
Code:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/5312702/230513 */
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final int W = 640;
private static final int H = 480;
private Point textPt = new Point(W / 2, H / 2);
private Point mousePt;
public MouseDragTest() {
this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
textPt.setLocation(textPt.x + dx, textPt.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w2 = g.getFontMetrics().stringWidth(TITLE) / 2;
g.drawString(TITLE, textPt.x - w2, textPt.y);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
Well, if I remember correctly, the drag and drop machinery catches all mouse events and processes them itself. Thus, the normal MouseEvents are not thrown anymore. You'd need to register a DropTargetListener on the JLabel's DropTarget.
Does it have to be a JLabel? I made a class with a string that might get you started..
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class mainProgram extends JPanel implements Runnable
{
private static final long serialVersionUID = 1L;
public static boolean MOUSE_DOWN = false;
public static String str;
public mainProgram()
{
JFrame win = new JFrame("Window");
win.add(this);
win.setSize(700,500);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
str = "Drag me!";
new Thread(this).start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(MOUSE_DOWN)
{
g.drawString(str, MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);
}
}
#Override
public void run()
{
Thread t = Thread.currentThread();
this.addMouseListener(new MouseListener()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
}
#Override
public void mouseEntered(MouseEvent arg0)
{
}
#Override
public void mouseExited(MouseEvent arg0)
{
}
#Override
public void mousePressed(MouseEvent arg0)
{
MOUSE_DOWN = true;
}
#Override
public void mouseReleased(MouseEvent arg0)
{
MOUSE_DOWN = false;
}
});
while(t==Thread.currentThread())
{
if(MOUSE_DOWN)
repaint();
try {Thread.sleep(10);}
catch (InterruptedException e) {e.printStackTrace();}
}
}
}