Overloading paintComponent() - java

I'm currently making a basic connect four game with a GUI and I'm trying to figure out how I can place the pieces on the board. I have a method that can locate which space the user would like to put the piece on, but I'm unsure how to paint the pieces in. Since paintComponent() is always called without an actual method call and the default constructor only takes a Graphics object, how could I overload paintComponent() so that it can take different arguments (these arguments are the location of the piece) and the compiler will know to call my new paintComponent() method?

how could I overload paintComponent() so that it can take different arguments
You can't. Or rather, you can create an overloaded method, but the JRE won't call it.
Instead, the code needs to keep a model of the game state, when it changes, call repaint(). In the normal paintComponent(Graphics) method, use the model to determine how it should be drawn.
Obviously, for this to work, the model must be within the scope of the method - so you might make it a class attribute.

Related

2D Game not repainting

I checked the other questions and couldn't find one with the same case as me so here's my question.
I am making a 2 player stick fighting game that you can play on the same computer using different keys. Everything's fine but when I try to move the oval on the screen with the keys, it's not moving.
Here's the code for my first class - http://pastebin.com/wA0JXdzr
second class - http://pastebin.com/ArByyirt
I think I need to call repaint in my second class in the gameloop, but it's saying that it can't make a static reference to it.
You are trying to call a non static method directly from another class which is not legal in java. The paint() method in your first class is the non-static method. You were able to use the variables stickx2 and such because they are static as defined in your first class.
Thus, I suggest you create an object of stickFrame() in the gameLoop class and copy all your code in your stickframe main method and put it in your gameLoop main method. It is highly not recommended that you have two main methods.
Declare a Stick Frame variable below your Serialization ID.
StickFrame s;
Then instantiate it in your gameLoop constructor
s = new StickFrame();
Now we need to fix the repaint from another class problem.
To do this we need a method in the gameLoop Class.
public void repaintStickFrame()
{
s.repaint();
}
Then call it by
s.repaintStickFrame() in your loop.
or you can just call
s.repaint();//place in loop
Heres a link to a question that is similar to yours and has solutions as well
Calling repaint from another class JFrame
Heres a link that explains how you can call an objects method once you've created one (Like we did above, which allowed us to call the repaint() method from a different class):
https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html

Does SwingUtilities.updateComponentTreeUI() method set the current L&F to all super and sub components?

Background:
From the documentation, the method SwingUtilities.updateComponentTreeUI() ask to each component in the tree (What tree?) to update their own UI properties calling the method updateUI().
SwingUtilities.updateComponentTreeUI() is strictly recommended to be called after we set the LAF, calling the method: UIManager.setLookAndFeel(LAFClassName), otherwise the LAF theme could not be applied to some components and, worst, some components could not be redesigned (and some exceptions could be thrown?).
I am new to this kind of things and I discovered the method SwingUtilities.updateComponentTreeUI() after the discover of the more suggestive UIManager.setLookAndFeel(LAFClassName) method.
Before discovering SwingUtilities.updateComponentTreeUI() I had been having some problems/Exceptions/NullPointerExceptions, and the truth is that I really wasn't understanding the reason of them until I didn't discover the SwingUtilities.updateComponentTreeUI() method, which made me understand that some components in the tree could not be updated to the new LAF.
Concrete/real problem:
For instance, if I have a
subJFrame
(instantiated dynamically or triggered by an ActionEvent (click) in the
mainJFrame
), where I set the look and feels properties, and then I call SwingUtilitiesupdateComponentTreeUI() passing to it a reference to the mainJFrame:
SwingUtilities.updateComponentTreeUI(mainJFrame),
is this last one going to update all its sub-components/subJFrames (and hence updates the subJFrame where I set the LAF) ?
This is not a trivial question (also keeping in my mind what the documentation says), because I call the UIManager.setLookAndFeel(LAFClassName) method in the subJFrame (what actually this call does?) and then I call SwingUtilities.updateComponentTreeUI() method passing to it a reference to the mainJFrame, so what LAF theme is going to be applied to all the sub-components of the mainJFrame? And if some of the sub-components/subJFrames haven't been initialized yet?
You never need to call updateComponentTreeUI if you only set the look and feel before creating components.
If you change the look and feel after having already created components then you need to call the updateUI() method on every existing component. This is what updateComponentTreeUI assists with: it calls updateUI() on the component, as well as all the components it contains (and all the components that they contain; this is what it means by "tree").
If I have a subJFrame where I set the look and feel, and then I call SwingUtilities.updateComponentTreeUI() passing to it a reference to the mainJFrame: is this going to update all its sub-components/subJFrames (and hence updates the subJFrame where I set the LAF)?
If by subJFrame you mean a window that is directly contained within the other (a JInternalFrame) then yes. If you mean a frame which was merely opened from the other frame, but is a separate top-level window, then no, it won't update it, because it is not contained within the component that is being updated.
This is the loop I use for updating all top-level windows after changing the look and feel:
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
if (w.isDisplayable() &&
(w instanceof Frame ? !((Frame)w).isResizable() :
w instanceof Dialog ? !((Dialog)w).isResizable() :
true)) w.pack();
}
That loop won't catch any components that are not currently attached to windows. For example, this can include JFileChoosers, if you keep instances of those in variables when they're not actively being displayed, in which case you will need to call updateComponentTreeUI separately on those.

