I'm really a beginner at Java. Today I wrote some codes, it should draw some rectangles but they don't. Is there something wrong in my code?
import java.awt.*;
import java.awt.event.*;
public class NewMain extends Frame{
static int oldx = 0;
static int newx = 0;
static int oldy = 0;
static int newy = 0;
static Color drawColor = Color.white;
public static void main(String[] args) {
Frame myFrame = new Frame();
Graphics myGraphics = myFrame.getGraphics();
myFrame.setSize(1360,760);
myFrame.setTitle("Fun Blackboard");
myFrame.setVisible(true);
myFrame.setBackground(Color.black);
myFrame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
myGraphics.setColor(Color.white);
myGraphics.fillRect(0,0,20,20);
myGraphics.setColor(Color.lightGray);
myGraphics.fillRect(0,0,20,40);
myGraphics.setColor(Color.gray);
myGraphics.fillRect(0,0,20,60);
myFrame.addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
System.out.print("X:");
System.out.print(e.getX());
System.out.print(", Y:");
System.out.println(e.getY());
}
});
}
}
I also tried to put them in the mousePressed() thing, but still don't work.
You can try using the drawRect of Graphics class, there is an easy method:
paint(Graphics g) {
Rectangle r = new Rectangle(5,5,30,30);
g.drawRect(r.x,r.y,r.width,r.height);
}
Anyway, awt is dated, you can try creating something with JavaFX, it's easier and faster to use and it's easier to create a graphical interface
Related
My paint method doesnt seem to paint my 20x20 cells. I have a boolean array for the cells to control their state and that if true, call the cells paint method, a cell is painted however I have two problems;
Only one is painted at a time which is odd because i should have a 40x40 array of booleans meaning i have 40x40 cells
They dont actually paint exactly where I click. I do not know how this is the case as when I get the co-ordinates of my click I immediately place those co-ordinates as my x, and y values in my paint method.
Main
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
public class mainApplication extends JFrame implements Runnable, MouseListener {
private static final Dimension windowsize = new Dimension(80, 600);
private BufferStrategy strategy;
private Graphics offscreenGraphics;
private static boolean isGraphicsInitialised = false;
private static int rows = 40;
private static int columns = 40;
private static int height = windowsize.height;
private static int width = windowsize.width;
private static Cells cells = new Cells();
private int xArrayElement,yArrayElement, xPosition, yPosition;
private static boolean gameState[][] = new boolean[rows][columns];
public mainApplication() {
System.out.println(System.getProperty("user.dir"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = screensize.width / 2 - windowsize.width / 2;
int y = screensize.height / 2 - windowsize.height / 2;
setBounds(x, y, screensize.width, screensize.height);
setVisible(true);
createBufferStrategy(2);
strategy = getBufferStrategy();
offscreenGraphics = strategy.getDrawGraphics();
isGraphicsInitialised = true;
// MouseEvent mouseEvent = new MouseEvent();
addMouseListener(this);
// addMouseMotionListener(MouseEvent);
Thread t = new Thread(this);
t.start();
}
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 1){
xPosition = e.getX();
yPosition = e.getY();
cells.setPosition(xPosition,yPosition);
xArrayElement = (xPosition/20);
yArrayElement = (yPosition/20);
if(gameState[xArrayElement][yArrayElement]){
gameState[xArrayElement][yArrayElement] = false;
}
else if (!gameState[xArrayElement][yArrayElement]) {
gameState[xArrayElement][yArrayElement] = true;
}
else(gameState[xArrayElement][yArrayElement]) = true;
}
}
#Override
public void run() {
while (true) {
try { //threads entry point
Thread.sleep(20); //forces us to catch exception
}
catch (InterruptedException e) {
}
this.repaint();
}
}
public void paint(Graphics g) {
if (isGraphicsInitialised) {
g = strategy.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 800);
if (gameState[xArrayElement][yArrayElement]) {
g.setColor(Color.WHITE);
cells.paint(g);
System.out.println(xPosition);
}
else if (!gameState[xArrayElement][yArrayElement]) {
g.setColor(Color.BLACK);
g.fillRect(xPosition, yPosition, 20, 20);
}
strategy.show();
}
}
public static void main(String[]args){
mainApplication test = new mainApplication();
}
}
Cell Class
import java.awt.*;
public class Cells {
int x;
int y;
public Cells(){
}
public void setPosition(int xi, int xj){
x = xi;
y = xi;
}
public boolean cellState(boolean visible){
return visible;
}
public void paint(Graphics g){
g.drawRect(x, y, 20,20);
}
}
You are doing a number of things wrong. My first suggestion would be to forget about offscreen graphics and ensure you are doing what you want. You can always create an image latter. Here are some basic guidelines:
Don't extend JFrame. Use an instance.
Extend JPanel or create a class that extends JPanel and add to frame instance
Then override paintComponent(g) and use that graphics context to draw.
Here is an earlier answer that may help Can't add Graphics into JPanel in Java
More information may be found in the Java Tutorials on painting.
Updated. It took me a few minutes to find this.
public void setPosition(int xi, int xj){
x = xi;
y = xi; // <--- should be xj
}
Regarding (1) above. You must repaint every cell each time you enter paintComponent. This means you will need to iterate across the list and paint them in the correct spot. Right now you are only painting one upon each entry.
A couple more suggestions. Instead of messing with the thread and calling repaint every 20ms in a loop, why not just invoke repaint in the mouseClicked() method.
If you do eventually need to paint every 20ms. I suggest using a swing Timer as follows: (check JavaDoc to ensure I got the syntax correct!!)
Timer timer = new Timer(0, (ev)-> frame.repaint());
timer.setDelay(20);
timer.start();
And you can create your own mouseListener class and extending MouseAdapter. The purpose of these adapter classes is to keep the clutter down so you don't have to have empty methods to satisfy the interface requirements. Put the class inside your main class so it has access to the appropriate data structures. Then just add an instance of it to the mouse listener of the target Component.
I am working on a simple app Java/Swing, which involves having the user click on a box and drag it around. I am having troubles with understanding how the repaint method can be used. I created this example of the problem, in which a square is drawn and then on mousePressed it gets the x cordinates of the click, and displaces the original drawing by however much the pointer is moved.
I have read the commonly referred guides on drawing in Swing, but I haven't seen any answers to the question on how to write a program that incorporates both mouseMotion and mouseListener (which as far as I can tell means that the mouseListener must be implemented as its own class, as opposed to the common solution of incorporating it into the custom JPanel class) and also calls repaint() based on mouse actions.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.MouseInputAdapter;
class drawTest extends JPanel {
static int xpos_square = 200;
static int ypos_square = 200;
int width = 100;
int height = 100;
static int x_init;
static int y_init;
public drawTest(){
addMouseListener(new mouseListener());
addMouseMotionListener(new mouseListener());
setBackground(Color.BLACK);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawSquare(g);
}
public void drawSquare(Graphics g){
g.setColor(Color.GREEN);
g.fillRect(xpos_square, ypos_square, height, width);
}
public static void moveShape(int x, int y){
xpos_square += x-x_init;
ypos_square += y-y_init;
repaint();
}
public static void getChord(int x, int y){
x_init = x;
y_init = y;
}
}
class mouseListener extends MouseInputAdapter{
public void mousePressed(MouseEvent e){
drawTest.getChord(e.getX(),e.getY());
}
public void mouseDragged(MouseEvent e){
drawTest.moveShape(e.getX(),e.getY());
}
}
public class myTest {
JFrame myFrame = new JFrame();
JPanel myDrawing = new drawTest();
public myTest () {
myFrame.add(myDrawing);
myFrame.setSize(500,500);
myFrame.setVisible(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String []args){
new myTest();
}
}
The issue is of course that repaint() cannot be called in a static context. However, I don't see how I can avoid this, since if I want the position to smoothly update, it has to be called via the mouseDragged method.
How else could I use the repaint() method to redraw based on mouse movements?
So I figured out a way around it, using anonymous methods in addMouseListener. This bypasses the need for static methods in the call to repaint. If anyone else has a similar question, maybe they will find it helpful.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.MouseInputAdapter;
class DrawTest extends JPanel {
static int xpos_square = 200;
static int ypos_square = 200;
int width = 100;
int height = 100;
static int x_init;
static int y_init;
public DrawTest(){
addMouseListener(new mouseListener(){ public void mousePressed(MouseEvent e){
getClick(e.getX(),e.getY());
}});
addMouseMotionListener(new mouseListener(){ public void mouseDragged(MouseEvent e){
moveShape(e.getX(),e.getY());
}});
setBackground(Color.BLACK);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawSquare(g);
}
public void drawSquare(Graphics g){
g.setColor(Color.GREEN);
g.fillRect(xpos_square, ypos_square, height, width);
}
public void moveShape(int x, int y){
if((x >= xpos_square)&&(x <= xpos_square + width)&&(y >= ypos_square)&&(y <= ypos_square + height)){
xpos_square += x-x_init;
ypos_square += y-y_init;
x_init = x;
y_init = y;
repaint();
}
}
public void getClick(int x, int y){
x_init = x;
y_init = y;
}
}
public class MyTest {
JFrame myFrame = new JFrame();
JPanel myDrawing = new DrawTest();
public MyTest () {
myFrame.add(myDrawing);
myFrame.setSize(500,500);
myFrame.setVisible(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String []args){
new MyTest();
}
}
I have worked with the school assignment for quite some time now. But I can not really understand what I should do. The assignment is due tomorrow and I feel quite stressed.
The task is, I'll get some pictures, have them in a window, then be able to move around them and also be able to rotate.
The big problem is that I do not know how I'll manage paintComponent().
What I read is that it should be called automatic "when needed" and when you call repaint(). I find it hard to get it to work.
The main class
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class JFrameC extends JFrame{
JPanel panel;
ArrayList <ThePhoto> oneArray = new <ThePhoto> ArrayList();
public JFrameC(){
super("This window");
setLayout(new BorderLayout());
panel = new JPanel();
panel.setBackground(Color.GREEN);
panel.setLayout(null);
add(panel);
setSize(500,500);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void addPicture(String name){
oneArray.add(new ThePhoto(name, this));
panel.add(oneArray.get(oneArray.size()-1).getJPanel());
}
public void draw(JPanel p){
//One of the tasks is that the image is pressed to end up on top.
//I thought that if I sort of an ArrayList so I can keep track of which one
//is on top. Then be able to paint them in order.
for(ThePhoto x : oneArray){
if(x.getJPanel() == p && oneArray.indexOf(x) != 0){
int i = oneArray.indexOf(x);
for(;i > 0; i--){
ThePhoto temp = oneArray.get(i);
oneArray.set(i, oneArray.get(i-1));
oneArray.set(i-1, temp);
}
break;
}
}
panel.validate();//I can not get this to work
panel.repaint();
getContentPane().validate();//Or this.
getContentPane().repaint();
}
public void paintComponent(Graphics g){
//Is this right?
//What should I write here?
}
public static void main(String[] args) {
JFrameC j = new JFrameC();
j.addPicture("one.gif");
j.addPicture("two.gif");
j.addPicture("three.gif");
j.addPicture("four.gif");
}
}
Class
import javax.swing.*;
import java.awt.*;
public class ThePhoto{
ImageIcon onePicture;
JLabel l;
JPanel p;
JFrameC k;
int posX = 10;
int posY = 10;
public ThePhoto(String name, JFrameC k){
this.k = k;
onePicture = new ImageIcon(name);
l = new JLabel(onePicture);
p = new JPanel();
p.setLayout(new CardLayout());
p.setBorder(null);
p.setBackground(null);
p.add(l);
p.setBounds(posX, posY, 100, 100);
p.addMouseListener(new HandleMouse(k, this));
p.addMouseMotionListener(new HandleMouse(k, this));
}
public void setX(int x){posX = x;}
public void setY(int y){posY = y;}
public JPanel getJPanel(){return p;}
public void paintComponent(Graphics g){
//Is this right?
//What should I write here?
}
}
MouseEvent Class
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.*;
import javax.swing.*;
public class HandleMouse extends MouseAdapter implements MouseMotionListener{
JFrame k;
ThePhoto b;
public HandleMouse(JFrameC k, ThePhoto b){
this.k = k;
this.b = b;
}
public void mouseClicked (MouseEvent e) {
k.draw((JPanel)e.getComponent());
}
public void mouseDragged (MouseEvent e) {
e.translatePoint(e.getComponent().getLocation().x, e.getComponent().getLocation().y);
e.getComponent().setLocation(e.getX(), e.getY());
b.setX(e.getX());
b.setY(e.getY());
}
public void mouseReleased(MouseEvent e) {
k.draw((JPanel)e.getComponent());
}
}
To summarize the issues clearer:
1.Is it best to call repaint() to Frame or Panel? As, I understand it is in both cases everything 'in' the container that will be repainted. And if so, should JFrame be preferable?
2.Is there any routine/usual/rule on what should be in the paintComponent()?
3.What advice and criticism whatsoever is very welcome. But please write so that a beginner understands and no unnecessary insults.
I understand that nobody wants to do my homework. But I only ask for some advice so that I can get better. I also want to write that I am a novice and therefore looks like my code to be written by a novice.
Solve the problem for a single image before trying for multiple images. Starting from this example, use ImageIO.read() to initialize an image and use drawImage() to render it in paintComponent().
private final BufferedImage image = getImage();
private BufferedImage getImage() {
try {
return ImageIO.read(new URL(
"http://i.imgur.com/kxXhIH1.jpg"));
} catch (IOException e) {
e.printStackTrace(System.err);
}
return null;
}
…
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image,
textPt.x - image.getWidth() / 2,
textPt.y - image.getHeight() / 2, this);
}
You can rotate the graphics context as shown here.
this is my code. It worked for drawing a circle but I am having troubles drawing a triangle now.. A triangle should appear using mouse clicks but it is showing a triangle immediately after running the application. Please help. Thanks.
package mouse;
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.event.*;
import java.awt.geom.*;
public class triangle extends JFrame implements ActionListener, MouseListener {
int xx[]= {20, 50, 80};
int yy[]= {80, 30, 80};
public triangle () {
setSize(2000,2000);
addMouseListener(this);
}
public static void main(String[] args) {
//TODO code application logic here
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
triangle frame = new triangle();
frame.setVisible(true);
}
});
}
public void actionPerformed(ActionEvent ae) {
}
public void drawPolygon(int x, int y, int i)
{
Graphics g = this.getGraphics();
g.setColor(Color.BLACK);
g.drawPolygon(xx, yy, 3);
}
int x, y;
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override
public void paint(Graphics g) {
drawPolygon(x, y, 3);
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
}``
The problem you have is that you override the paint method and therefore the drawPolygon method is already called in the initial painting of the JFrame.
For the effect you want to have you should avoid overriding the paint method and only use the drawPolygon method when the MouseListener is invoked.
This should look like this:
#Override
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
drawPolygon(x,y,3);
repaint();
}
In order to paint the triangle where you click with the mouse you need to add the current position to the original triangle coordinates like this:
public void drawPolygon(int x, int y, int i)
{
Graphics g = this.getGraphics();
g.setColor(Color.BLACK);
int[] drawx = {xx[0]+x,xx[1]+x,xx[2]+x};
int[] drawy = {yy[0]+y,yy[1]+y,yy[2]+y};
g.drawPolygon(drawx, drawy, i);
}
I hope this answers you question.
Some general remarks on programming:
You should definitely include a
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
otherwise you program won't terminate on closing the frame and keep on running.
It would also help the readability of your code if you avoid having everything in one class and split your code into several classes.
The MVC model is something that is a very good general guideline for designing class structures.
I'm quite new to swing, and I'm having an issue with graphics not showing up in my JFrame. What I should be seeing is a blue rectangle slowly moving downwards through the frame, and behind it is a plain white background. However, when I run my main class, all I see is a plain JFrame. This is my code:
Execute class
public class Execute {
public static void main (String[ ] args) {
GUI gui = new GUI();
gui.createFrame(800,600);
ElevatorOne e1 = new ElevatorOne();
e1.addElevatorOne();
}
}
ElevatorOne class (Where the graphics should be initialized and added)
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class ElevatorOne extends GUI{
int y = 100;
public void addElevatorOne() {
drawElevatorOne drawE1 = new drawElevatorOne();
frame.getContentPane().add(drawE1);
for(int i = 0; i < 130; i++) {
y++;
drawE1.repaint();
try {
Thread.sleep(50);
} catch (Exception ex) { }
}
}
#SuppressWarnings("serial")
class drawElevatorOne extends JPanel{
public void paintComponent(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLUE);
g.drawRect(200,y,40,60);
}
}
}
And finally, my GUI class (where frame is created)
import javax.swing.JFrame;
public class GUI {
JFrame frame = new JFrame();
public void createFrame(int x, int y) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
frame.setSize(x, y);
}
}
While you've got an accepted answer, I do take issue with that answer and feel impelled to add my two cents:
I see no purpose to your having a GUI class and then having Elevator1 extend it. If you want Elevator1 to use a JFrame, then have it create a JFrame as there really is no need or benefit from your inheritance.
Myself, I'd have Elevator1 extend JPanel and then have it draw in its own paintComponent method, thus eliminating the need for drawElevatorOne inner class (which should be named DrawElevatorOne to adhere to Java naming conventions).
You are using Thread.sleep in a Swing GUI which is extremely risky to do. The only reason this works is because it is being called in the main thread. If your code were properly created and set up to start and create GUI components in the Swing event thread, this would and should fail since it would put the Swing event thread to sleep. Don't do this, don't call Thread.sleep in a method that has any risk of being called in the Swing event thread.
Instead use a Swing Timer to manage your delay.
Don't forget to (almost) always call the super.paintComponent(g) method within your oeverride. To not do this breaks the Swing painting chain and risks significant hard to debug side effects.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class ElevatorTest {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private static void createAndShowGui() {
MyElevator mainPanel = new MyElevator(PREF_W, PREF_H);
JFrame frame = new JFrame("Elevator Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start everything on the Swing event thread
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyElevator extends JPanel {
private static final Color BACKGROUND = Color.white;
private static final int ELEVATOR_X = 200;
private static final int ELEVATOR_W = 40;
private static final int ELEVATOR_H = 60;
private static final int TIMER_DELAY = 50;
public static final int MAX_ELEVATOR_Y = 130;
private static final Color ELEVATOR_COLOR = Color.blue;
private int prefW;
private int prefH;
private int elevatorY = 0;
public MyElevator(int prefW, int prefH) {
this.prefW = prefW;
this.prefH = prefH;
setBackground(BACKGROUND);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
// Don't forget to call the super method
super.paintComponent(g);
g.setColor(ELEVATOR_COLOR);
g.fillRect(ELEVATOR_X, elevatorY, ELEVATOR_W, ELEVATOR_H);
}
// to help size our GUI properly
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int w = Math.max(superSz.width, prefW);
int h = Math.max(superSz.height, prefH);
return new Dimension(w, h);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (elevatorY >= MAX_ELEVATOR_Y) {
// if elevator at max, stop thimer
((Timer) e.getSource()).stop();
} else {
// advance elevator and draw it
elevatorY++;
repaint();
}
}
}
}
Your ElevatorOne class extends GUI. Therefore it inherits all of the functionality of GUI, yet you create both of them. This is probably what you intended to do:
edit: I ran this code and indeed there is a box moving as you specify.
public class Execute {
public static void main (String[ ] args) {
// GUI gui = new GUI();
// gui.createFrame(800,600);
ElevatorOne e1 = new ElevatorOne();
e1.createFrame(800, 600);
e1.addElevatorOne();
}
}