Building a game GUI in java - java

I'm in the process of building a GUI in java for a virtual pet game I'm working on, my main problem thus far is establishing the best way to get the result I want.
Basically I have a basic setup like this
JFrame (MainFrame)
Jpanel (MainPanel) This panel sits on the Jframe
I then add further panels to the main panel
menuPanel and gamePanel - I switch between panels using cardLayout
MenuPanel provides a basic menu to launch a game / load / help / exit (this is running fine).
GamePanel is where I'm running into issues.
I'm wanting to provide a screen to allow the player to input data (petName, Type etc) I was thinking of doing this as a panel and then switching to the gamePanel where the actual game will be played, but I don't know if this is the best way as I also want them to be able to check if the details are correct, if not allow them to reenter them.
The other problem I have is I want a setup like this
Area for pet (background, pet animations)
below this buttons which remain static.
vvvvvvvvvvvvvvvvvvvvv
v v
v v
v Pet Area v
vvvvvvvvvvvvvvvvvvvvv
v v
v buttons v
vvvvvvvvvvvvvvvvvvvvv
Ive tried to add two panels onto gamePanel - graphicPanel and buttonPanel, but netbeans has issues with panel hierarchy.
If someone has done a project similar and can give me some pointers to coding this better would be appreciated. It will work this way, but it seems messy and inefficient.

The other problem I have is I want a setup like this
I would do something like this:
public class gamePanel extends JPanel{
private ButtonsPanel buttonsPanel;
private GraphicsPanel graphicsPanel;
public gamePanel(){
super();
this._initGUI();
}
private void _initGUI(){
this.buttonsPanel = new ButtonsPanel();
this.graphicsPanel = new GraphicsPanel();
this.setLayout(new BorderLayout());
this.add(buttonsPanel, BorderLayout.SOUTH);
this.add(graphicsPanel, BorderLayout.CENTER);
}
public void run(){
graphicsPanel.run();
}
}
public class GraphicsPanel extends JPanel(){
public void run(){
// this method could be called from the game loop.
// ....
// ....
this.repaint();
}
#Override
public void paint(Graphics g){
// here paint all graphics
}
}
public class ButtonsPanel extends JPanel{
public ButtonsPanel(){
super();
this._initGUI();
}
private void _initGUI(){
// here add all the buttons you want..
}
}
I don't know if it is the best way, but it works fine

I'm wanting to provide a screen to allow the player to input data (petName, Type etc)
That would probably be a model JDialog, instead of a panel on your main frame. Then you can redisplay the dialog and change the data as required.
The other problem I have is I want a setup like this...
Seems like a BorderLayout with one panel in the "CENTER" and the other in the "PAGE_END".

Related

Java KeyBindings not reacting on JPanel

