I recently started learning Java and aam writing a gui for a character creation sheet for personal use. I believe i have gotten all of the back end stuff working properly, but I can't test it outside of the console because I can't get the GUI to display anything other than a gray box.
I have a main class that creates the JFrame and calls the constructors for my other character classes to do all of the work, but for some reason, nothing shows up in the GUI. I'm not getting any errors or anything and I have spent several hours researching possible solutions to no avail.
My code:
The main method:
public static void main(String[] args) throws IOException
{
JFrame main = new JFrame();
JMenuBar menu = new MenuBar();
JPanel character = new CreatorGUI();
main.getContentPane().add(character);
main.add(menu);
main.setJMenuBar(menu);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setSize(10000, 10000);
main.pack();
main.setVisible(true);
}
The CreatorGUI:
public CreatorGUI() throws IOException
{
JPanel container = new JPanel();
JPanel stats = makeStats();
JPanel mods = makeMods();
JPanel character = makeChar();
container.add(mods);
container.add(stats);
container.add(character);
add(container);
}
I am trying to get the GUI working in its most basic form to make sure everything is working before I go back and refine the GUI, but I have hit a wall.
Any help is much appreciated!
main.getContentPane().add(character);
main.add(menu);
main.setJMenuBar(menu);
Using main.getContentPane().add(...) is the same as main.add(...). That is the component gets added to the content pane.
The default layout manager of a JFrame is a BorderLayout.
When you don't specify a constraint the component is added to the CENTER. However only a single component can be added to the CENTER so the "menu" is replacing the "character" panel.
Get rid of the main.add(menu) statement. It should only be added to the menubar so you only need to use the setJMenuBar(...) method.
The most suspect method call there is setSize which takes the pixel height and width. 10000 is probably too large as a width and a height and so you may only be seeing a portion of what you're trying to display. Changing it to something like 800 x 800 may allow you to see new things.
Related
I'm trying to make a visual novel using Java Swing, and so far it has been going smoothly. I'm using a JLabel that is attached to a JPanel to make the background image, and it starts good: image of a background behind a textbox + choice buttons, but when I try to update the image using Game.backgroundLabel.setIcon(newBackground);, it brings the background label to the very front: image of a background in front of the textbox, with only one of the three buttons showing. I'm new to the entirety of Java Swing, and mediocre at Java, but I'll try to include only the code that I believe to be relevant.
FROM THE MAIN CLASS (Game.java):
Container con;
JPanel backgroundLabel;
JLabel backgroundLabel;
// Creates background
backgroundPanel = new JPanel();
backgroundPanel.setBounds(0, 0, 800, 600);
backgroundLabel = new JLabel();
backgroundPanel.add(backgroundLabel);
con.add(backgroundPanel);
FROM A DIFFERENT CLASS (Story.java):
ImageIcon inCarBackground = new ImageIcon("C:\\Users\\kiwid\\eclipse-workspace\\FatuiBusiness\\backgrounds\\inCarBackground.png");
ImageIcon scaraSprite = new ImageIcon("C:\\Users\\kiwid\\eclipse-workspace\\FatuiBusiness\\sprites\\ScaraSprite.png");
This first update works, and the JPanel stays in the back where I added it in the Game.java class, as shown in the first image.
public void gameStart() {
position = "inCar00";
Game.nameLabel.setText("");
Game.mainTextArea.setText("My name is Lumine. I’ve recently sided with the Fatui - a huge mafia\norganization - through Scaramouche, who I befriended in Teyvat\nUniversity. I’m on a mission for the Fatui to steal a Blue Diamond\nring that once belonged to the Tsaritsa herself.");
Game.backgroundLabel.setIcon(inCarBackground);
Game.choice1.setText("");
Game.choice2.setText(">");
Game.choice3.setText("");
}
However, this update seems to change the order of the JPanel, and brings it to the front of the screen.
public void inCar01() {
position = "inCar01";
Game.mainTextArea.setText("Here with me are Tartaglia, Scaramouche, and Mona. Or, as I’m\nsupposed to call them here, Childe, Balladeer, and the Prophesizer.");
Game.backgroundLabel.setIcon(scaraSprite);
}
I've searched online for a solid 2 hours, but can't find anything good. I've read a little bit about JLayeredPane, but it seems like that revolves around user input, and when I try to use it, it says that I cannot add a JPanel to it.
Thank you all so much in advance! Please tell me if there's any other code I need to include, or if there's any code that I did not need to include (so I know for the next time I need help here).
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
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.
I think I solved my problem, but I don't know why it works this way, so I'm hoping someone can explain it to me so I don't do the same mistake again in the future.
Here's a quick example that is compilable of what I'm trying to do:
public class BoxLayoutTest extends JFrame
{
public BoxLayoutTest()
{
setSize(400,300);
JPanel mainPanel = new JPanel(new FlowLayout());
setContentPane(mainPanel);
JPanel subPanel = new JPanel();
subPanel.setLayout(new BoxLayout(subPanel, BoxLayout.PAGE_AXIS));
subPanel.setBackground(Color.BLUE);
JLabel labelTest = new JLabel("This is a test");
subPanel.add(labelTest);
labelTest.setPreferredSize(new Dimension(150, 20));
mainPanel.add(subPanel);
System.out.println(mainPanel.getSize());
}
public static void main( String[] args )
{
BoxLayoutTest testFrame = new BoxLayoutTest();
testFrame.setVisible(true);
}
}
At first, I had problems with the panel containing the JLabel not resizing like it should with the preferred size. I found out that it was because I was using some variation of mainPanel.getSize() as a preferred size for my subpanels. In this example, I'm using actual number values, which work.
The reason why it didn't work the old way (and that's actually the thing I'd like someone to explain), is why, as seen in the SOP line, mainPanel.getSize() returns a width and a height of 0 while it clearly takes the whole screen, which is 400x300.
Thanks #camickr for telling me I shouldn't set a preferredSize for my Panels, this helped me figure out where the problem was coming from.
Why [does] mainPanel.getSize() returns a width and a height of 0?
Until pack() "causes this Window to be sized to fit the preferred size and layouts of its subcomponents," the dimensions will be zero.
System.out.println(mainPanel.getSize());
this.pack();
System.out.println(mainPanel.getSize());
Console:
java.awt.Dimension[width=0,height=0]
java.awt.Dimension[width=160,height=30]
Its hard to say why your code doesn't work, since you didn't post your code. A few random lines of code does not give us the context of how the code is used in your program.
When you post a question you need to post your SSCCE which demonstrates the problem.
The glue should not have fixed the problem. The panel should still display, its just that it may not display in the position you expect it to be. A BoxLayout will attempt to resize components added to it to fill up the entire space available to it.
You should not be using setPreferredSize() on a panel. It is the job of the layout manager to calculate the preferred size of the panel based on the preferred size of all the components added to it. So I would say your code is still wrong.
is there a difference between typing this and this.getContentPane()
Certain methods calls are automatically forwarded to the content pane of the frame, which is why the end result is the same. Read the JFrame API. This is addressed in the API description or for the method in question.
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.