I'm using card layout to show and hide every panel I made. For the first couple of days, it has been working fine for the first 5 panels I've made. The weird thing is, all of a sudden, my new, 6th panel does not seem to be appearing. There is no syntax error anywhere, I went through all my codes again to look out for any typos, misspellings, failed copy pastes, but can't seem to be able to find anything out of the ordinary... I tried moving on to making the 7th panel today, but the 7th panel was not showing up either.
public ViewController(int width, int height){
this.WIDTH = width;
this.HEIGHT = height;
bgColor = new Color(255,204,153);
mainFrame = new JFrame ("Mei Centre");
mainFrame.setPreferredSize(new Dimension(WIDTH,HEIGHT));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout (new CardLayout(0,0));
mainPanel.setBackground(bgColor);
mainPanel.setVisible(true);
}
public void makePanels (){
// make most panels
mainPage = new MainPagePanel(this, WIDTH, HEIGHT, bgColor);
adminLoginPage = new AdminLoginPage(this, WIDTH, HEIGHT, bgColor);
playerLoginPage = new PlayerLoginPage(this, WIDTH, HEIGHT, bgColor);
playerLoginPrompt = new PlayerLoginPrompt (controller, this, WIDTH, HEIGHT, bgColor);
playerMainMenu = new PlayerMainMenu (controller, this, WIDTH, HEIGHT, bgColor);
gameSettings = new GameSettingPanel (controller, this, WIDTH, HEIGHT, bgColor);
dealerShuffle = new DealerShufflePanel (bgColor);
// add panels to frame in chronological order
mainPanel.add(mainPage, "MainPage"); // index 0
mainPanel.add(adminLoginPage, "Admin"); // index 1
mainPanel.add(playerLoginPage, "Player"); // index 2
mainPanel.add(playerLoginPrompt, "LoginPlayer"); // index 3
mainPanel.add(playerMainMenu, "PlayerMainMenu"); // index 4
mainPanel.add(gameSettings, "GameSetting"); // index 5
mainPanel.add(dealerShuffle, "DealerShuffle"); // index 6
mainFrame.add(mainPanel);
mainFrame.pack();
mainFrame.setVisible(true);
}
// make and add GamePlayPanel into mainPanel
public void makeGamePanel(Dealer dealer, GameTable table, ArrayList<GamePlayerInterface> gamePlayers) {
System.out.println("Making gamePlayPanel");
gamePlay = new GamePlayPanel (controller, this, WIDTH, HEIGHT, bgColor, dealer, table, gamePlayers);
mainPanel.add(gamePlay, "GamePlay"); // index 7
mainPanel.repaint();
}
This is my ViewController (class that controls the main flow of my GUI). I made a main panel and set layout to CardLayout, and made all my other panels and added them into the main panel. The 7th panel was added in later, outside the constructor (inside makeGamePanel method)
public void showPanel(String page) {
System.out.println("Showing panel -> " + page);
CardLayout cl = (CardLayout)(mainPanel.getLayout());
cl.show(mainPanel, page);
}
This is my method used to control which panel to show. It works from panel in index 0 up to 5 (list in screenshot above)
private class changePanel implements ActionListener{
String page;
public changePanel(String page){
this.page = page;
}
public void actionPerformed(ActionEvent e){
System.out.println(page + " is clicked");
vController.showPanel(page);
}
}
When I click on some Jbuttons in any of the panels above, I will assign this action listener with the appropriate panel name, so that it may call the method to show the appropriate panel.
private void startRound(GameTable table, ArrayList<GamePlayerInterface> gamePlayers, GamePlayer human) {
// GAME START! dealer shuffles cards
dealer.shuffleCards();
view.showPanel("DealerShuffle");
/* insert some delayer here*/
/*does some game logic action*/
// make game play GUI
view.makeGamePanel(dealer, table, gamePlayers);
view.showPanel("GamePlay");
My issue is with the 6th and 7th index panel (DealerShuffle, and GamePlay), which are called in my game controller (class which handles all game logic running) .
I've checked to make sure that my controller and my view are both linked to each other, so it doesn't seem to be an issue of different instances.
Enter Choice --> Player is clicked.
Showing panel -> Player.
LoginPlayer is clicked.
Showing panel -> LoginPlayer.
Player Login information entered, checking information
username input got is : maggie
password input got is : joey
Showing panel -> PlayerMainMenu
Play game button clicked
Showing panel -> GameSetting
Game start button clicked!
Setting game with 1 opponents, 1 difficulty, 1 size.
Game Start
Showing panel -> DealerShuffle
Dealer deals cards onto table
Making gamePlayPanel
Game Play Panel has been created
Showing panel -> GamePlay
These are the results of a normal run. In the bottom few lines, it shows that my program is running properly, and that its even trying to show the DealerShuffle panel and GamePlay shuffle, but what actually happens on screen is: right as the changing panel method is called to show DealerShuffle, the previous panel (GameSettings) is actually disabled, but DealerShuffle doesn't appear, so the screen is stuck at an after-image of the GameSetting panel, with nothing for me to click on or interact with. Needless to say, my GamePlay panel afterwards wasn't showing up either.
If anybody wants to check out my whole program to run, here is the link to my zipped files:
Program zip file
The codes will be in a quite a mess, as I've only started implementing GUI on a program which was previously running off on console.
Thank you for your time and help!
Nvm, I may not have fixed the issue with the way my codes are currently structured or learnt what was causing the issue in the first place, but I managed to get it to work after building it from scratch again and restructuring my codes. This time instead of creating the JPanels in the viewController and adding them inside, I've build the JPanels in the Controller instead and passed them into the viewController to add to the JFrames. So anyways, problem solved. Thanks to all who helped!
Related
I am beginner in Java. This is my first project.
The GUI of the code keeps changing every time I run the code.
Sometimes output doesn't even load completely.
This is the code for just initializing a chess board 8X8 jbuttons.
I have put down the images do checkout the hyperlinks below.
Is there any solution that shows the same output every time the code executes?
package chess;
import game.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.*;
public class board{
static JButton [][] spots =new JButton [8][8];
public static void main(String[] args){
board b =new board();
b.initializeboard(spots);
}
public void initializeboard(JButton [][] spots){
JFrame f = new JFrame("CHESS");
f.setVisible(true);
f.setSize(800,800);
GridLayout layout =new GridLayout(8,8,1,1);
f.setLayout(layout);
for(int ver=0;ver<8;ver++){
for(int hor=0;hor<8;hor++){
JButton button = new JButton();
if((ver+hor)%2==0){
button.setBackground(Color.WHITE); }
else{
button.setBackground(new Color(255,205,51)); }
pieces p =new pieces();
spots[ver][hor] = button;
p.setButton(button);
f.add(button);
}
}
} //initialize board
} // close board
Improper Execution
Correct Execution
Incomplete Execution
I am beginner in Java.
First of all, class names SHOULD start with an upper case character. Have you even seen a class in the JDK that does not start with an upper case character? Learn by example from the code in your text book or tutorial.
Is there any solution that shows the same output every time the code executes?
All components should be added to the frame BEFORE the frame is made visible.
When the frame is made visible the layout manager is invoked and the components are given a size/location. If you add components to a visible panel, then you need to invoke revalidate() and repaint() on the panel to make sure the layout manager is invoked.
Must admit I'm not sure why you get this random behaviour. Some components are getting a size/location and other are not even though the layout manager is not invoked.
I would suggest you restructure your code something like:
JPanel chessboard = new JPanel( new GridLayout(8, 8, 1, 1) );
// add buttons to the panel
JFrame frame = new JFrame("CHESS")
frame.add(chessboard, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
Other comments:
Don't set the size of the frame. Using 800 x 800 will not make each button 100 x 100. The frame size also include the title bar and borders, so each button size will be less than you expect.
Instead you can create a variable outside of your loops:
Dimension buttonSize = new Dimension(100, 100)
Then when you create the button you use:
button.setPreferredSize( buttonSize );
Now when pack() method is invoked is will size the frame at the preferred size of all the components added to the frame.
All Swing components should be create on the Event Dispatch Thread (EDT). Read the section from the Swing tutorial How to Make Frames. The FrameDemo.java code shows you one way to structure your class so that the invokeLater(…) method is used to make sure code executes on the EDT.
Don't make your variables static. This indicates incorrect class design. Check out the MenuLook.java example found in How to Use Menus for a slightly different design where your ChessBoard becomes a component created in another class. You can then define your instance variables in that class.
We have a project for university which is a program to hold handouts and feedback for courseworks done.
What we've thought of is breaking the whole thing down into smaller pieces, for example:
You have a coursework which requires to write a program and a report on results etc.
So the user will create a new coursework by selecting the "code" and "report" options, since that's what is required. And then we need to create the respective tabs in the program so the user can input what is needed.
I have created all necessary forms and windows, It's just I'm not sure how to move on forward.
a) where should I put my code? should I have it on the "create" event?
b) how do I do this whole custom population thing?
Obviously, I'm not asking for the entire thing in code. I'm not even sure what to read and what to search for.
Following are some screenshots of the ui to help explain what I mean.
New project window
How the main window should be after creating a new projet. Notice the various tabs.
A form for report feedback
On your "Create" button click check for the checkbox.isSelected() and use the method below as:
if(reportCheckbox.isSelected()){
addonScreen(new reportFrame(),"Report Submission");
addonScreen(new reportFeedbackFrame(),"Report Feedback");
}
Use a desktop pane as a container...add your tabbed pane to it
public static JTabbedPane tabbedPane = new JTabbedPane();
jDesktopPane1.add(tabbedPane);
Use this method to add tabs to the layout at runtime
public static void addOnScreen(JInternalFrame inFrame, String title) {
//border for the internal frame
javax.swing.plaf.InternalFrameUI ifu = inFrame.getUI();
((javax.swing.plaf.basic.BasicInternalFrameUI) ifu).setNorthPane(null);
Border b1 = new LineBorder(new Color(114, 139, 173), 3, true) {
};
tabbedPane.setBounds(0, 0, jDesktopPane1.getWidth(), jDesktopPane1.getHeight());
inFrame.setLocation(0, 0);
inFrame.setSize(jDesktopPane1.getWidth(), jDesktopPane1.getHeight());
inFrame.setBorder(b1);
JPanel jp = new JPanel();
jp.setLayout(new GridLayout());
jp.setOpaque(true);
jp.add(inFrame);
tabbedPane.addTab(title, jp);
tabbedPane.setSelectedComponent(jp);
inFrame.requestFocusInWindow();
inFrame.setVisible(true);
tabbedPane.setVisible(true);
}
so I'm trying to make a battleship game, and I implemented a 10x10 grid containing gifs of some pixelated water. Now, what I'm trying to do is offset the grid one cell down and to the right so I can place the numbers and letters along the side and top like in a real battleship game. The problem is that when I try to offset it, it removes either the entire right side column of cells and reduces the window accordingly, and visa versa with the bottom. Here's my code:
EDIT 3: I have replaced the gif so that it can be used by everyone, simply copy the code and run it.
public class ButtonGrid {
JFrame frame=new JFrame(); //creates frame
JLabel[][] grid; //names the grid of buttons
public ButtonGrid(int width, int length) throws MalformedURLException{
URL urlPic = new URL("http://i47.tinypic.com/14wswi9.gif");
ImageIcon urlPicture = new ImageIcon(urlPic);
frame.setLayout(new GridLayout(width,length)); //set layout
grid=new JLabel[width][length]; //allocate the size of grid
for(int y=0; y<length; y++){
for(int x=0; x<width; x++){
grid[x][y]= new JLabel(urlPicture); //creates new button
frame.add(grid[x][y]); //adds button to grid
}
}
grid[1][1].setForeground(Color.red);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(270, 400);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static void main(String[] args) throws MalformedURLException{
new ButtonGrid(11,11);//makes new ButtonGrid with 2 parameters
}
}
EDIT: It seems that I may not have made this really clear. On a real battleship game, there is a row of numbers and a column of letters. The rest of the grid is simply water with the ships inside of it. With the code I have provided, the entire grid is water, and I want to offset to place a row of numbers and a column of letters just like in a real battleship board. If I try to place anything on top of the current grid, it doesn't change anything. I tried to change the foreground color and even changed the picture of one of the cells to something different, and the grid still remained the same; a 11 x 11 grid of animated pixel water.
Second EDIT: I have rewritten my code to draw a grid on top and on the left of the window, but now I am getting a null pointer exception. I don't exactly know what is wrong with this:
EDIT FOUR: Removed un-needed code.
One way to get what you need is to use the same technique I used in the Chess GUI with the columns (A-H) and rows (8-1) as seen below. Have a look over the code and see if you can implement that in your own code.
Failing that, post an MCVE (Minimal Complete and Verifiable Example) of your own (as opposed to uncompilable code snippets). One way to get image(s) for an example is to hot-link to the images seen in this answer (again as the linked code does).
Not sure I really understand the question, but I would think you should be using a GridLayout if you want to display components in a Grid.
//frame.setLayout(new FlowLayout());
frame.setLayout( new GridLayout(0, 11) );
Or maybe you would do something like this
JPanel topPanel = new JPanel( new GridLayout(1, 11) );
// use a loop to create 11 labels for the letters and add the labels to the panel
JPanel leftPanel = new JPanel( new GridLayout(10, 1) )
// use a loop to create 10 labels for the letters and and the labels to the panel
Use your current loop to create your "gamePanel" with the 10 x 10 grid of labels.
Then you add the 3 panels to the frame using:
frame.add(topPanel, BorderLayout.NORTH);
frame.add(leftPanel, BorderLayout.WEST);
frame.add(gamePanel, BorderLayout.CENTER);
I wanna fix a 2D board for a game. I've already fixed other panels for the Gui and everything goes well. But the panel for the board cant be printed on the window. I'm a bit confused about it as i think i've followed the same ideas as for the others panels i need.
Here's what i've done:
EDIT:
what I'm trying to do is fix a board panel for the game according to the dimensions of the it,hold every square in an array in order to use it after wherever it;s needed. I draw each little square of it with the method draw and put it back to the panel. So, each square on the board is a panel. This is the idea. But as u can see. There are troubles/errors on it.
EDIT: code updated.
just found a part of the problem. i thought first that i had set background to squared, but i didnt. with this one it appears on the panel a wide black "column". Unfortunately,still none squares. :(
One More EDIT:
Also,i realized that draw method is never called. when i put the draw method in the following method i can see the squares but they remain small. I redefine them with setSize but still no change.
How can I use paint method to edit the panels properly???? As it is now it can't. Even it can't return an object(eg panel) as it's polymorphic void!
/**
*Method used to construct the square in the area of the
*gui's grid. In this stage a GUISquare array is being constructed,
* used in the whole game as
*a mean of changing a square graphical state.
*#param squares is the squares array from whom the gui grid will be
*constructed.
*#see getSquare about the correspondance beetween a squareModel and
* a GUISquare.
*/
private void initBoardPanel(SquareModel[][] squares){
BoardPanel.setLayout(new GridLayout(height ,width )); //set layout
SquareRenderer[][] Squares;
JPanel[][] grid;
Squares=new GUISquare[height][width()];
grid=new JPanel[height()][width()];
for (int i=0; i<height(); i++){
for (int j=0; j<width() ; j++){
SquareRenderer kou=new SquareRenderer(i,j);
kou.setSquare(myGame.getSquares()[i][j]);
//NOTE: THE FOLLOWING DRAW METHOD CANT BE CALLED!!!?
if (myGame.getSquares()[i][j] instanceof SimpleSq ){
kou .paintPanel(i,j,"");}
else if (myGame.getSquares()[i][j] instanceof ActionSq )
{ kou .paintPanel(i,j);
}
//JUST BECAUSE DRAW CANT BE CALLED I PUT ITS CODE HERE:
//JUST TO CHECK:
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label1 = new JLabel("Move To "+myGame.getSquares()[i][j].getGoTo());
JLabel label2 = new JLabel(""+myGame.getSquares()[i][j].getSquare());
panel.setBackground(Color.ORANGE);
panel.add(label2, BorderLayout.NORTH);
panel.add(label1, BorderLayout.CENTER);
panel.setSize(250,250);
///////// <--until here ---paint method<---
kou.add(panel);
kou.setVisible(true);
kou.setBackground(Color.BLACK);
Squares[i][j]= kou;
BoardPanel.add(kou);
BoardPanel.setVisible(true);
BoardPanel.setBackground(Color.WHITE);
}
}
this.add(BoardPanel,BorderLayout.WEST);
// this.pack(); //sets appropriate size for frame
this.setVisible(true); //makes frame visible
}
IMPLEMENTED BY SQUARERENDERER:
/**
* Transformer for Snake/Ladder
* <br>This method is used to display a square on the screen.
*/
public void paintPanel(int i,int j) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label1 = new JLabel("Move To"+myGame.getSquares()[i][j].getGoTo());
JLabel label2 = new JLabel(""+myGame.getSquares()[i][j].getSquare());
JSeparator CellSeparator = new JSeparator(orientation);
panel.add(CellSeparator);
panel.setForeground(Color.ORANGE);
panel.add(label2, BorderLayout.NORTH);
panel.add(label1, BorderLayout.CENTER);
}
I see a couple things that are problematic:
When using a layout manager, you should avoid calling setSize. Most layout managers will simply override it. You should use setPreferredSize, setMinimumSize, and setMaximumSize instead, which provide hints to the layout manager.
It doesn't look like the draw method of SquareRenderer ever adds the panel you create to anything. You should either add panel to the SquareRenderer in the last line of draw or (better) add the sub-components directly to the SquareRenderer instead.
how to add and remove components(JButons , JTextField etc) at runtime in a Swing program (Java ) , without using NetBeans ? which Layout should I use ?
I want the user to enter Username & Password and , when he clicks on Submit button , the new screen with new components(JButtons , JTextField etc) should appear , I am unable to achieve the transition at runtime.
You want to use two different panels to achieve this result. It's not a good idea to use the same panel and remove all of the first components and add all of the second ones.
Make a LoginPanel class which lays out the username and password fields, labels, and submit button. Then, when the submit button is pressed, after the login is authenticated, hide the login panel and display a new panel with the layout you want for the next screen.
This sort of approach makes it much easier to maintain the two panels, and clearly separates their layouts and functionality from each other.
You can center this new frame over the existing panel using this code:
public static void centerFrameOverComponent(JFrame frame, JComponent component) {
Window parent = SwingUtilities.getWindowAncestor(component);
Rectangle frameRect = frame.getBounds();
Rectangle parentRect = parent.getBounds();
int x = (int) (parentRect.getCenterX() - frameRect.getWidth() / 2);
int y = (int) (parentRect.getCenterY() - frameRect.getHeight() / 2);
frame.setLocation(x, y);
}
Another approach is to call setVisible(false) on the specific component when you wish to hide it.
In cases where I have wanted to add/remove an entire sub panel, I have used the following:
panel.remove(subPanel);
panel.revalidate();
panel.repaint();
You want to call the last two methods whenever you add/remove components.
One approach would be to use CardLayout. Your login button handler would check the credentials and use show() to reveal the second pane.
Addendum: For security, consider using JPasswordField for the password; for convenience, consdier setLocationRelativeTo() for positioning the frame.
you could create a new class for exsample MyFrame thath extends JFrame, that rapresetns your new windows, in the constructor of that class you have to add at the contentpanel your all contolr....
in this way you can add a jbutton to your JFrame.
class MyFrame extends JFrame{
private JButton jb= new JButton("hello");
public MyFrame(){
setSize(new Dimension(300,180)); //set the MyFrame size
getContentPane().add(jb); //add your Component at ContentPane
}
}
after the login you could show your new frame in this way:
new MyFrame().setVisible(true);