I am currently working on an intro screen for a game designed using JOGL. I want the intro to be a JPanel with a few buttons to alter options before starting the game.
So, I have JFrame which I add a GLCanvas to. The GLCanvas also contains a GLEventListener. Finally, I add the JPanel.
I have overridden the JPanel paintComponent method to set a background image. I have a few buttons within the panel. Whenever you click the 'play' button, it calls a function which does:
frame.remove(JPanel);
frame.repaint();
animator.start();
What happens is that my JPanel goes away correctly, but when repaint is called, my frame is just filled with grey. I know that the animator is starting correctly as the display method in my GLEventListener is getting called.
Does anyone know what the problem is there?
What is your LayoutManager? If you didn't specify one, then by adding the JPanel you replace the GLCanvas.
I would make your code do this:
frame.remove(JPanel); frame.add(glcanvas); animator.start();
you may need to throw in a frame.revalidate(). I'm not up on how all that works right now.
Related
My desktop Java application has a JMenubar with several JMenuitems, and underneath it is a JPanel which I re-render when an item in the dropdown menu is clicked.
It all works okay, but my JPanel is re-rendering (my overridden paintComponent is being called) when I hover or click on my JMenuitems.
That is a problem, because on the JPanel are programmatically constructed images (randomly seeded), and the construction takes a while, so my program hangs if i hover over the menu too much..
Why is this and how do I fix it?
Edit: Even if I seed the random values and get the same image, the program does too many unecessary calculations and it becomes slow.
… (my overridden paintComponent is being called) when I hover or click on my JMenuitems. That is a problem, … Why is this …
It is expected behavior. The toolkit will repaint a panel whenever it determines it is necessary to do so: E.G.s
A menu appearing or disappearing over it
Another window or dialog dis/appearing over it
The user resizing the window …
… on the JPanel are programmatically constructed images (randomly seeded), and the construction takes a while, …
To avoid having to recreate a complex paint, draw the details to a BufferedImage then either paint the image in the paint method, or (simpler) display it in a label.
I have define the JPanel named drawPanel, and a button named Jbutton1 with an ActionListener. I want to continue draw something on the drawPanel after clicked the Jbutton1. And I do not want to clear the drawPanel first and draw more things, I just want to continue draw on the drawPanel and show it in a JFrame.
Check out Custom Painting Approaches for the two common ways to do this:
Keep a List of Objects that you want to paint and then iterated through the list every time.
Paint to a BufferedImage and then just paint the BufferedImage.
I'm trying to build a program that displays random shapes and random text. This is my code inside my class that extends JPanel.
#Override
protected void paintComponent(Graphics g) {
// draw all shapes
super.paintComponent(g); // clears the background
this.add(new JLabel(new RandomText().getRandomSentence()));
for (RandomShape shape : shapes) {
shape.draw(g);
}
}
I use a JPanel instead of g.drawString() to in the future display HTML code. I also have a button that "regenerates" the window, by calling the repaint() method. However, when I push the regenerate button, thus calling the repaint() method, the shapes change (like they're supposed to), the text however does not. What I find even stranger is when I resize the window new labels are continously added to my panel (with random text like they're supposed to).
Does super.paintCompnent(g) not clear components added to the panel? If so, why does calling repaint() myself not add extra labels, like resizing the window does?
Resizing the window also forces validate() to be called which lays out the components on the panel again - simply repainting does not.
However, in your painting method you're adding a new JLabel each time and not removing any, which almost certainly isn't what you want to do. You should keep track of the JLabel in a separate variable and either change it's position when you repaint (preferably) or remove it before adding a new one.
This adds a new label to the panel at every repaint:
this.add(new JLabel(new RandomText().getRandomSentence()));
Instead, you should add one label once to the panel, perhaps in the constructor of your class. Then setText(aRandomSentence) for it, when the button is pressed. Do not modify components in paintComponent().
when super.paintComponent(..); is called it wipes out the graphics elements. It however does not change the objects that have been added to it. You will be adding a new label to the panel every time repaint is called.
When you call repaint(); yourself, it's not guarenteed to call the paintComponent of all components. But when you resize it HAS to since everything is going to be different.
This happens because you're constantly adding new JLabels to the JPanel.
Keep track of your JLabel and change it's text instead of adding new JLabels.
In my code I override the paintComponent method and draw a rectangle inside JPanel.
The JPanel is then added to JFrame and I use a method that updates the position of the rectangle via a Thread.
The rectangle does actually move .. but only when I minimize the window and maximize it back again. So in other words.. it doesn't do it as I'm looking at it.. the rectangle will just sit there.. but after I minimize and bring the window back up, the rectangle will have moved.
What can I do to fix this?
I am guessing you forgot to call the Repaint of the JPanel whose paintComponent you are overriding everytime you update the object. The reason you are only seeing the change on minimize/maximize is because that is when swing calls the repaint of the component.
I am new to the java (and programming in general) and I am trying to make my very first program. I'm stuck on the same problem for about 5 hours now, so I've decided to ask for help.
Basically I'm trying to make a program (2d game) that has about 20 positions on the board. Each position is either blue (owned by player1), red(owned by player2) or black(not owned by anyone).
The way I'm going about this is in main I've put a method that calls setup game, and then a method that plays game. I am working on the setup game, basically all it does is it makes an object of class Background (extends JPanel, and overrides paintComponent()) and 20 objects of class Position(extends JPanel, and overrides paintComponent()).
So far I'm stuck on putting those Position objects on top of Background object.
When I do:
Background background= new Background();
frame.getContentPane().add(background);
Position position1= new Position;
frame.getContentPane().add(position1);
frame.setVisible(true);
it shows only a circle and no background as I was hoping, if I first add position and then background, I only have background and no circle.
Anyway I'm new to the java and I am still having trouble founding my way around, however I've tried to search for solutions, and I've found many different solutions to this problem (such as adding position to background first, and then adding background to frame, etc.) but I couldn't make any of them to work.
I am aware that the way I am adding them both to frame is (very likely) completely wrong, but I wrote it that way so you would (hopefully) be sure that what I've wrote actually does show you that my code for each of those classes draws something on the screen.
PS: I didn't copy my code here as most of variable and method names aren't in English so it's fairly hard to read, but if you still think its needed, I will add it. Also I'm sorry for my probably stupid question, but I'm kinda hitting a wall here and I've no idea what else to try.
Basically I'm trying to make a program (2d game) that has about 20
positions on the board. Each position is either blue (owned by
player1), red(owned by player2) or black(not owned by anyone).
Painting in Swing by default never returns PreferredSize, is required to override getPreferedSize()
JPanel has implemented FlowLayout in API, this LayoutManager accepting only PreferredSize came from JComponents added to this container
after a.m. changes to post an SSCCE, short, runnable, compilable
Background background= new Background();
frame.getContentPane().add(background);
Position position1= new Position;
frame.getContentPane().add(position1);
A JFrame uses a BorderLayout by default. Also by default when you add a component to a Container that uses a BorderLayout the comopnent is added to the CENTER. Only one comonent can be added to the CENTER so your Position comonent replaces the Background component.
You want to add the Position to the Background and then add the Background to the frame. Something like:
Background background= new Background();
Position position1= new Position;
background.add(position1);
frame.add(background);
Note: there is no need to uses getContentPane() when adding a component to the frame.
The root panel should be a JFrame with a Container class underneath. When you call someRoot.window.container = yourJPanel, that loads the JPanel as the main component view of the JFrame. Note, a JFrame can only hold one JPanel but other JPanels can hold other JPanels. Just as you add the initial JPanel to the JFRam, a JPanel's own container can be another JPanel. Hope this helps.
Like this:
JPanel temp = new JPAnel();
frame.getContentPane().add(temp);
temp.getContentPane().add(new JPanel());
After these additions, there is a command that is illuding me but you call on JFrame to get it to refresh in real time. I think it is something like:
frame.validate(); //thanks #SMT
or something,
Try using something like
jPanelExampleName.validate();
jPanelExampleName.repaint();
after adding your JPanels.
It sounds like you want to use one JFrame and attach JPanels to it. This is how I personally would do it.
Declare your JFrame and JPanels
JFrame frame1 = new JFrame( "App Name");
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
JPanel panel4 = new JPanel();
Set the Background (I'm using colors but you get the idea)
panel1.setBackground(Color.orange);
panel2.setBackground(Color.orange);
panel3.setBackground(Color.orange);
panel4.setBackground(Color.orange);
Set your layout for the JFrame (I'm using BoxLayout not sure which would be best for you) You can find the best one for you and some sample code here. Also just set the default close operation.
frame1.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame1.setLayout( new BoxLayout( frame1.getContentPane(), BoxLayout.Y_AXIS ) );
Then Just attach your JPanels
frame1.add( panel1);
frame1.add( panel2);
frame1.add( panel3);
frame1.add( panel4);
frame1.pack();
frame1.setVisible( true );
This will allow you to use the JPanels you created and then change the colors via other methods.