I'm creating a game where I need to draw some lines and dots. I have a general function called paintDot (check code below) and I want to call it in a different function. I don't know how to call it, any help?
public void paintDot (Graphics g, int x, int y)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(x,y,15,15);
}
This is the other function/method where I need to call the drawing function:
ATM the coordinates are just hardcoded so I know it's working correctly.
As you can see, I'm calling the paintDot method with bad arguements. Don't know what argument should be placed at Graphics g
private void gameWindow (int dif)
{
this.removeAll();
areaImage = new JPanel ();
//distance between points = 75
//point grid = 7*6
areaImage.setBounds(50,50,675,600);
areaImage.setBackground(Color.WHITE);
areaImage.setBorder(BorderFactory.createLineBorder(Color.black));
add(areaImage);
answer = new JTextField();
answer.setBounds(835,200,150,50);
answer.setBorder(BorderFactory.createLineBorder(Color.black));
answer.setHorizontalAlignment(JTextField.CENTER);
answer.setFont(new Font("Verdana", Font.BOLD, 20));
add(answer);
info= new JLabel ("Write your answer here:");
info.setBounds(830,155,250,50);
info.setFont(new Font("Verdana", Font.BOLD, 12));
add(info);
checkAnswer = new JButton ("Check Answer");
checkAnswer.setBounds(835,310,150,50);
checkAnswer.addActionListener(this);
add(checkAnswer);
next = new JButton ("Next");
next.setBounds(835,410,150,50);
next.addActionListener(this);
add(next);
end = new JButton ("End Game");
end.setBounds(835,510,150,50);
end.addActionListener(this);
add(end);
revalidate();
repaint();
int x = 75,y=75;
for(int num=0;num<6;num++)
{
for(int xx=0; x<7;xx++)
{
paintDot (areaImage,x,y); // here is the problem
x=x*2;
}
y=y*2;
}
}
I have a general function called paintDot (check code below) and I want to call it in a different function
You can't.
Painting can only be done in the paintComponent() method.
You should NEVER be invoking paintComponent() directly.
All painting code MUST be in the paintComponent() method.
If you want to paint 7 dots. Then that painting code MUST be in the paintComponent() method which means the looping code would be in the paintComponent() method and then you invoke the paintDot(...) method from withing the loop. The painting of the dots must be done EVERY time Swing determines the component needs to be repainted.
You have asked several questions on this topic and the answer is always the same. Read the tutorial link you have been given and follow the examples. The tutorial draws a square, but the concept would be similar for drawing 7 dots.
So once again, read the tutorial, download the code and play with the working example. Start by changing the tutorial code to draw 7 dots. Once you understand how that works, then you add the logic to your real code.
The tutorial link is give to you for a reason. If there is something you don't understand in the tutorial, then ask a question, but don't post code that looks nothing like the example from the tutorial and wonder why it doesn't work!
You have this for:
for(int xx=0; x<7;xx++)
where you have an index called xx and you try to do a cycle. The problem is that you test for x < 7 instead of xx < 7 and since x is greater than 7, you will never get into the for.
You could extend JPanel and overwrite the drawing functions, such as the paintComponent(Graphics g) (Thanks camickr) or paintAll(Graphics g) (I believe) method.
You might also want to add a JLabel with a BufferedImage using createGraphics()
Please note if you are trying to make a full-fledged game, you would need a game loop and other stuff, which is NOT fun without a library.
This is not an attempt in shameless self-promotion, it's a suggestion.
IF you need a game loop, canvases, multiple screens and stuff,
a library could be the way to go.
I made the library j2D to make 2D games.
Related
I'm new in building Java applets
I want to show what it's display in my console in the Java applet, I know you should use the paint method, but I don't know how to call it in the code.
public void paint(Graphics g) {
//Draw a rectangle width=250, height=100
g.drawRect(0,0,250,100);
//Set the color to blue
g.setColor(Color.blue);
//Write the message to the web page
g.drawString("Running",10,50);
This is what I currently have, the whole program it's made to run from the console in
System.out.println(x)
is there anyway to call something like
paint(x)
to show the same on the applet as is show on the console? Plus I need it to refresh constantly.
You don't have a call to the superclass method. Put
super.paint(g);
before anything else.
If you want to display a message on the applet at the same time as on the console, you need to have a method that calls repaint();. The way I would set this up is to have an Arraylist of Strings. When you want something written to the applet output, you add the new String to the ArrayList, then call repaint(). Then, in paint(),
ArrayList<String> ar = new ArrayList();
public void paint(Graphics g) {
super.paint();
//Draw a rectangle width=250, height=100
g.drawRect(0,0,250,100);
//Set the color to blue
g.setColor(Color.blue);
//Write the message to the web page
for(int i = 0; i<ar.size(); i++)
g.drawString(ar.get(i), 10, 50); }
If you want a function that does this, you might write it like so
public void appletOut.println(String str){
ar.add(str);
repaint();
}
Finally, I question whether this route is really best for what you are trying to accomplish. I would suggest researching text fields and scrollbars and seeing if that might fit your parameters better.
I have done a program that numerically solves a set of differential equations which describes how an "arbitrary" illness move in an isolated and constant population, it was a programming assignment from a class I took a while ago. What I've done to extend it is to add some graphical components that can pause, reset and "play" the simulation, as well as some components that allows me to change some constants in the equations.
All this was an exercise in programming as I find it to be fun and exciting and want to become better.
However, at the moment I'm stuck, what I want to do now is to make a very simple form of animation of it. I want to visualize the data I get for the number of infected, susceptibles and resistants in a grid as points. I managed to create the grid and have an idea of how to place the dots.
The problem I have is how to draw the dots as the program is working, I can draw one dot in the grid but only as the grid is created, that's it. I need to be able to create a dot at a specific place in the grid, this goes on until the number of dots reaches a finite number, say 30. At that points I want to have the first dot, the one the left, removed, all the dots shifted to the left and place the new dot at the furthest right of the grid, the whole thing is then repeated.
I think I will be able to figure it out with some help/hints about the paintComponent() method and whether I need to use repaint() method at all, I can't get my head around these for some reason. I've read through my course literature on Java, but despite the extensive sections where he explains most of the different graphical components he does not say that much about those methods, only that you don't call for the paintComponent() method, it is done automatically.
If there is something unclear let me know and I'll try to clarify it.
Thanks in advance.
//
Fox Mulder
I think I will be able to figure it out with some help/hints about the paintComponent() method and whether I need to use repaint() method at all, I can't get my head around these for some reason.
Basically, say you create a custom component by extending JPanel. When you #Override the paintComponent() method, it get implicitly called for you, so you never have to call it. So what ever you paint inside the method, gets drawn on your surface. For example
public class DrawingPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 10, 10);
}
}
When you call repaint() you are basically causing the paintComponent method to be call implicitly. So to answer your question, Yes you will need to call it if you want to animate, as you will need to update some kind of variable (like the x and y) in the paintComponent() method, to see any change in the drawing.
You can see more at Performing Custom Painting
Not to handle the actual animation, you'll want to use a javax.swing.Timer. You can see more at How to use Swing Timers. Here's the basic construct
Timer ( int delayInMillis, ActionListener listener )
where delayInMillis is the time to delay between ticks(in this case animations) and the ActionListener listens for "ticks". Each tick, the actionPerformed of the ActionListener is called. There, you can put the code to update any variables you use for animation.
So for example you update the x and y, in the actionPerformed, then call repaint()
public class DrawingPanel extends JPanel {
int x = 50;
int y = 50;
public DrawingPanel() {
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
x += 5;
y += 5;
repaint();
}
});
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 10, 10);
}
}
Now this was just a simple example. But in your case you want to animate a scatter plot. So what you can do is have a list of Points and in the actionPerformed you can add pull points from that list and push them into another list that is to be drawn. So say you have this
List<Point> originalPoints;
List<Point> pointsToDraw;
...
#Override
protected void paintComponent(Grapchics g) {
super.paintComponent(g);
for (Point point : pointsToDraw) {
g.fillOval(point.x - 5, point.y - 5, 10, 10);
}
}
Basically all the points in pointsToDraw list will be drawn. Initially it will be empty. And in the timer, you can add to the list, until the originalPoints list is exhausted. For example.
List<Point> originalPoints;
List<point> pointsToDraw;
private int currentIndex = 0;
public DrawingPanel(List<Point> originalPoints) {
this.originalPoints = originalPoints;
pointsToDraw = new ArrayList<>();
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if (currentIndex == originalPoints.size() - 1) {
((Timer)e.getSource()).stop();
} else {
pointsToDraw.add(originalPoints.get(currentIndex));
currentIndex++;
}
repaint();
}
});
timer.start();
}
So basicall you just keep a current index. When the index reaches the size of the original list, you stop the timer. Otherwise you just pop from the originalPoints and push to the pointsToDraw. For every point you add the pointsToDraw, a repaint() is called, and there will be another point for the paintComponent to draw a circle with.
The END
UDPATE
I just reread your question, and I think I have have misunderstood it. If you want all the points drawn, then basically just have one list. And draw all the points initially. with each tick, just remove the first index, advance all the rest up an index, and add a new one to the end. Though this is the implementation of a LinkedList so you may just want to use that
Solved.
I had a question before but it was very badly posted so here it goes again, according to better rules.
I want to create some style of a graph such as this image:
.
It's based on a physics law, Snell's Law. As of now I've managed to paint the graph it self with a basic Line2D.Double which you can see here (Line.java). Then all I need to do is, in the interface class, add the lines to the array in that class as so:
LinesArray.addLine(150 , 25 , 150 , 275);
And every time it adds a new one, it repaints as you can see in the code sample.
But the problem is that I have no idea how to make this interactive. I wanted to make it interactive, as in that you could actually move those lines and at the same time you move the first line, the second would move accordingly to the Snell's Law formula, which is:
n1 * sin( a1 ) = n2 * sin ( a2 )
Considering that a1 is the first (left) angle, and a2 the second (right) angle in the first image posted.
A perfect example of what I'd hope to achieve is this one.
And if interactive movement is too hard (I'm on a 2 days schedule), this example is also a possibility.
Correct me if I'm wrong but for the second one, all that I'd need to do is calculate the mouse's coordinates and draw and calculate everything from there.
Here (menu_ui.java) is my interface class, in which the method I'm currently working with the lines is "menuSnell()" and here (Snell.java is my Snell class which contains the logic. Apologies for portuguese comments but it's fairly simple code which you don't really need comments to understand, plus I've separated it into readable methods.
So basically, my question is how do I make those lines interactive in the way I've described above.
Thanks!
I am not a graphic expert, but I had similar work a long time ago. I had an object that I need to repaint. I created my own JPanel, which holds my objects that should be paint. Whenever something changed, I call repaint method on JPanel. It looked like this
http://sourceforge.net/p/scribbler-cvut/code/132/tree/Tuzka/src/cz/cvut/scribbler/panel/RewritableGlassPane.java.
private LinkedList<ColoredArea> background = new LinkedList<ColoredArea>();
/**
* Vykreslí všechny položky v senamu vykreslených obrazců
* #param g2d grafika k vykreslení
*/
public void paintShape(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (ColoredArea area : background) {
area.fill(g2d);
}
if (mouse != null && !block) {
g2d.setColor(mouse_color);
g2d.draw(mouse);
}
if (point!=null){
SetPointsDialog.paintPoints(point, maxPoint, parent.getChildsSize(), g2d);
}
}
#Override
public void paint(Graphics g) {
paintShape((Graphics2D) g);
}
#Override
protected void paintComponent(Graphics g) {
paintShape((Graphics2D) g);
}
Everything I need to paint was stored in background variable. When something I LinkedList changed, I invoke repaint () method on the window.
I have a full source code store here: http://sourceforge.net/projects/scribbler-cvut/ but it was my long term project, so it is a little bit big.
I have a Game Tutorial that I followed, that paints String's on the Screen using Graphics2D. It works like a star, but the only problem is that I don't undertstand why.
I call draw(graphics) in a game loop and it works fine. I use an int, named currentChoice to keep track of which letter should be Red and which should be Black.
Well, I call the method Draw in a loop. I just don't understand how does the graphics clear the previous string it drew. I mean, I call the method constantly, and it keeps on Drawing string's on the window, and its 'clearing' the other ones (if you get what i'm saying).
Basicly, I just don't undertstant how it's clearing the screen (NOTE: I am super new to this sort of thing)
CODE (I call this in a loop and it works):
public void draw(Graphics2D graphics) {
bg.draw(graphics);
graphics.setColor(titleColor);
graphics.setFont(titleFont);
graphics.drawString("Peache's Revenge", 50, 70);
graphics.setFont(font);
for (int i = 0; i < options.length; i++) {
if (i == currentChoice) {
graphics.setColor(Color.RED);
} else {
graphics.setColor(Color.BLACK);
}
graphics.drawString(options[i], 145, 140 + i * 15);
}
}
Assuming the Graphics context does not change (ie is the same for each call), then, unless the background is cleared, content will continue to be painted ontop of it.
From you comments, bg.draw is drawing the background, over the top of whatever was previously painted, meaning that anything that was previously painted will now be covered by the background, thus requiring the text to be re-generated.
I have a program selection tool that i made. it opens a JFrame with 17 buttons, 15 of which are customizable, and they get their text from a .txt document located in the C: drive. when i click the assign button, it opens a JFileChooser to select a file to open when the button is clicked. You then select a button to change, and then type the text you want displayed by the button. After that the program rewrites the .txt file and updates the buttons. here is the code for updating:
public static void restart() {
start.assignButtonActions();
start.assignButtonText();
start.paint(graphics);
}
public void assignButtonActions() {
/**
* assign button actions
*/
for (int i = 0; i < buttonAction.length; i++) {
buttonAction[i] = io.readSpecificFromHD("C:\\ButtonActions.txt", i
+ 1 + actionButton.length);
}
}
public void assignButtonText() {
for (int i = 0; i < actionButton.length; i++) {
/**
* set button text
*/
actionButton[i].setText(io.readSpecificFromHD(
"C:\\ButtonActions.txt", i + 1));
}
}
public void paint(Graphics g) {
g.drawImage(getImage("files/background.png"), 0, 0, FRAMEWIDTH,
FRAMEHEIGHT, null);
refresh();
}
public void refresh() {
graphics.drawImage(getImage("files/background.png"), 0, 0, FRAMEWIDTH,
FRAMEHEIGHT, null);
for (int i = 0; i < actionButton.length; i++) {
actionButton[i].repaint();
}
assignButton.repaint();
helpButton.repaint();
}
Thats all the code that is required for this question i believe. The problem is, after the method restart() is called, the background is there, with a white square around the buttons, with it being white inside the square. not really a major problem, but really incredibly annoying and pretty unprofessional. At first i thought it was that the buttons were resizing after the background is painted, so i made it so that the refresh runs twice each time its called. didnt help one bit.
EDIT:
I fixed the problem. I took hovercraft's answer and modified what i learned a little bit. all i had to do was modify the restart() method to:
public static void restart() {
start.assignButtonActions();
start.assignButtonText();
start.repaint();
}
because the repaint(); repaint the whole component which was what hovercraft said. Thank you a ton everyone! hope this helps future questions.
You appear to be handling your Swing graphics incorrectly by calling paint(...) directly and trying to use a Graphics object outside of a JComponent's paintComponent(...) method. Don't do this, as all the Swing graphics tutorials will tell you (if you've not gone through some of them yet, you will want to do this soon). Instead do all graphics within a JComponent's (such as a JPanel's) paintComponent(...), call the super's method first, and use the Graphics object provided by the JVM in the paintComponent's method parameter.
Edit
Tutorial links:
The introductory tutorial is here: Lesson: Performing Custom Painting.
The advanced tutorial is here: Painting in AWT and Swing.
I'm thinking that you'll have to re-write most of your graphics code. Changes you should make:
Draw only in a JPanel or other JComponent-derived class, not in a JFrame or other top-level window.
Draw in your class's paintComponent(...) method.
Place an #Override annotation just above your paintComponent(...) method to be sure that you are in fact overriding the super method.
Call the super's paintComponent(...) as the first line (usually) of your paintComponent(...) override method.
Use the Graphics object passed into this method by the JVM.
Do not use a Graphics object obtained by calling getGraphics() on a component (with rare exceptions).
Do not give your class a Graphics field and try to store the Graphics object in it. The Graphics objects given by the JVM do not persist and will quickly become null or non-usable.
Do not call paint(...) or paintComponent(...) directly yourself (with rare exceptions -- and your current code does not qualify as one of the exceptions, trust me).
You will likely not need to call repaint() on your JButtons