Java Swing brief paintComponent graphics - java

I am creating a java 2D game and have come to a point where I am thinking of creating "pop-up graphics" i.e graphics that will populate the screen when a certain event occurs. Say, you pick up a certain item, I want this item to be displayed in the middle of the screen in a box containing information about said item.
Currently I have one big paintComponent that paints all of the graphics for the game (tiles, entities, players etc (which has been done efficiently I might add)). I know that I can probably have a boolean value which checks if an item has been picked up in that method, but it feels wrong.
What I am wondering is, is there a way for items to have their own paintComponent so that when it is called, it will show say a bo for a brief period WITHOUT having a boolean value in the big paintComponent method that I currently use for everything?
Small code example (won't execute)
public class popUpGraphics extends (JComponent or JPanel or whatever works best for this scenario)
{
public popUpGraphics(){
}
#Override
protected void paintComponent(Graphics g){
//g.Draw(stuff);
}
}
and then somewhere in an event I instantiate this or somesuch.
I do not want this to override the other paintcomponent, I just want to add to it
(as if it was another layer) to the paintComponent
In short I want to know:
1. Is is possible to have brief graphics shown without including in the huge paintComponent method
2. What Swing library should be extended (JComponent, JPanel etc)
Thanks in advance!

Related

Mouselistener in chess game

I am creating a chess game, and I have now populated my graphic chessboard with all the pieces, now I need to use Mouselistner to move the pieces around. Before implementing the graphic version I created a 2D console version, that took in "player moves", so I do have all those methods, but I need to now use Mouselistener, I read up about the methods, however, do I need to implement mouselistener in each class?
I have 1 abstract Piece class as well as 7 subclasses (incl Dummy piece), and a ChessBoard class that populates all the pieces and provides methods for moving (from the console version..) so where do I put the mouselistener? In the Jcomponent extension, JFrame or ChessBoard class that contains the methods to populate the chessboard and moves?
Sorry for such a simple answer, but all you need to do is add the mouselistener to your ChessBoard class. From there I'm assuming you can access the Piece subclass objects you've instantiated and call methods on them (i.e. mouseClicked, piece.pickUp()). If you code is arranged in such a way that you need to implement a mouse listener in many of your classes, consider the following:
addMouseListener( new MouseAdapter() {
#Override
public void mouseClicked( MouseEvent e ) {
// Do something
}
} );
http://docs.oracle.com/javase/7/docs/api/java/awt/event/MouseAdapter.html
Also, if it were me, I would transfer the methods for moving your Pieces to your Piece class, preferably at a higher level and then you don't have to rewrite the same code twice. Then in your game, whenever mouseReleased is invoked, call some method like attemptToMove(BoardPoint p) that will check if your piece's current position and the new position, p are within your piece's means of travel. A BoardPoint could be something you set up with x, y coordinates for your own board in an 8 X 8 style, like a 2-dimensional integer array.
It depends somewhat on how you have your pieces implemented. If they are GUI objects themselves, such as buttons or panels, then putting the mouseListener on them will allow the Swing framework to figure out which one has been clicked on. If the pieces all extend a Piece class, then you can put a handler in that as long as the logic it needs to execute (such as moving a piece around) can be made the same for all pieces.
If, on the other hand, you are drawing graphic images on the board in your code, so there is no GUI component for Swing to detect being clicked, then it makes more sense to implement the mouseListener on the board. In this case, your code is going to have to figure out which square was clicked on, and whether it has a piece on it; after that the handling will be much like the previous case.

Simple painting

I have an seemingly very simple task at hand. I have a grid (500x500 right now) I want to visualize as it is populated and I want to write a class in Java that makes this easy for me to do. I'm thinking something along the line of:
public class Screen {
...
public void plot(x,y) {
// change the color of pixel x,y to black
}
public void clear() {
// fill the screen with white
}
}
I have been looking around and quickly found Canvas in awt, however from what I have been able to figure out so far, this widget will only allow me to draw on to it by overriding its paint method. This is far from optimal in my case as this will require me to draw the entire grid every time I wish to do just plot one single pixel.
Is there any way to get canvas to just draw a single pixel rather than the entire canvas? Or some other way to accomplish what I look for here?
I would prefer to avoid having to use any external libraries.
You will need to override the paint method to display the entire grid.
However, what you can do is create a BufferedImage that flips the one pixel, and draw that entire image to the component in the paint method, using Graphics.drawImage().
Unfortunately you have to override paint() and render the entire grid every time paint() is called. That's how graphical components work - the windows system/OS may request to repaint the component at any time (eg. when the window is re-shown/resized/moved)

How to handle custom, selectable line class in Java

I've got an application where I'd like for the user to be able to mouse-over and/or right click on a line that is being drawn on a JPanel. I fully expect that I'll implement the line as part of an object that will handle all of the behavior, but I've got a more fundamental question about how to implement the line shown in the below picture. First, the picture:
I can draw the line itself without any problem, but it's currently just being done in an overridden paintComponent() call in the parent JPanel. I have the rudiments of an idea on how to handle this:
public class ChassisLink extends JComponent implements MouseListener
{
//Rectangle to handle mouse-over and right-click for each segment?
public ChassisLink()
{
initializeLink();
}
private void initializeLink()
{
//Init stuff
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
//Paint the line(s)
}
//MouseListener events...
//When mouse-over on the line, display a tooltip
//When right clicking, display a different dialog
}
The issue I think I'm failing to understand is how to do the mouseover or click point check. Do I use a Rectangle and check whether the mouse is currently contained in that Rectangle, simply ignoring the triangular parts of the arrows? I'm perfectly sanguine about that. My issue then becomes how I would display these link objects over top of the existing JPanel that contains the chassis objects; it sounds like a candidate for a JLayeredPane, but any confirmation on that path?
Anyway, I appreciate any input people could give me. Feel free to ask for further explanation if something is a bit vague.
Thanks,
-Rich
You are on the right track. I would recommend using Area instead of Rectangle - you can get the arrows in that way too, and Area is extremely easy to manipulate using AffineTransforms.

java 2D and swing

I have trouble understanding a fundamental concept in Java 2D.
To give a specific example:
One can customize a swing component via implementing it's own version of the method paintComponent(Graphics g)
Graphics is available to the body of the method.
Question:
What is exactly this Graphics object, I mean how it is related to the object that has the method paintComponent? Ok, I understand that you can do something like:
g.setColor(Color.GRAY);
g.fillOval(0, 0, getWidth(), getHeight());
To get a gray oval painted. What I can not understand is how is the Graphics object related to the component and the canvas. How is this drawing actually done?
Another example:
public class MyComponent extends JComponent {
protected void paintComponent(Graphics g) {
System.out.println("Width:"+getWidth()+", Height:"+getHeight());
}
public static void main(String args[]) {
JFrame f = new JFrame("Some frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(200, 90);
MyComponent component = new MyComponent ();
f.add(component);
f.setVisible(true);
}
}
This prints
Width:184, Height:52
What does this size mean? I have not added anything to the frame of size(200,90).
UPDATE:
I understand that I must override paint to give in the Graphics g object the hints required to do the repaint and that I do not have to create a Graphics object as one will be given by platform.
What happens after that is what I can not understand.
E.g. does Graphics represent the screen and the object is painted accordingly on screen as soon as I start calling the various g.setXXX methods?
Does it get stored in a queue and there is a 1-1 association among g and each component? So the framework uses each g of each component to paint it one at a time?
How does this work?
Any help on this is highly welcome
Thanks
I understand your problem as I struggled with it for some time when I was learning Java graphics. It's not just Java 2D graphics - it is part of AWT.
When you create a JFrame or some other top-level object, it does a lot of work "behind the scenes" - part of which is creating a Graphics object. (There is not explicit notification of this, though if you stepped through the code with a debugger you may see classes which create the Graphics).
You then create components which you add, or register with, the top-level object. These all have to implement a call-back method, including
paint(Graphics g);
You will then #Override these methods so that when the component is rendered it uses YOUR paint method.
Do not try to save the Graphic or create a new one. Think of it as the framework taking the responsibility off you.
The size of components is often taken out of your hands. If you use a layout manager then it may decide to resize your component.
If you are coming from a procedural imperative background you may well have problems (I came from FORTRAN). My advice would be to try a number of tutorials and - at some stage - enlightenment will start to come.
The general documentation for Java graphics is poor. There are many concepts which are opaque (see How does Java Graphics.drawImage() work and what is the role of ImageObserver ). The early implementation was rushed through and had many bugs. Even now it is often unclear whether and in what order you should call methods such as setPack() and setVisible().
This doesn't mean you shouldn't use it! Just that the learning curve is a bit longer than IMO it should be.
MORE:
Also YOU don't decide when something is painted, the framework does. paint(g) really means "The framweork is repainting its components. What to you want this component to provide at this stage".
Maybe providePaintingInstructionsWhenRequiredForComponentGraphics(Graphics g) would be a useful name.
Similarly repaint() does not repaint at your orders, but when the system thinks it should. I haven't found it useful.
If you (say) resize a component interactively every slight change will normally trigger a paint(g). try putting a LOG.debug() in the paint code and seeing when it gets called.
What does this size mean? I have not added anything to the frame of size(200,90).
You added your component to the frame and set the size of the frame to be (200, 90). The default layout manager for the content pane of the frame is the BorderLayout, which means the component you added gets all the available space. The frame needs some space for the title bar and borders, so your component gets the remaining space.
The component does not create a static Graphics object association.
The graphics object is the wrapper for a platform handle giving access to a physical device, like the screen. It's valid for the time when "paint" is executed only, you can't store it and reuse it later. It is a resource managed by the "toolkit".
The component itself is an abstraction on top of the windowing system, that gets asociated shortly with this device for getting rendered.
EDIT
You can force such an association calling "getGraphics" if you feel the need to paint out of the "paint" callback. This should be a very rare case and you ALWAYS should dispose the Graphics afterwards.
Think of a Graphics like a piece of paper which you draw on to show how the Component looks like at that moment. After you've drawn it, the framework toolkit will trim off the edges and show what you've drawn to display the component. Moreover, the next time you draw the component, you'll be drawing on a different piece of paper, so don't keep the old Graphics around.

Splitting up the drawing of a GUI Element

I have to use a GUI Element that draws a picture at a specific screen position.
If the user selects this picture there is a border drawn around the Image.
Now we want to include another border that identifies pictures with a specific value for the user.
At the moment the Element looks at his internal state if it is selected and then decides how to draw itself.
graphic.drawImage(icon, x, y, null);
if (selected) {
drawBorder();
}
I don't like the idea of adding another if else to this drawing method.
I thought about creating a new class that inherits the behavior of the element and overwrites the draw method but that means duplicating the whole selected code in every inherited class.
Is there a nice possibility so solve this problem without creating a subclass?
Since you tagged this with design-patterns and you seem to be looking for a pattern-oriented approach, I'd suggest taking a look at the state pattern. The example on the wikipedia page even mentions keeping state while drawing a GUI. Unfortunately, this would mean you'd have to create another class with subclasses and overridden methods.
Is this going to be something that is likely to change? I.e. do you realistically think you're going to be adding new behavior to the drawing (e.g. if the user double clicks, draw a different type of border; if the user right clicks, change the color of the border), or is this it? If you see more behavior being added, I think going ahead and taking a more OO approach is wise. If it's just these two cases, I'd say just add and else if statement.
What do you have against if-else?
It makes less sense to me to create a whole new object for the selected item than to check a flag in the drawing function.
one possibility is to allow your drawBorder() method to take parameters:
private void drawBorder(boolean isSelected, boolean hasSpecialValue);
this method can determine which type of border to draw.

Categories

Resources