Is there a Java.Swing equivalent to AS3's ADDED_TO_STAGE event?

In AS3, there is an event that listens for when an object is added to the stage. This is useful for cases where, for example, some variables are not set until it is added on-screen. By waiting until the object has been added, you can assure that all of those variables are set.
Is there an equivalent in swing? For example, I have a function that relies on an objects getWidth function. Obviously, if I try to call this before the object is added on screen, this function will have problems because the width will be zero. I would like this function to be called as soon as the component is added and has a width. In as3, I would do something like:
myComponent.addEventListener(Event.ADDED_TO_STAGE, myFunction).
How would I do that in Java?
Depending on your setup, a ComponentListener might be enough. There is a section in The Java Tutorials about ComponentListeners.
Another way of initializing stuff as soon as it is displayed is overriding the paintComponent method and performing the setup on the first invocation.
JavaScript is different from Java. There are no function objects in Java and hence no JavaScript-style callbacks. In Swing you can react to events related to showing/adding of components by adding ComponentListener or ContainerListenerto either component or container via addComponentListener() and addContainerListener() methods.

How the paint method run without in main method?

Here, we have two classes. One of them is application class.
And the output is a jframe which has a rectangular inside. But I don't get it, we don't write paint method in main method. How can it run?
The paint method is automatically called to refresh your window. For example, the paint method is automatically called when resizing your window.
You can also force to call the paint method by calling the repaint() method of JFrame.
Also, if you're looking for the declaration of paint method, it is in java.awt.Component. Dont hesitate to have a look to the javadoc

Force repaint from another class - Swing

I basically have 1 class called ClueGame dedicated to painting the main gui using swing.
In this class, I iterate through a list of BoardCell objects, and call boardcell.draw(g) from within paintComponents(Graphics g), which draws rectangles to the board.
However, in a different class entirely, the WalkwayCell class (a child of BoardCell), I need to update the color of specific rectangles. I'm thinking something like cell.updateColor()
But obviously I need to get draw to do that some how. I don't know how to update the color of one object (rectangle) on the board because I can't call draw because I don't have a graphics object.
Hopefully that makes sense. I can post code if someone requests it.
You have any number of options...
You Could
Pass a reference of your ClueGame to the instances of WalkwayCell which would then be capable of calling repaint on the ClueGame reference directly.
The problem with this is you expose the entire ClueGame class to ever instance of WalkwayCell, which allows them to do whatever they want to it...
You Could
Use an observer pattern, to allow the ClueGame to monitor changes to the state of the WalkwayCells
This means that WalkwayCell doesn't really care, it will simply provide some kind of event notification when the state of the object changes and doesn't expose parts of your application to other parts that have no right to know about...
Swing makes use of the observer pattern for it's listener API. You could take a look at Writing Event Listeners for some more ideas...
When creating a Swing GUI, it’s important to create GUI model classes. The model classes hold the data for the GUI. Having model classes makes coding the Swing view classes so much simpler.
In your case, you would change the state of the instance of the WalkwayCell class, using a method like cell.updateColor(), as you suggested. First, you update the model instances. Then you draw the model instances on the view.
I've explained this concept in more detail with a working example in my Hangman Swing GUI article.

Categories

Resources