I want to know how to create graphics (draw shapes, move shapes) by using the JFrame form in NetBeans. I have already watched the tutorials in youtube, about how to create shapes and move them. But all the tutorials are done in normal java class file. I want to know how to do it on a JFrame Form (The java class file that you can edit the interface of JFrame visually) like in this image http://image.ohozaa.com/i/b84/mOu1ku.png
I try to do the code similar to the tutorial but it isn't work
Ball.java
public class Ball extends JPanel{
int x = 0;
int y = 0;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D gra = (Graphics2D) g;
gra.setColor(Color.red);
gra.fillOval(x, y, 50, 50);
x++;
y++;
repaint();
}
Interface.java
private void DrawButtonActionPerformed(java.awt.event.ActionEvent evt) {
Ball ball1 = new Ball();
animationPanel.add(ball1);
}
Main class
public static void main(String[] args) {
Interface f = new Interface();
f.setVisible(true);
}
Related
My goal: create a method of class Point (code at the bottom), that allows me to draw multiple points (and lines in the future), so it looks like this:
Point pointA = new Point(0,0);
Point pointB = new Point(10,20);
pointA.draw(); // or probably: pointA.draw(someSurface);
pointB.draw();
I took code from a tutorial and modified it.
I found many similar problems while searching for answer, but either none of them had the answer for my case or I couldn't implement it.
As you can see below, I tried to create the method both inside the Point class and inside the Surface class (commented code), but without success.
What is the problem and what should I fix in my code?
Main:
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
BasicGraphics ex = new BasicGraphics();
ex.setVisible(true);
Point pointA = new Point(0,0);
Point pointB = new Point(10,10);
pointA.draw(ex.currentSurface);
pointB.draw(ex.currentSurface);
}
});
}
}
BasicGraphics:
public class BasicGraphics extends JFrame {
public Surface currentSurface;
public BasicGraphics() {
initUI();
}
private void initUI() {
currentSurface=new Surface();
add(currentSurface);
setTitle("My points");
setSize(100, 100);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Surface:
class Surface extends JPanel {
/*public void drawPoint(Graphics g, Point givenPoint) {
//I want to represent points as little circles
Ellipse2D circle = new Ellipse2D.Double();
Graphics2D g2d = (Graphics2D) g;
circle.setFrameFromCenter(givenPoint.x, givenPoint.y, 10,10);
g2d.draw(circle);
}*/
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
Point:
public class Point {
public double x;
public double y;
public Point(double newX, double newY){
x=newX;
y=newY;
}
public void draw(Surface givenSurface){
Graphics g = givenSurface.getGraphics();
Ellipse2D circle = new Ellipse2D.Double();
Graphics2D g2d = (Graphics2D) g;
circle.setFrameFromCenter(x, y, 10,10);
g2d.draw(circle);
givenSurface.paint(g2d);
//givenSurface.drawPoint(g2d,this);
//givenSurface.repaint();
}
}
edit: Solutions, thanks to camickr. That's not the most elegant way I can imagine, but it works:
draw method in Point:
public void draw(Surface givenSurface){
givenSurface.pointsList.add(this);
}
Surface class:
class Surface extends JPanel {
public ArrayList<Point> pointsList = new ArrayList<>();
private void drawPoints(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
double diameter = 10;
for (Point currentPoint : pointsList) {
Ellipse2D circle = new Ellipse2D.Double(currentPoint.x - diameter / 2, currentPoint.y - diameter / 2, diameter, diameter);
g2d.fill(circle);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawPoints(g);
}
}
create a method of class Point (code at the bottom), that allows me to draw multiple points (and lines in the future).
All custom painting needs to be done in the paintComponent() method of the panel. So every time the panel is painted the points/lines are repainted.
So if you want to paint multiple object you need to:
Create an ArrayList of the Object you want to paint
Create a method to add Objects to this list
In the paintComponent() method you iterate through the list and paint each Object.
Check out the DrawOnCompont example from Custom Painting Approaches. It shows how you can dynamically add Rectangle to be painted.
Since the paintComponent method will be invoked at setVisible(true) but you draw your Points after that, You have to repaint. See code modification.
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
BasicGraphics ex = new BasicGraphics();
ex.setVisible(true);
Point pointA = new Point(0,0);
Point pointB = new Point(10,10);
pointA.draw(ex.currentSurface);
pointB.draw(ex.currentSurface);
ex.revalidate();
ex.repaint();
}
});
}
}
I'm trying to print a rotated number "999" in the upper left corner of a report that is set to landscape. The characters should be placed about 1/2" in and 1" down from the top but nothing is printing so far. Here's my code:
haX = 30;
haY = 100;
AffineTransform at = g2d.getTransform();
g2d.translate(haX + haY, 0);
g2d.rotate(-Math.PI/2);
Font rotatedFont = new Font(font.getFontName(), font.getStyle(), fs );
rotatedFont = rotatedFont.deriveFont(at);
g2d.setFont(rotatedFont);
g2d.drawString("999", haX, haY);
g2d.setTransform(at);
Any ideas would really be appreciated.
Thanks
Elliot
You do not need an AffineTransform, the rotate method is a special case of it. I also don't know why you call translate since you already know the location at which you draw.
Here is how to rotate text:
public class Draw extends JFrame {
Draw() {
setContentPane(new MyPanel());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(300,300);
setVisible(true);
}
class MyPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
int haX = 30;
int haY = 100;
g2d.rotate(-Math.PI/2, haX, haY);
g2d.drawString("999", haX, haY);
}
}
public static void main(String[] args) {
new Draw();
}
}
I'm wondering how can i store objects in a vector and then draw them with the paintComponent(Graphics g) method later.
My drawing class is atm:
import java.awt.*;
import java.util.Vector;
import javax.swing.*;
public class PaintingPanel extends JPanel{
public static Rectangle playField = new Rectangle(10, 10, 800, 800);
public static int playFieldCentreX = 399;
public static int playFieldCentreY = 399;
public static Vector contents;
public PaintingPanel(Vector contents)
{
contents = new Vector();
contents.addElement(Breakout.paddle);
contents.addElement(Breakout.ball);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.draw(playField);
Breakout.paddle.paintThis(g2d);
Breakout.ball.paintThis(g2d);
}
}
I'm also not sure if i have added the objects correct in the vector, if i do
System.out.println(contents); i just get a vector with 2 null elements.
the Breakout.ball, and paddle elements is both 2 Rectangles. If i try to draw them directly as i have done so far in the bottom it works fine, but its when i want to add in like 20+ bricks i would need to store all the objects in a vector and then draw it all out.
If anyone got some good pointers, or a link to a good tutorial that would be great!
Edit: parts of breakout class
public class Breakout extends TimerTask implements KeyListener {
public static Ball ball;
public static Paddle paddle;
public static PaintingPanel panel;
public static boolean gameRunning;
public static Breakout game;
public Breakout()
{
}
public static void setupGame()
{
paddle = new Paddle(350, 790, 100, 10); //initial paddle creation
ball = new Ball(393, 400, 7);
showGUI();
}
public static void beginGame()
{
gameRunning = true;
}
public void run()
{
if(gameRunning == true)
{
Ball.move();
Paddle.move();
}
}
}
public static void main(String[] args)
{
Timer t = new Timer();
t.schedule(new Breakout(), 0, 40);
panel = new PaintingPanel(PaintingPanel.contents);
setupGame();
beginGame();
while (gameRunning == true)
{
panel.repaint();
}
// TODO a lot
}
private static void showGUI()
{
JFrame frame = new JFrame("Breakout");
game = new Breakout();
frame.addKeyListener(game);
frame.add(panel);
frame.setSize(1000,1000);
frame.setLocationRelativeTo(null); // create game window
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
What you should do is have each object class (if they are even classes, which IMO, they should be), implement a Drawable interface, with a single draw(Graphics g) method.
public interface Drawable {
public void draw(Graphics g);
}
public class Ball implenents Drawable {
#Override
public void draw(Graphics g) {
// draw ball
}
}
Then the Vector (I recommend a List instead) could be typed Drawable. Then you can just loop through it, calling the draw method of each object. (That is after adding all your Drawable objects to it.
public class PaintingPanel extends JPanel {
private List<Drawable> objects;
BreakOut breakOut;
public PaintingPanel(BreakOut breakout) {
this.breakOut = breakOut;
this.objects = breakOut.getSomething();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Drawable object: objects) {
object.draw(g);
}
}
}
IMO, this would be the better design. So you can add any object that implements the Drawable interface into the List<Drawable>
See some example here and here and here and here and here and here that draw multiple objects and use a javax.swing.Timer for animation, which maybe you want to consider doing.
We'd need to see your Breakout class to know whether you actually added anything or not. If they're null objects, then it means they were never instantiated. So, basically, call the constructor and use its returned object reference to assign Breakout.paddle and Breakout.ball, respectively.
i'm trying to write a jigsaw puzzle application where an image is cut in pieces, scrambled, and the user have to rearrange them with drag&drop to reassemble the original image. (something like this: http://www.jigzone.com/puzzles/74055D549FF0?z=5).
i have to write this in java with Graphics2d.
so, at first i'm trying to make some kind of component which can show a part of the image (a rectangle for now), and can be dragged with mouse.
the code below works well when there is only one one such component. the problem is, when i add the second component, the first one is no longer visible.
i'm really stuck here. i have a feeling i'm missing something really basic. or maybe i'm on a wrong way. any help will be greatly appreciated.
edit: i changed a bit the code according to suggestions, however, still not working as expected.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
public class GraphicDragAndDrop extends JPanel {
Rectangle rect;
Image img;
public GraphicDragAndDrop(String imgFile, int x0, int y0){
rect = new Rectangle(x0, y0, 150, 75);
img = new ImageIcon(imgFile).getImage();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setClip(rect);
int x = rect.x;
int y = rect.y;
g2d.drawImage(img, x, y, this);
}
public void setRect(int x, int y) {
rect.setLocation(x, y);
repaint();
}
public static void main(String[] args) {
// first piece
GraphicDragAndDrop piece1 = new GraphicDragAndDrop("a.png", 0, 0);
piece1.setRect(0, 0);
new GraphicDragController(piece1);
// second piece --> only this will be visible
GraphicDragAndDrop piece2 = new GraphicDragAndDrop("a.png", 200, 200);
//GraphicDragAndDrop piece2 = new GraphicDragAndDrop("b.png", 200, 200); // does'n work either
piece2.setRect(150, 150);
new GraphicDragController(piece2);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(piece1);
f.add(piece2);
f.setSize(500,500);
f.setLocation(300,100);
f.setVisible(true);
}
}
class GraphicDragController extends MouseInputAdapter {
GraphicDragAndDrop component;
Point offset = new Point();
boolean dragging = false;
public GraphicDragController(GraphicDragAndDrop gdad) {
component = gdad;
component.addMouseListener(this);
component.addMouseMotionListener(this);
}
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Rectangle r = component.rect;
if(r.contains(p)) {
offset.x = p.x - r.x;
offset.y = p.y - r.y;
dragging = true;
}
}
public void mouseReleased(MouseEvent e) {
dragging = false;
}
public void mouseDragged(MouseEvent e) {
if(dragging) {
int x = e.getX() - offset.x;
int y = e.getY() - offset.y;
component.setRect(x, y);
}
}
}
Your code above is written to draw only one image:
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setClip(rect);
int x = rect.x;
int y = rect.y;
// here
g2d.drawImage(new ImageIcon("a.png").getImage(), x, y, this);
}
If you need to draw more than one image, then consider creating a collection of images and iterating through the collection in paintComponent using a for loop:
also, never read in the image from within paintComponent since this method should be lean, mean and fast, and should concern itself with painting only. Also, there's no need to read the image in each time your program has to draw it as that's very inefficient and will slow the program unnecessarily. Instead read the image in once in the constructor or a similar init method.
For example,
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Image img: myImageCollection) {
g2d.drawImage(img, 0, 0, this);
}
}
Edit
You state:
also, my plan was to have more objects of GraphicDragAndDrop class, each of them showing a different piece of the original image. is my approach wrong?
You could use components, but I have a feeling that it would be easy to drag images. I think it would be easier to rotate them for instance if you want your program to have this functionality. If not, though then sure use a component, but if you go this route, I would recommend using a JLabel and simply setting its ImageIcon rather than dragging JPanels.
As shown below in code, i'm getting x and y values of line from the database. And then storing them in an array x. After that i'm trying to draw this line on the Frame, but it is not getting drawn. How can i draw line on Frame?
public class TestFrame{
static JFrame test;
public static void main(String ar[]){
test=new JFrame("Test");
JButton openLine=new JButton(new AbstractAction("Open Line"){
public void actionPerformed(ActionEvent e) {
String lineId=JOptionPane.showInputDialog("Enter Line id");
ImageComponent image=new ImageComponent();
image.openLine(lineId);
}
});
test.add(openLine, BorderLayout.NORTH);
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setSize(600,600);
test.setVisible(true);
}
static class ImageComponent extends JComponent{
static int[] x=new int[100];
static ArrayList al=new ArrayList();
public void openLine(String line_id){
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection("jdbc:odbc:image");
Statement pstm=con.createStatement();
ResultSet rs=pstm.executeQuery("select * from Line where ID= '"+line_id+"'");
while(rs.next()){
x[0]=rs.getInt(3);
x[1]=rs.getInt(4);
x[2]=rs.getInt(5);
x[3]=rs.getInt(6);
al.add(x);
}
repaint();
} catch (Exception ex) {
System.out.println("Exception : "+ex);
}
}
public Graphics2D gd;
Line2D[] line=new Line2D[100];
protected void paintComponent(Graphics g) {
super.paintComponent(g);
gd=(Graphics2D)g;
gd.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(int i=0;i<al.size();i++){
line[i]=new Line2D.Double(x[0], x[1],x[2],x[3]);
gd.draw(line[i]);
}
}
}
}
Here is one approach that uses a BufferedImage as a rendering surface.
The OP in that question was asking about an applet, but I displayed the image in an option pane. It is just as well suited to display in a frame etc. without any confusion over whether to override paint(Graphics) or paintComponent(Graphics). ;)
You can use the Graphics object and override the paint() method like so:
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.gray);
int x = 5;
int y = 7;
g2.draw(new Line2D.Double(x, y, 200, 200));
g2.drawString("Line2D", x, 250);
}
Taken from here
You shouldn't directly on a JFrame. All rendering in the main body of JFrame is done in the contentpane. Menu content is done in the JMenuBar
One issue is that you create a new ImageComponent every time the button is clicked but it is not added to your frame.
Another one is that you fill in an arraylist (al) but don't use it to actually draw your line.
This works for me with dummy values for x[0], x[1], x[2], x[3]:
static JFrame test;
static ImageComponent image = new ImageComponent(); //declared as a class member
public static void main(String ar[]) {
test = new JFrame("Test");
JButton openLine = new JButton(new AbstractAction("Open Line") {
public void actionPerformed(ActionEvent e) {
String lineId = JOptionPane.showInputDialog("Enter Line id");
image.openLine(lineId);
}
});
test.add(openLine, BorderLayout.NORTH);
test.add(image); //ADD THE IMAGE TO THE FRAME
image.setVisible(true);
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setSize(600, 600);
test.setVisible(true);
}