I am trying to create a mancala game board. For the purpose of the game, is there any way I can create a JButton and then just paint on it? I don't want to use setIcon property
You need to create a custom class which extends from JButton and then override it's paintComponent method
See Performing Custom Painting, Painting in AWT and Swing and 2D Graphics for more details
Remember though, a button typically has a lot going on, borders, content etc, this makes performing custom painting on them a little more tricky..
Related
I have a problem that I'm not able to understand, none the less solve.
I am making a clone of Asteroids (I call it Meteors, to be clever). Currently I have a class entitled MeteorGame which is the chief class that does the GUI drawing. MeteorGame extends JFrame to make the window, and it has another class that it uses to interpret keyboard events. Everything works great but I need to scale this up. Basically, what I have created is one "level" of the game, and now I need a level manager. I call this class Meteors and I want IT to handle creating the JFrame, rather than MeteorGame.
So to this effect, what I am trying to create is a system where Meteors class is basically a shell that creates a window and instantiates "levels" of MeteorGame in sequence. I have converted my MeteorGame class from JFrame to JPanel, so that my JFrame Meteors class adds JPanel components to itself as the user levels up.
I want each MeteorGame to draw itself and interpret keyboard event entirely autonomously, with the JFrame Meteors class simply working to queue up levels.
Many problems.
Is using the paintComponent() method the only way to draw to a JPanel? The way my old class works is it uses a constant while loop (managed for frame rate) to continuously call the update() and draw() methods that do all the work. So 40 times per second the method draws itself onto the JFrame.
With my updates converting draw() to paintComponent() the frame is drawn only once, and then disappears. I need to find a way to keep redrawing the JPanel continuously. (to eliminate flicker I draw the panel by writing to an image and then drawing the image)
Is there a better way to do all of this? I'm moving from a background in Objective-C iOS development where I am much more familiar with the view hierarchy. I'm sure that what I'm doing is not the most ideal situation by any means.
Also, when I create a JButton in the JFrame class and try to draw it using the following code, nothing happens. What am I doing wrong?
JButton button = new JButton("Close");
button.setLocation(300, 300);
add(button);
"Is using the paintComponent() method the only way to draw to a JPanel?"
Technically, no. But it's the correct way.
"The way my old class works is it uses a constant while loop (managed for frame rate) to continuously call the update() and draw() methods that do all the work"
Don't do this. Instead implement a javax.swing.Timer passing delay to timer, which will determine the frame rate. See more at How to Use Swing Timers
"With my updates converting draw() to paintComponent() the frame is drawn only once, and then disappears."
What you want to do is have a model class, say Asteroid which maintains the state of each Asteroid object. You can then maintain a List<Asteroid> that you can iterate through in the Timer calling each of its method to manipulate its state, then repaint() the panel with every tick of the timer. Then you can can iterate through the List in the paintComponent method, and call each Asteroid's draw method.
"I need to find a way to keep redrawing the JPanel continuously. (to eliminate flicker I draw the panel by writing to an image and then drawing the image)"
It most cases, using the Timer (if used correctly) will help in alleviating the flickering (of course given other factor that I may be unaware of).
"Is there a better way to do all of this?"
Take all the above notes into consideration and have a look at this answer, which takes all those points into consideration, and is also a wannabe asteroid like game/background of a game.
"Also, when I create a JButton in the JFrame class and try to draw it using the following code, nothing happens. What am I doing wrong?"
Can't tell with the bit of code you've provided.
Is there any alternative way to open a JFileChooser in which a JFrame only contains a Canvas?
I don't think so.
Taking a look at the documentation of Canvas, seem the only component one can add is a PopMenu
not possible without dirty hacks, I'd suggest to use JPanel instead of Canvas,
lightweight Swing JComponents are behind AWT Components,
for painting to Swing JComponents to use paintComponent instead of paint
I'd suggest don't mixing AWT Components (Canvas) with Swing JComponents (JFrame or JFileChooser)
I'm converting a 2D game from an Applet to a JFrame. I know I should add a JPanel to a JFrame and use the JPanel as my drawing surface but I'm not sure exactly what I should be subclassing. I was trying it with JFrame but I've read that it's usually unnecessary and a bad idea to extend JFrame (I wasn't adding any extra functionality anyway, so that makes sense). I need to override the paintComponent() method of JPanel so right now I'm leaning towards extending JPanel. Is there a better way of creating a 2D game surface or is extending JPanel and adding that to a JFrame an appropriate way to do it?
No, there is no better way, that's a very good option.
If you would extend a JFrame (the other option), your animation would blink on most windows family OS.
JPanel is a pure swing component and reacts better in java than a peered component like a JFrame.
Your choice is good, go ahead and have fun programming.
update
My knowledge in this area has grown since I originally answered the question and I agree with #Snicolas that you should use a JPanel.
JPanel (because it's a swing component) has builtin support for double buffering (AWT does not) and has better performance (so I hear, but I have no first hand experience with this).
You may find this article useful: http://www.oracle.com/technetwork/java/painting-140037.html#swing
original answer:
I recommend you subclass Canvas or Component or JComponent. My preference is Canvas. You should read the 2d graphics tutorial.
update
Use Canvas because it receives all the user input events and doesn't have the baggage of being a container. read more. Panels don't receive all mouse input events, for instance.
I want to draw a line between different components in a JPanel, but the line should be a component, ie, it can be clicked, highlighted, selected and deleted instead of just painting a line in a panel, is there anything like this or I must implement it by myself. And if I must implement it, how?
You could use a JSeparator. But you'll have to implement the click, highlighting, selection and deletion yourself. A JSeparator is just use to... separate sections in a panel.
If you mean that all these operations should be available when designing your GUI in a wysiwyg editor like NetBeans Matisse, then JSeparator is just what you need.
I tried to use prepared things like JSeparator, But I found the best way by myself and I implement it. I used a JLayeredPane for my container. I add my own JPanel behind the all layers and override its paint() method. in paint() method I used Java2D to draw a curve between Components on higher layers in JLayeredPane. You can see the result in below.
How to use paint() such that when repaint() is called the previously drawn object should not get deleted when drawing the new object. That is the drawing area must get UPDATED only and not REDRAWN.
In my code when one of many button is clicked, some aplhabet get displayed. I want to have functionality such that when other buttons are clicked the previously drawn alhabets must be present.Take is as if a string of alphabets getting created as the buttons are clicked.
Im using Java Swing for coding.
Some piece of my code:
if(source == btnAlpha[i] )
bollyDraw.repaint(); //bollydraw is an object of a JPanel extended class having implemented the paintComponent(Graphics g) method
In the paint() method:
if (word[i] == key) {
g.drawChars(word, i, 1, x, y);
}
In a project I worked on I used a List to store the objects that were to be drawn as a member of a class. Then as the user interacted with my UI I added/removed items from this list. The JPanel that rendered the items painted the items that were in this list. It's helps separate the UI logic from the paint logic as you can determine what goes into the paint list when an event is fired rather than in the paint method ( which should be as clean as possible ). However this will force you to repaint everything on every paint call.
In conjunction with this Kim's RepaintManager is a great way to limit what gets repainted. It is region based so there is some complexity in determining what region of the screen has changed. If you have the time it is better to use something like this otherwise it could be difficult to add this functionality down the road.
Your app must be prepared to re-paint anything it has painted. From your description, I'm afraid that means you have to keep track of everything you've painted.
The Swing behavior is partially dictated by the underlying window manager and graphical system, which at any time may chose to paint over an area where your application is present. You can override update() to control repaints initiated by your own app, and might be able to improve performance by implementing your own RepaintManager.
This tutorial explains Swing painting in more detail: http://java.sun.com/products/jfc/tsc/articles/painting/
Custom Painting Approaches shows a couple of ways to do this depending on your exact requirement.