I am trying to paint multiple images depending on whether a Boolean is true or not. But instead when the boolean becomes true or not, I get a NullPointerException involving anything with my methods. (comment in code specifically pointing to where), and I'm 99% sure its because of the graphics and it's null.
Basically I'm also asking how to fix this and how to properly paint images using my own methods in one class. I know how to do it with each image in one class, but I have WAY more than just 2 images, I think I have almost 100, so i don't want to make 100 classes (:|). Here's my code:
List of images class:
public class Images{
public static Toolkit tk = Toolkit.getDefaultToolkit();
public static final Image Image1 = tk.getImage("src/images/image1.png"), Image2 = tk.getImage("src/images/image2.png");
public ImageObserver observer = null; //i just did this for no reason
public static Graphics g = Main.graphics;
public void paintImage1(Graphics g){
Images.g = g;
g.drawImage(Image1, 10, 10, observer); //NullPointerException points here, even if I replace 'pbserver' with null
}
public void paintImage2(Graphics g){
Images.g = g;
g.drawImage(Image2, 10, 10, observer); //strangely, it doesn't point here
}
}
Then, I cite and use it in my class that paints the image with my boolean like so:
public class PaintHandler{
public static Graphics graphics = Images.g;
public void PaintImages(boolean upheld){
if (upheld){
Images.paintImage1(graphics);//NullPionterException points here
}
else if (!upheld){
Images.paintImage2(graphics);//doesn't point here for some reason
}
}
}
The exception also points to the keybindings methods I use to make upheld true or not, another thing that is strange.
Like before, I don't want to make a class for every single image, I would prefer if they were all in one class. Additionally, when I try to use getGraphics() on the JFrame I'm using, I do through this GIGANTIC loop between making thing statics and not being able to apply static terms to non-static context, such as making a variable static, but then it says can't be used in static context, but then when you don't make it static a different variable says change it back to static, you don't make that static, and you go through this huge loop between making it static and changing to not be static (sorry for long explanation, was trying to be specific).
" when I try to use getGraphics() on the JFrame im using" - DON'T, this is not how custom is painting is done in Swing. getGraphics will, at best, return a snap shot of the last paint cycle and anything painted to it will be painted over on the next paint cycle and at worst, will return null.
Take a look at Painting in AWT and Swing and Performing Custom Painting for dore details about how painting works in Swing and how you should work with it...
Instead, create your self a custom component, extending from something like JPanel and use it's paintComponent to paint your images.
Normally, content stored in the src will be made available your application as embedded resources (this will depend on your IDE and build system), but generally speaking, you should not access any resource with the path containing src, this should be an immediate read flag for potential issues.
In this case you should be using Class#getResource to load the resource...
public class Images{
public static final Image Image1 = tk.getImage(Images.class.getResource("/images/image1.png"));
for example.
I would discourage you from using Toolkit.getImage as it will use a background thread to load the image and doesn't throw any kind of exception if the image wasn't loaded
Instead considering using ImageIO.read, see Reading/Loading an Image for more details
Like before, I don't want to make a class for every single image, I
would prefer if they were all in one class. Additionally, when I try
to use getGraphics() on the JFrame I'm using, I do through this
GIGANTIC loop between making thing statics and not being able to apply
static terms to non-static context, such as making a variable static,
but then it says can't be used in static context, but then when you
don't make it static a different variable says change it back to
static, you don't make that static, and you go through this huge loop
between making it static and changing to not be static (sorry for long
explanation, was trying to be specific).
Your images can be stored wherever you like, maybe in a Map of some kind. But they must be painted within a valid context, ie a component's paint method. You can paint as many images you want within in single component or spread them out if your prefer, that's tp up...
The issue with static is probably because you're ...
Still in the main method, which is static and/or
Trying to references (non-static) variables in other classes to which you've not created an instance to.
Only a runnable example will highlight which (if not both)
Related
I'm using lambda functions with custom functional interfaces to shorten some nested loops that occur regularly in my code. As I don't want to add additional parameters to my expressions and end with something like this all over my code:
doubleLoop((int i, int j, Graphics graphics) -> drawHexagonRandomColor(i, j, graphics), g);
can I call getGraphics() to get the graphics context inside my #Override public void paint(Graphics g) {...} (instead of using the parameter g) without unexpected/negative side-effects?
can I call getGraphics() inside my #Override public void paint(Graphics g) {...} without unexpected/negative side-effects?
What's the point? paint already has a reference to Graphics.
What happens when someone else wants to use your code? Will they know NOT to call these methods outside of the context of the paint routine?
Are there consequences? Not the way you're intending to use it, but what happens if you want to change to using a BufferedStrategy instead of the standard painting routine? What happens if you want to paint the results to a BufferedImage instead?
You've build in an inflexible solution which has it's own dangerous side effects. For the preserved benefit (of not having one additional parameter), you lose a lot of flexibility, reuse and self documentation.
No one else will use my code
That's only part of the point, you should always challenge yourself to assume that someone else will use your code, it makes you a better developer, stops you from taking shortcuts or cutting corners.
getGraphics is just a bad idea generally and should be avoided wherever possible
Lets suppose we have a class Shape which has a method rotate(int velocity). This method makes a shape rotate with a speed of velocity(the parameter passed to rotate). This method has been called in a project, say at 100 places.
But now a new requirement comes, that the rotate functionality will also depend on the color of the shape, i.e. if the color is blue then the velocity should be decreased by 1, else no change should be made.
One solution to this problem would be to change the rotate(int velocity) method to rotate(int velocity, Color color), then add an if statement inside rotate method to check for the color, and make a change in 100 calls of rotate.
E.g.
shape.rotate(50, blue) ;
Inside the rotate method,
void rotate(int velocity, Color color) {
if(color == blue)
--velocity ;
}
Another solution would be to make color as an instance variable of the shape object, and then without adding a new argument to the rotate method, simply set the color before calling it, and squeeze the if check inside the rotate method.
E.g.
shape.setColor(blue) ;
shape.rotate(50) ;
Inside the rotate method,
void rotate(int velocity) {
if(this.color == blue)
--velocity ;
}
Yet another solution would be to overload the rotate method and create a new method named rotate(int velocity, Color color) and use it in the new calls. This would leave the existing code which uses rotate(int velocity) unchanged.
Which of these would be the best possible solution? Or, does there exist a better solution? If yes, then what could it be?
Regards
I'd say there are a couple of questions you need to ask yourself.
Do you care about the color outside of the rotate method? If yes, make it an instance variable; if no, pass it to the rotate method.
Are you likely to care about the color outside of the rotate method further down the line? If yes, make it an instance variable; if no, pass it to the rotate method.
Are you always going to care about the color when calling the rotate method? If yes, make it an argument (to force them to set the color when rotating the shape).
A good principle of OO is to co-locate related behavior and state. In this case the rotate behavior of shape depends on the colour state of shape, so it makes sense to co-locate both in the Shape class, c.q. create a field 'colour' and use it within the rotate method to customize the rotation behavior.
Apart from this design decision, you are really also asking about a refactoring decision: how do I handle the application code that depends on shape? My approach in cases like this is to think ahead: how many changes like these to the Shape class can we expect? If this is a rare change then you could just go ahead and change all the code locations that initialize the shape class so a colour is set. If shape changes more often, then you should be more rigorous and make your code less tightly coupled. A way to do that in this case is to create an abstract factory (or use the factory offered by a D.I. framework like Spring) so that the application code does not need to know the creation details of shape.
BTW your third option seems sub-optimal to me: part of the code is not made aware of the addition of the colour state to shape, and keeps calling the old 'deprecated' rotate method. This means that setting a shape's colour to blue will not universally affect the rotation behavior, but only in 'special cases'. This weakens the design and makes it harder for the developers after you to understand it.
I think the first option is is tedious to implement. What if you miss at one place, what if later u realize that you need rotate(single parameter) again.
The second option is irrelevant as many have already pointed out.
3rd I think is the best solution, as it will not break your code. You can have both the overloaded method, can use any of them as per requirement.
As for me, I see classic example of inheritance usage here.
class Shape {
public void rotate(int v) {}
}
class GreenShape extends Shape {
public void rotate(int v){
super.rotate(v + 10);
}
}
I'm planning to write a simple spaceshooter. I have read that the repaint() method is only a request, and it doesn't execute every time it's called. I believe I'm noticing the effects of this, as my spaceship tends to lag ever so slightly when I'm moving it. Currently I'm simply drawing my ship in a a JPanel's paintComponent() method, and keep calling repaint() on regular intervals (my panel's also Runnable). Seeing as repaint() may potentially screw me over, I'm trying to find a way to work arround it, however I've ran out of ideas. The code I have so far:
private void renderGraphics() {
if (MyImage == null) {
MyImage = new BufferedImage(getPreferredSize().width,
getPreferredSize().height, BufferedImage.TYPE_INT_RGB);
}
MyGraphics = MyImage.getGraphics();
MyGraphics.setColor(Color.BLACK);
MyGraphics.fillRect(0, 0, getPreferredSize().width, getPreferredSize().height);
MyGraphics.drawImage(ship.getImage(), ship.getCurrentX(), ship.getCurrentY(), null);
}
The idea was to create my own graphics, and then make the JPanel draw it, and keep calling this instead of repaint() in my run() method, however I have no idea how to do that. I'd appriciate any input on the matter.
There are multiple ways to approach this.
The best is probably to use BufferStrategy and draw to that, of which I have included a code snippet that should work for you.
You can take this one step further and abandon Swing altogether, just using Frame/BufferStrategy. There is a fully working example (from which the code snippet was taken and adapted) in my question here:
AWT custom rendering - capture smooth resizes and eliminate resize flicker
Anyway, here is an implementation BufferStrategy that you should be able to just drop in:
// you should be extending JFrame
public void addNotify() {
super.addNotify();
createBufferStrategy(2);
}
private synchronized void render() {
BufferStrategy strategy = getBufferStrategy();
if (strategy==null) return;
sizeChanged = false;
// Render single frame
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
MyGraphics draw = strategy.getDrawGraphics();
draw.setColor(Color.BLACK);
draw.fillRect(0, 0, getPreferredSize().width, getPreferredSize().height);
draw.drawImage(ship.getImage(), ship.getCurrentX(), ship.getCurrentY(), null);
draw.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());
}
any drawing will still be performed in the Swing Thread, so no matter what you try work around, it wont help.
Make sure you are not doing any lengthy calculations in the swing thread, this may be stopping repaint from being executed as soon as it needs to be executed
Separate all the logic into 2 parts. Static and Dynamic. (e.g. sea and moving ship. Ship changes shape/location on a static image of sea)
Draw static content in an image once and use the image in your paintComponent(). Call dynamic parts painting after the static image.
Use setClip() to restrict repainting areas.
Calling repaint without any arguments means that the whole panel is repainted.
If you need to repaint parts of the screen (the spaceship has moved to a different location) you should make shure that only those parts of the screen are repainted. The areas that stay the same should not be touched.
Repaint takes coordinates of a rectangle that should be repainted. When moving the ship you should know the old coordinates of the ship and the coordinates the ship should move to.
repaint( oldShipCoordinateX, oldShipCoordinateY, shipWidth, shipLength );
repaint( newShipCoordinateX, newShipCoordinateY, shipWidth, shipLength );
This is usually much faster than calling repaint() without arguments. However you have extra effort to remember the last position of the ship and must be able to calculate the new position of the ship.
See also: http://download.oracle.com/javase/tutorial/uiswing/painting/index.html - especially step 3
Just for code that you post here:
1/ if you want to display Image/ImageIcon, then the best and easiest way is to Use Labels
2/ as you mentioned Runnable{...}.start(); Swing is simple threaded and all output to GUI must be done on EDT; you have to look at Concurrency in Swing, result is that all output from BackGround Task(s) must be wrapped into invokeLater(), and if is there problem with perfomancie then into invokeAndWait()
3/ if you be switch (between JComponents)/add/delete/change Layout then you have to call revalidate() + repaint() as last lines in concrete code block
EDIT:
dirty hack would be paintImmediately()
I have read that the repaint() method is only a request, and it doesn't execute every time it's called
It consolidates multiple repaint() requests into one to be more efficient.
I believe I'm noticing the effects of this, as my spaceship tends to lag ever so slightly when I'm moving it.
Then post your SSCCE that demonstrates this problem. I suspect the problem is your code.
Regarding the solution you accepted, take a look at Charles last posting: Swing/JFrame vs AWT/Frame for rendering outside the EDT comparing Swing vs AWT solutions.
I have a custom UI drawn for my java application. Right now I draw the entire UI from scratch. I know for a fact some parts of the UI are static. I know I could save these static parts to an image, but will this yield a improvement in performance (Since even an image must be drawn every frame)?
Is it plausible to save a reference to the Graphics2D object after the UI has been drawn and assign that to the new graphics object every frame (starting from a point where all the static components are drawn)?
Thanks in advance,
Alan
You don't need to redraw everything in every frame. So if you have static parts of your UI (or even dynamic parts that you know haven't changed since last frame) then you simply don't need to repaint them.
In my code (Swing games and simulations mostly) I usually try to follow the following rules:
Pre-prepare static images (e.g. BufferedImage textures for UI elements)
Override the paintComponent() method for each UI element individually to do the painting
Only call the repaint() method of any given UI element if I know that something has changed
Call repaint() in a timer-based loop for animation, but only call it on the portion of the UI that is being animated (e.g. a nested JPanel)
This approach seems to work and perform pretty well (though I'd welcome comments if there are ways to improve it!!)
There are two main optimizations you can do here. The first is to make sure that when you cause your UI to be repainted, usually done by calling repaint, make sure you call the version of repaint where you specify a rectangle that has changed. Only make the rectangle big enough to encompass the parts that actually have changed, not the static parts. For this to be effective you also have to pay attention to the clipRect in the Graphics2D object you are passed in paint(). That is used by the system to tell you exactly what needs to be repainted, in the above case usually the rectangle that you passed to repaint. Don't paint anything that lies entirely outside that rectangle.
You can also get significant performance improvements by caching the static parts of your interface in an image. Writing an image is by far the fastest way of getting things onto a screen. My measurements indicate that small images are faster than even a few simple drawing primitives. However you need to make sure the image characteristics match the screen, by using createCompatibleImage().
Of course you may be using a lot of memory to get this speedup. I would recommend testing to see if you need to do image caching before implementing it.
if some parts of the screen is completely static, then never redraw that part. Don't do a full-screen/window clear, just clear the part of the screen/window that changes all the time.
This way, you don't unnecessarily redraw the static image.
I'm doing a little strategy game to help me learn Java in a fun way. The thing is I visioned the units as objects that would self draw on the game map (using images and buffering) and would react to the mouse actions with listeners attached to them.
Now, based on some tutorials I've been reading regarding basic game programming, all seems to be drawn in the Graphics method of my Map class. If a new unit emerges, i just update the Map.Graphics method, it's not as easy as making a new Unit object which would self draw... In this case, I'd be stuck with a whole bunch of Map methods instead of using classes for rendering new things.
So my question is, is it possible to use classes for rendering units, interface objects, etc, or i'll have to create methods and just do some kind of structural programming instead of object oriented? I'm a little bit confused and I'd like to have a mental blueprint of how things would be organized.
Thanks!
Sounds like your objects need to have a common interface that they can all be down-casted to for rendering.
E.g. have a generic list of your interface type, populate it with the game objects, then enumerate the list and call the common method to do the rendering.
This is C# code, but it should be similar for Java
public interface IRenderable
{
void RenderMe(Graphics graphics)
}
List<IRenderable> myGameObjects;
foreach (IRenderable myGameObject in myGameObjects)
{
myGameObject.RenderMe(myMap);
}
While the objects are held in the list they can respond to events and update their internal state ready for the next render cycle.
As ck said, you could do this with a drawable interface, something like:
public interface GameElement {
public void draw(Graphics g);
}
public class Sprite implements GameElement{
private Image image;
private int x;
private int y;
public void draw(Graphics g) {
g.drawImage(image,x,y,null);
}
}
public class GameLoop {
public void drawElements(final Graphics2D g, final List<GameElement> elements) {
for (final GameElement gameElement : elements) {
gameElement.draw(g);
}
}
}
but the way you said you want to do it, with a listener, may give you problems in the future.
As dash-tom-bang already pointed, all elements are rendered in a single game loop, after all of them were already updated. If you do this with a listener and you have a game loop or any other thread modifying the unit list, you can end up with a concurrent access modification.
Besides, this way you will draw all elements in a single point, that will avoid some weird flickering on your game.
While "real" game projects come in many forms, ultimately you have something like this:
while True:
ProcessUserInput()
for o in objects:
o.Update()
for o in objects:
o.Render()
Use whatever mechanism you find dear to implement any and all of these functions. :) Polymorphism is fine, so you should feel free to use that if you're comfortable with that. The "world map" likely should be the first item in the list, unless your rendering system is sufficiently advanced to handle out-of-order drawing (depth sorting, basically).
From your question, it may be that the units are owned by the map? In that case, the Map.Render function would iterate over all of the units that it owns, calling Render on each one of them in turn. Regardless, it's probably cleanest if the code to draw a unit is in the class for that unit.
Good luck!