paintComponent method mixes different JPanel components - java

I'm developing a software which paints 2 different JPanel for my GUI: a score and a mast guitar. The score is a class which extends JPanel and has paintComponent() method like this:
public class PanelPartitura extends JPanel implements MouseListener{
public void paintComponent(Graphics comp){
super.paintComponent(comp);
comp2D = (Graphics2D)comp;
comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground();
paintStave();
paintNotes();
[...]
}
}
The mast guitar is a class as well:
public class PanelGuitarra extends JPanel implements MouseListener
public void paintComponent(Graphics comp){
super.paintComponent(comp);
comp2D = (Graphics2D)comp;
comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Then I call secondary methods to paint it:
paintBackground();
PaintPoints();
}
[...]
}
It still works fine. I add the class PanelPartitura to a JScrollPane in order to scroll when it's playing:
partitura = new PanelPartitura();
JScrollPartitura = new JScrollPane(partitura, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
Both JPanels mix each others painted components when the software is playing and scrolling. I would like to ask, if somebody has a clue about what on earth is going on? In my opinion:
It could be because I separated the painting methods as we've seen above:
paintBackground();
paintStave();
paintNotes();
then, when the software starts to paint, it paints some parts of the first JPanel (paintBackground() for example) and then some parts of the mast guitar (paintBackground()), then it changes again and the result is a mixture of both.
I think this is because it mixes different parts every time, I mean it doesn't behave in the same way every time it plays.
I really don't want this to be happening, so let me ask you: how can I make atomic methods to be sure this wouldn't be the problem?
I missunderstood the scroll method. I scroll on this way:
//the note playing currently position is saved in positionBar
positionBar = 150 + 50*PGuitarra.composicion.getAcordeSeleccionado().getPosicionXAcorde();
//horizontalScrollBar is moved to this position
PGuitarra.JScrollPartitura.getHorizontalScrollBar().setValue(positionBar);

I see that your paint methods are not using the same Graphics object (at the JPanel scope). Could that be the reason? And if it is, try passing comp (the Graphics object) as a parameter to paintBackground, paintStave and paintNotes.

Related

.setBounds() not working with nested JLabels

I'm making a Chess-like game in Java Swing (I know Swing isn't the proper way to go about it but I want to attempt it nevertheless)
I am having a problem with making the chess pieces show up on the display at the proper paces. Due to the nature of the chess pieces physical positions, I cannot use a layout manager.
The code looks something like this (it's admittedly awkwardly designed) :
public class Window extends JFrame {
private JPanel board;
public Window() {
super();
board = new JPanel();
JLabelOrganizer jlo = new JLabelOrganizer();
for (JLabel: JLabelOrganizer) {
JLabel.setBounds(calcX(), calcY(), width, height);
board.add(JLabel);
}
board.setBounds(x, y, width1, height1);
board.setLayout(null);
add(board);
setLayout(null);
}
public class JLabelOrganizer {
public JLabelOrganizer {
instantiate Type1 and Type2 JLabel objects and store them
}
public class Type1 extends JLabel {
}
public class Type2 extends JLabel {
}
}
}
The classes Type1 and Type2 represent the pieces.
When this runs, the JLabels (Type1 and Type2) do not show up at the correct place as designated from setBounds(). However, the board JPanel holding these pieces is set up at the correct place as designated from the call of its own setBounds().
Does anything have an idea as to why this is happening? Could it be because I'm inheriting from JLabel or the JLabel classes are inner classes? Thanks.
Edit: Forgot to specify that the JLabels only show up in the upper left hand corner of where the JPanel is located no matter what x and y positions I set them to.
I found the answer after looking at another post.
My class inheriting JLabel won't show up but if I change the type to JLabel it does
I accidentally overrided JLabel's getX() and getY() for my own purposes. Java Swing uses a component's getX() and getY() which is why the change with setBounds() was not being reflected.

Cant draw a shape to a specific panel in a NetBeans GUI

I'm trying to make a simple application to draw shapes to a panel in a jFrame. The GUI is a NetBeans generated jFrame. The application has three panels. the first two hold button groups to select the shape and a color. There's a button to draw the shape to the third panel once the selections are made.
What the GUI looks like
Unfortunately I'm having no love and can't make it work. For now I just want to get the button to draw a shape then I'll add the button functionality. Here's the code I have so far.
private void btnDrawShapeActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Draw shape = new Draw();
pnlDrawPad.add(shape); //pnlDrawPad is the name of the jPanel
shape.drawing();
}
import javax.swing.*;
import java.awt.*;
public class Draw extends JPanel{
public Draw(){
super();
}
public void drawing(){
repaint();
}
//#Override <-- gives error "method does not override or implement a method from a supertype"
public void paintCompnent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
g.drawString("Hello World!",40,30);
}
}
When I click the "Draw Shape" button nothing happens. I've been searching for a couple days now and am not finding the answer. Actually, its making me more confused as to what to do.
How to deal with this?
Don't keep creating new panels for each shape.
Instead you need a single panel with an ArrayList of objects you want to paint. Then you customize the paintComponent(...) method of the panel to iterate through all the objects in the panel and paint them.
So you button will just add another object to the ArrayList and then invoke repaint() on the panel.
Check out Custom Painting Approaches. The DrawOnComponent example shows how to paint a Rectangle objects from an ArrayList to get you started.
I found that with NetBeans you don't need to Override the paintComponents() method. Since all the GUI stuff is done when you design it, you merely need to add the drawings to the panel or what ever you need to do. I found you that by declaring and instantiating a 2D graphics object then drawing it to the place you want.
private void btnDrawShapeActionPerformed(java.awt.event.ActionEvent evt) {
int centerX;
int centerY;
Graphics2D drawFx = (Graphics2D)pnlDrawPad.getGraphics();
drawFx.setColor(Color.ORANGE);
centerX = (int)(458*Math.random());
centerY = (int)(440*Math.random());
drawFx.fillOval(centerX-50, centerY-50, 100, 100);
drawFx.dispose();
}
Worked like a charm so now every time I push the draw shape button it draws a shape to the panel in a different location every time. I've since put in the radio button functionality to change shape color and fill and added a button to clear the screen.
Not sure if this is the ideal way to do it but for this stupid simple little program it works well enough and I'm done stressing over it.