I have previously used Java's KeyListener, but as my programs are demanding more I have gotten the recommendation to switch over to KeyBinds.
First of all I have tried to add keybindings to JFrame which didn't work ( I don't understand what JComponent I need to use. ). Therefore I tried moving the program over to a JPanel and then adding it to a JFrame, however the Key bind do not react when the desired button is pressed (in this case it's the "1" button);
In the method call I have set the action to be Print "Hi". Here is the code:
public class Panel extends javax.swing.JPanel {
JPanel Panel = new JPanel();
/**
* Creates new form Panel
*/
public Panel() {
addKeyBinding(Panel, KeyEvent.VK_1, "1Button", (evt)->{
System.out.println("Hi");
});
initComponents();
}
.....
And here is the method
.....
public static void addKeyBinding(JComponent comp, int keyCode, String id, ActionListener actionListener){
InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap ap = comp.getActionMap();
im.put(KeyStroke.getKeyStroke(keyCode, 0, false),
id);
ap.put(id, new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
actionListener.actionPerformed(e);
}
});
}
What am I doing wrong? Thanks!
The key bindings are for your form panel, right? I think you're misunderstanding a few concepts about classes and objects. Also it's hard to help without seeing the full code. But your error is very likely caused by this line:
addKeyBinding(Panel, KeyEvent.VK_1, "1Button", ...
which should be:
addKeyBinding(this, KeyEvent.VK_1, "1Button", ...
The variable Panel should be replaced with the keyword this thus referencing the actual form panel.
It also should be created wherever you're creating your window so this line can also be removed:
JPanel Panel = new JPanel();
There are many things wrong with your code. I can't imagine the code in the first snippet even compiles. You are trying to name a variable the same as your classname.
Your class has no reason to extend JPanel since it isn't a new type of JPanel. Simply remove your extends. Then change the first line to:
JPanel panel = new JPanel();
Then pass lower-case panel to the addKeyBinding method.
If for some strange reason you want to keep your class extending JPanel then pass this as the first parameter to addKeyBinding as /u/tiiv said and remove the JPanel Panel = new JPanel line since that isn't needed (as you have it written now your class is the JPanel).
As far as which component to use JFrame is a top-level container so that is usually your main application window. And then you put JPanel and other components in the JFrame. There are actually 4 top-level containers in swing (JFrame, JWindow, JDialog, and JApplet) but JFrame is generally the one you will use as your main app window.
I hope that helps.

Java, swing opening new JFrame from another class

I have this piece of code:
public class GUI extends JFrame {
private PlaneUI planeui;
public GUI(PlaneUI planeui) {
this.planeui = planeui;
}
//We have put the code that creates the GUI inside a method
public GUI() {
start();
planeui.display();
} ...
This is just a test and I need the method "planeui.display" to work when the program starts, together with the method "start();" which already works.
public final class PlaneUI extends JFrame {
public void display() {
//Creates a new JPanel object
JPanel panelStart = new JPanel();
getContentPane().add(panelStart);
//Changing the default layout from Flowlayout to absolute
panelStart.setLayout(null);
setTitle("Reservationer"); //Sets the window title
setSize(236, 256); //Sets the default size of the window
setLocationRelativeTo(null); //Start location of the window (centered)
setDefaultCloseOperation(EXIT_ON_CLOSE); //Exits the window
}
}
I have imported the needed libraries and I feel like the problem lies in an object that isn't created correctly since I get a nullpointerexception. I tried running this planeUI class in the main method and it worked correctly. I just can't get it to work this way..
In function PlaneUI.display() add one last line setVisible(true) because your adding everything but not displaying anything
you have to add this into your display() method:
setVisible(true);
Otherwise, all you are doing is setting all the aspects of the JFrame and adding the JPanel to it. You have to make it visible afterwards.

Cannot use JFrame method from mouselistener

I am currently trying developing simple game, but having some trouble with making game menu. I use JPanel for each states in game menu such as instruction or option and have method in parent JFrame to shuffle them according to what item user click on the menu.
My code is like this (without some simple method like setSize() or setVisible() ).
public class Game extends JFrame{
private JPanel mainPanel = new MainPanel();
private JPanel helpPanel; = new HelpPanel();
private JPanel optionPanel = new OptionPanel();
private JPanel currentPanel = new JPanel();
public Game(){
add(currentPanel);
}
public void changePanel(int destination){
remove(currentPanel);
if(destination==MAIN_PANEL)
currentPanel = mainPanel;
else if(destination==HELP_PANEL)
currentPanel = helpPanel;
else if(destination==OPTION_PANEL)
currentPanel = optionPanel;
add(currentPanel);
}
Everything work perfectly except when I try to use changePanel method in mouselistener, it wasn't responded anything. Then I try some simple method like this.
....
public void mouseClicked(MouseEvent e) {
removeAll();
JOptionPane.showConfirmDialog(null, "Pop when click anywhere.");
}
....
I expected my JFrame would be cleared and the dialog poped. The dialog does pop but for JFrame. My question is how can I use those simple method from mouselistener.
Sorry for my terrible English. I am now learning both Java and English.
Don't use a MouseListener.
I can't tell exactly what you are doing but you should probably be using either a JMenuBar with menus or JButtons. In any case I suggest you start by reading the Swing tutorial to learn the basics of Swing. There are sections on:
How to Use Menus
How to Use Buttons
to get your started.
Also you should check out the section on Using a Card Layout. This is generally the better approach when you want to remove/add panels from a frame.

How to add external JPanel in JFrame?

I'm working on large scale program. As you can see I have one main JFrame and about 20 menu items on that. Each menu item must pop up a new window. At the beginning I have created a JLayeredPanel and then I assigned each menu item to one JPanel which is inside JFrame.Then I put 25 panel in JLayeredPanel... Default all the panels are set to invisible like:
panel1.setVisible(false);
panel2.setVisible(false);
so on
When user click on one menu item, its JPanel will be visible and rest are invisible. It looks messy and I have 5000 lines code. I used InternalFrame and TabbedPane but I'm not happy with them. I want to split my code in different JPanel classes and assign them to the main JFrame. I mean when user clicked on each menu item it will call the external JPanel and render it on the JPanel on the main JFrame. I am using design mode in netbeans and it does everything for me but the simpled structure is like this and it is not working:
public class NewJPanel extends JPanel{
//I have added buttons and etc on this panel
......
}
public class frame extends JFrame(){
JPanel panel = new JPanel();
.....
Public frame(){
frame.add(panel);
}
......
//When use click on the any button on the panel
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//this is not working
NewJPanel fi = new NewJPanel ();
panel1.add(fi);
//or I tested this way separately but it did not work
panel1.remove();
panel1 = new NewJPanel();
add(panel);
invalidate();
}
}
please give me any suggestion how I can control this program in splited classes in professional way.
remove JPanel from JFrame.getContentPane.remove(myPanel)
add a new JPanel with constants, everyhing depends of used LayoutManager and its methods implemented in API
call JFrame.(re)validate() and JFrame.repaint() as last code lines, if everything is done, these notifiers correctly repaint available area
again to use CardLayout, there isn't signoficant performance or memory issue
Please give me any suggestion how I can control this program in splited classes in proressional way.
Ok.
You should put all of your JPanels in a JTabbedPane. The JTabbedPane would be added to the JFrame.
The JFrame, JTabbedPane, and each JPanel would be constructed in a separate class.
You use Swing components, rather than extending them. The only reason you extend a Swing component is if you override one of the component methods.
You should also create model classes for each of the JPanels, as well as a model class for the application.
Read this article to see how to put a Swing GUI together.
make's code better
public class NewJPanel extends JPanel{
//I have added buttons and etc on this panel
......
}
public class frame extends JFrame(){
JPanel panel = new JPanel();
.....
Public frame(){
//frame.add(panel); you dont need call frame because extends JFrame in frame class
add(panel);
......
//When use click on the any button on the panel
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//this is not working
NewJPanel fi = new NewJPanel();
add(fi);
//or I tested this way separately but it did not work
/*panel1.remove();
panel1 = new NewJPanel();
add(panel);
invalidate();you must define panel1 before use it,like :JPanel panel1 = new JPanel();*/
}
}

Using a single JFrame across multiple classes

I am working on a video game in Java that so far has a main menu class and a class for the game. As I have it set up right now, each class uses its own JFrame, which means that when the user clicks "start game", the main menu JFrame closes and the games JFrame opens. Obviously this is not ideal and I would like to have both classes use the same JFrame, however I really don't know how to go about this and internet searches have not been helpful.
The class for my main menu is:
public class Frame extends javax.swing.JFrame {
...
}
I have it set up right now so that my Game class imports my Frame class, but when I try to make the JFrame display elements from my game nothing comes up. So my question is:
How do I use one single JFrame across multiple classes?
Any help is much appreciated!
Rather then needing to pass a reference of the main frame to each of the child panels, which might expose parts of the program you don't want them to have access to (as an example), you should use something like a CardLayout and use the main frame as the main display hub, switching out the panels as you need to
Check out How to use CardLayout for more examples
Rather than having each class be its own frame, you can have one frame, with several classes manipulating it. I would probably set something up like this:
public class MainFrame extends JFrame {
public MainFrame() {
super("Cool Game!");
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
public class Game {
private final MainFrame mainFrame;
public Game(final MainFrame mainFrame) {
this.mainFrame = mainFrame;
mainFrame.setContentPane(createGamePanel());
}
private JPanel createGamePanel() {
//...
}
}
public class MainMenu {
private final MainFrame mainFrame;
public MainMenu(final MainFrame mainFrame) {
this.mainFrame = mainFrame;
}
public void showMainMenu() {
mainFrame.setContentPane(createMainMenuPanel());
}
private JPanel createMainMenuPanel() {
//...
}
}
You should use just one frame at overall game. And there should be many JPanels for different contents.
Deciding content and switching should be like this :
switch( currentState ) {
case introduction:
setContentPane(new IntroductionPanel());
break;
case insideGame:
setContentPane( new GamePanel() );
...
...
...
}
Use cardLayout to switch panels
http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html

Categories

Resources