I am coding an intense game and have an important question. In this game, thanks to searching and finding the revalidate() method and the repaint() method I have managed to successfully remove a JPanel and place another JPanel in it's place.
However... this is where the problems begin. I am able to do this, but there are multiple (can range from 9 to 729) such JPanels that need to be changed. I am able to do this in the JFrame no problem... however the issue I am currently facing is that although one JPanel is replaced properly, when I do the next one it is also replaced properly. However, after multiple tests I found that when the JFrame is refreshed by dragging it off and back on screen or any other such change the older changed JPanels vanish.
Is there any way that I can make the newly added JPanel's permanently there rather than vanishing if and only if the JFrame is refreshed??
Here is the code:
int a = f%27;
int b = g%27;
int c = a%9;
int d = b%9;
winningletter.setFont(new Font("Times New Roman", Font.BOLD, 17));
miniwin.add(winningletter);
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).removeAll();
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).setLayout(new GridLayout(1,1));
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).add(miniwin);
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).repaint();
metametametaminiminiwincheck[f/3][g/3]=winningletter.getText();
boardChanger(f, g, 4);
WinChecker(s, f,g,3,4,metametametaminiminiwincheck,x);
You should be using CardLayout: The CardLayout class manages two or more components (usually JPanel instances) that share the same display space.
It enables you to flip between panels the pro way. Each JPanel has an ID and you can display it using it.
link:
http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html
Code:
//Where instance variables are declared:
JPanel cards;
final static String BUTTONPANEL = "BUTTONPANEL";
final static String TEXTPANEL = "TEXTPANEL";
//Where the components controlled by the CardLayout are initialized:
//Create the "cards".
JPanel card1 = new JPanel();
JPanel card2 = new JPanel();
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
cards.add(card2, TEXTPANEL);
Calling the JPanel to display:
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, BUTTONPANEL);
I found that when the JFrame is refreshed by dragging it off and back
on screen or any other such change the older changed JPanels vanish
Emm... it seems naturally that UI repaint() method is being invoked authomatically after you re-size JFrame etc :)
thanks to searching and finding the revalidate() method and the
repaint() method I have managed to successfully remove a JPanel
It is quite strange you point your code strategy for the graphics2d only :S If you don't need to paint a new UI every time but keep them , as I could get it, inited in the heap not to re-init to set into your JPanel (?which is acting as a canvas)...
Actually, if you want all JPanel(s) be inited at the same time and just get them one by one by some event you can simply use some kind of storage as a Map or List etc, add them all (invisible) to your 'canvas' preferrably FlowLayout manager and make a needed one visible/invisible by an event for example...
Still the major task you trying to achieve is not pretty clear because you do accent Graphics2D so maybe you trying to achieve some another effect ? :S
P.S.
Anyway, it would be better you to show the problem code snippet because your current question contains too less information as for now...
EDIT
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).removeAll();
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).setLayout(new GridLayout(1,1));
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).add(miniwin);
((JPanel)((JPanel)newDossier.Board.metametametaboard[f/27][g/27].getComponent((a/9)*3+b/9)).getComponent((c/3)*3+d/3)).repaint();
Ok... so that is how you add component to your canvas... As I can see, the array in Board is static object... I may suggest, you have more than one canvas object(s)? If yes, it is naturally the miniwin(s) vanish because static array cannot have shared access by two invokers at a time; so I may recommend not to use static field in your case... Please read The Java Language Specification for more detailed information
If you have additional question details please comment
Report if that was helpful
Related
I am attempting to place two panels over the top of another two panels, so the positions match exactly. This will allow me to then paint over the top of the previous(bottom) panels. The reason for doing this, is that I have implemented a "drag a rectangle" zoom function, so on the panel the user will drag the mouse to draw a rectangle, and then the panel will become filled with the contents of that rectangle. However, I have now decided I would like include a visual representation of the rectangle as the user drags it.
Since I (assume) I cannot draw the rectangle on the bottom panel, since it already has a complicated paint on it anyway, I figured I would be able to draw it onto another panel that I would place on top. (If there is any easier way please shout!)
I am happy I have been able to get the panels into the correct position, using a BorderLayout/GridLayout combo, without the need for absolute positing, however the setOpaque method is not working on any of the three panels I have added. Does anyone know why this is?
Many thanks in advance, code below:
public void initiate() {
JPanel panel1 = new JPanel();
mandPanel mandDisplay = new mandPanel();
juliaPanel juliaDisplay = new juliaPanel();
JPanel detailsPanel = new JPanel();
JPanel bottomDetails = new JPanel();
JPanel panelForDisplays = new JPanel();
JPanel listenerPanelHolder = new JPanel();
JPanel listenerPanel = new JPanel();
JPanel blankPanel = new JPanel();
panelForDisplays.setLayout(new GridLayout(1,2));
detailsPanel.setLayout(new FlowLayout());
bottomDetails.setLayout(new FlowLayout());
panel1.setLayout(new BorderLayout());
panelForDisplays.add(mandDisplay);
panelForDisplays.add(juliaDisplay);
listenerPanelHolder.setOpaque(false);
listenerPanel.setOpaque(false);
blankPanel.setOpaque(false);
listenerPanelHolder.setLayout(new GridLayout(1,2));
listenerPanelHolder.add(listenerPanel);
listenerPanelHolder.add(blankPanel);
panel1.add(detailsPanel,BorderLayout.NORTH);
panel1.add(panelForDisplays,BorderLayout.CENTER);
panel1.add(listenerPanel,BorderLayout.CENTER);
panel1.add(bottomDetails, BorderLayout.SOUTH);
setContentPane(panel1);
setSize(width*2, height);
setResizable(false);
this.addWindowListener(new onClose(savedJulias));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
PS: A lot of code is omitted to avoid mess, but if anyone thinks they could solve with more code please say! Thanks :)
First off, adding two components at the BorderLayout.CENTER position replaces the first component with the 2nd, and so the 2nd doesn't cover the 1st, it displaces it. As per the BorderLayout API:
Each region may contain no more than one component,...
But having said that, as I understand your problem in greater detail, I think that your best solution is not to use JLayeredPane or to overlay two JPanels. The best solution is in fact to draw directly on the image-displaying JPanel. This is not hard to do, and shouldn't over complicate your code. For example.
You can use JLayeredPane to place one component to the top of the other. You can check this
I have a complex JPanel, that has various nested JPanels as components.
I want to replace one of these nested panels with a new one. But I can't get Top-Level Panel to redraw with new components unless I delete and add them all again:
JPanel topLevel = new JPanel();
JPanel upperPane = new JPanel();
JPanel lowerPane = new JPanel();
JPanel infoPane = new JPanel();
upperPanel.add(infoPane);
topLevel.add(UpperPane);
topLevel.add(lowerPane);
// The above (psuedocode) display nicely.
//Now I want to:
infoPane = new JPanel(); //Changed this Panel somehow;
topLevel.revalidate();
topLevel.repaint();
//The above 2 lines do NOT display the new information.
How can I get it to update?
If you're calling new JPanel() then you are referencing a different point in memory. Therefore, the reference to the old JPanel on upperPanel is lost, and changes made to infoPane after this will not be shown.
Haven't tried it myself, but change infoPane without calling new and that may well be your answer.
FWIW, the design paradigm you describe seems awkward to me. Wouldn't it be more straightforward to continue with that original infoPane instance and simply redraw its contents? Then your topLevel panel doesn't have to be involved with the change.
So, have your infoPane display whatever it is that your library gives you when you call new(), and just use new() to put new WhateverItIs() inside your infoPane.
Would that work in your context?
Hope this helps.
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.
This is my first time using a JFrame. I can't get the window to display the text areas I've nested inside the JFrame. I am trying to get the text field with my name in it to display above the tabulated results, which I have omitted the formatting for until I can get the JFrame to work.
public void printResults(String[] names, int[] temp, int[][] scores, float[] averages, char[] letters){
JTextArea outarea= new JTextArea(5,20);
JTextArea name = new JTextArea(5,20);
Font font = new Font("Tahoma", Font.BOLD, 48);
name.setFont(font);
name.setText("Made By Durka Durka");
JFrame window = new JFrame();
window.getContentPane().add(name);
window.getContentPane().add(outarea);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.getContentPane().setVisible(true)
String out = "foo";
outarea.setText(out);
//JOptionPane.showMessageDialog(null,window);
}
The probable reason why the JFrame is not appearing is because of this line:
window.getContentPane().setVisible(true)
The above line is setting the visibility of the Container to which the JTextAreas have been added, but does not control the visibility of the JFrame itself -- therefore, the JFrame itself is not being displayed.
(To be more precise, the JFrame.getContentPane method returns a Container, so the above code is actually calling the Containter's setVisible method.)
Try the following instead:
window.setVisible(true);
This will set the visibility of the JFrame itself to be visible.
Also, as the other answers have suggested, try using Layout Managers to control the locations of where the components should be displayed. The following are links to using two of the several Layout Managers which could be used to layout components.
How to Use BorderLayout
How to Use GridLayout
You should use some of the layout managers. This link should help you:
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html
The standard java layout managers are sometimes really hard to handle. Maybe you should also look into the JGoodies: http://www.jgoodies.com/ "Framework". It is easier to use and you realize that even a java gui can look nice..
First things first - are you calling printResults on the Event Dispatch Thread using SwingUtilities.invokeLater(Runnable runnable); or SwingUtilities.invokeAndWait(Runnable runnable);? Remember that you need to do all GUI work on the EDT.
If so, try this:
JFrame window = new JFrame();
// CHANGES HERE
window.getContentPane().setLayout(new BorderLayout();
window.getContentPane().add(name, BorderLayout.NORTH);
window.getContentPane().add(outarea, BorderLayout.CENTER);
// END CHANGES
I am writting a simple application which has a button that opens a new window then display a simple GUI/Text to acccept inputs from a user. but for some reason, I can get JLabel to be displayed on the new window. The application has following structure:
+mainFrame - JFrame
+newFrame - JFrame
-+newPanel - JPanel
----title - JLabel
----submitButton -JButton
...
Buttons and textfields all display fine, but Jlabels won't show up at all. I have tried using different layouts and all but I still can't get it shown. JLabels inside mainFrame tree, works fine.. so it seems like the problem is due to newFrame declaration or something, but then button should not be displayed either. Well, I am kindda lost and can someone suggest me what I should check?
Thanks : )
Make sure you do frame.pack() before you make it visible.
It can also help to set borders on different components (in different colours) for debugging just to see which components are/aren't turning out with size 0, in order to narrow down your problem. Logging, or breakpointing the component's setSize method, can help too.
Apart from that, maybe post some sample code? At the moment, you're question is fairly vague to answer.
Firstly, do you know about JDialog, and JOptionPane - these classes are often a better way of showing another popup window. It is quite rare to use 2 JFrames, (though sometimes a sensible thing to do).
Secondly have you done pack() and setVisible(true)?
The code below works fine for me. Either this breaks for you and it is something about your Java implementation, or you must be doing something different, in which case can you tell us what it is:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JLabelShower {
public static void main(String [] args) {
JFrame mainFrame = new JFrame("main frame");
JButton popup = new JButton("start new frame");
mainFrame.getContentPane().add(popup);
mainFrame.pack();
mainFrame.setVisible(true);
popup.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame newFrame = new JFrame("new frame");
JPanel newPanel = new JPanel();
JLabel title = new JLabel("title");
newPanel.add(title);
newFrame.setContentPane(newPanel);
newFrame.pack();
newFrame.setVisible(true);
}
});
}
}
In case you are using the JLabel as a placeholder, i.e. initialize it with an empty string and set the text later:
Since the JLabel's size gets calculated when the panel gets layed out (i.e. early on) and is based on the contained text, you'll probably end up with a label thinking it has a preferred size of (0, 0).
In this case you should tell the label what size it should ask for by calling setPreferredSize with an appropriate value.
And another cause might be the layoutmanager you are using in the surrounding panel. Maybe you are adding the label and the button in the same place, e.g. BorderLayout.CENTER. That would explain why only one of the two gets displayed.
Set the opacity of the JLabel object to true using title.setOpaque(true) . It will paint every pixel within bound of the JLabel object. This solved my problem of same type.