java - paint on top of nested components

So I am working on a Java game using a combination of swing components, and Graphics2D.
I have an AbstractLevelView class which contains all of the elements of the game inside.
This LevelView component uses a BorderLayout to display a context bar on the left, and a JPanel containing the game grid in the center.
My context bar and gridPanel all work fine, but what I want to do is paint "messages" directly to the AbstractLevelView, but I can't get any painting to work. This is presumably because there is nowhere to paint due to the nested components.
I've included an abbreviated version of my AbstractLevelView, as well as a test paintComponent method. I have tried using paintComponents, but it doesn't even get called.
Does anyone know what I can do so I can paint on top of my nested components?
public abstract class AbstractLevelView extends AbstractGameView {
private JPanel gridPanel;
private ContextBar contextBar;
public AbstractLevelView(){
gridPanel = new JPanel();
add(gridPanel, BorderLayout.CENTER);
contextBar = new ContextBar();
add(contextBar, BorderLayout.WEST);
}
#Override
public void paintComponent(Graphics g){
System.out.println("foo");
Image img = ImageManager.getImage("img.jpg");
g.drawImage(img, 0, 0, 300, 300, this);
}
}
Thank you MadProgrammer, for suggesting JLayeredPanes. I had attempted to use those back in the earlier stages of my game, but now that I know more about them, I've successfully implemented a solution.

Painting new panel on top of another one

I have a program where the base panel is just drawing the background (trees, water, etc), and i have a player and other objects moving around the screen. I don't want to call repaint() on the whole thing because it slows me down because it repaints the whole thing. When I try to add a new panel on top that will be repainted a lot and handle moving objects, nothing happens in my code. This is what I have in the constructor for the first
public GamePanel()
{ //some code
top = TopPanel();
top.setSize(this.getSize());
add(top);
//some more code
}
and then in the class for the toppanel
public TopPanel()
{
}
public void paintComponent(Graphics g)
{
i.drawItem(//);
player.draw(//fields);
}
And no matter what I do, I can't get anything to show up on the panel when i run it.
My general approach when rendering a complex but static 'background' with other things painted on top is to draw the background to a BufferedImage and simply redraw the image before painting the dynamic parts.

Java Paint Problem

Ok I'm wondering why the code below will not display the JLabel.
MyPanel is getting added correctly to a JFrame and everything because it all displays but will not draw the JLabel. Any help is appreciated.
public class MyPanel extends JPanel {
private Root root;
...
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
root.paint(g2);
}
}
class Root {
private Node1 node1;
...
public void paint(Graphics g) {
node1.paint(g);
}
}
class Node1 {
...
public void paint(Graphics g) {
JLabel jtp = new JLabel();
jtp.setLocation((int) x, (int) y);
jtp.setSize((int) width, (int) height);
jtp.setLocation(40, 40);
jtp.setSize(40, 40);
jtp.setText("Hello world");
//jtp.setVisible(true);
jtp.paint(g);
}
}
I suggest that you don't add Components to a Container in a paint method as 1) you do not have absolute control when or even if a paint method will be called and 2) paint and paintComponent have to be as blazing fast as possible, and this is not the time or place to update a GUI. 3) Since paint is often called many times, you will be adding components many times to your container, and all out of your direct control.
Also, while you're adding a component into Root (whatever Root is since it doesn't extend JComponent, JPanel, or similar) in the paint method, the Root object is never added to anything else that I can tell, and so it makes sense that nothing "added" to a component that is not added eventually to a top-level window will be visible.
Bottom line: I think you need a gui re-design as your solution. If you tell us more about it we can help you with it. Next we'll need to talk about use of layout managers and why setting absolute position and sizes of components is usually frowned on.
If anything I say is confusing, please ask for clarification, or if anything is wrong, please help me correct it!
You should not create your JLabel inside the paint method - instead, create it once when initializing your MyPanel. Your label is kind of a renderer component for your nodes, which in principle is a good thing. You may look how the renderers for JTable, JList, JTree work.
In your case, don't set the location of your label (it does not change anything, since it's paint-method expects its graphics object to be oriented by its own upper left corner), instead translate the Graphics-context:
Graphics copy = g.create((int)x, (int)y, (int)width, (int)height);
jtp.paint(copy);
(Graphics2D has some more fancy methods for shifting, rotating, scaling the context, too.)
Other than this, I don't see any problems. Make sure your Node1.paint() method gets actually called by putting some System.out.println() in there.

Categories