I m trying to make a main menu with START button, CONTROLS button and HELP button.
I made a backboard for it but I need help with making options.
I tried to make it, but the error says that local variable gameFrame is accessed from within inner class; needs to be declared final
import java.util.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.System.*;
public class GameFrame {
public static void main(String[] args) {
JFrame gameFrame = new JFrame("PoopMan");
gameFrame.setSize(900, 800);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setResizable(false);
gameFrame.setVisible(true);
gameFrame.getContentPane().setBackground(Color.yellow);
JPanel panel = new JPanel();
JButton button1 = new JButton();
gameFrame.add(panel);
panel.add(button1);
gameFrame.setVisible(true);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(gameFrame.getComponent(0), "START");
}
});
}
}
I believe you would like to initialize your Game in a non-static context. Do the following.
public class Main {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GameFrame();
}
});
}
}
And
import java.util.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.System.*;
public class GameFrame extends JFrame {
private void init() {
this.setSize(900, 800);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setResizable(false);
this.setVisible(true);
this.getContentPane().setBackground(Color.yellow);
JPanel panel = new JPanel();
JButton button1 = new JButton("START");
this.add(panel);
panel.add(button1);
this.setLayout(new FlowLayout());
this.setMinimumSize(new Dimension(300, 300));
this.pack();
this.setVisible(true);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(getComponent(0), "START");
}
});
}
public GameFrame() {
super("PoopMan");
init();
}
}
This way, you start the GameFrame on another thread, and you can continue your work within the GameFrame class.
That is quite simple. Please note that this is a place to inquire about issues regarding your code, and not a place to look for answers.
What you should be researching is known as JMenuBar (refer to This Tutorial for Assitance)
Seeing as you are new, I will assist you this once. Below is the code that will accomplish what you ask. (Tried and Tested)
import java.util.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.System.*;
public class GameFrame
{
static private JMenuBar menuBar;
static private JMenu startMenu, controlsMenu, helpMenu;
static private JMenuItem startBtn;
static private JMenuItem controls;
static private JMenuItem hlpBtn;
public static void main(String[] args)
{
JFrame gameFrame = new JFrame("PoopMan");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.getContentPane().setBackground(Color.yellow);
menuBar = new JMenuBar();
startMenu = new JMenu("File");
controlsMenu = new JMenu("Controls");
helpMenu = new JMenu("Help");
startBtn = new JMenuItem("Start");
controls = new JMenuItem("Controls");
hlpBtn = new JMenuItem("Help");
gameFrame.add(menuBar, BorderLayout.PAGE_START);
menuBar.add(startMenu);
menuBar.add(controlsMenu);
menuBar.add(helpMenu);
startMenu.add(startBtn);
controlsMenu.add(controls);
helpMenu.add(hlpBtn);
gameFrame.pack();
gameFrame.setResizable(false);
gameFrame.setVisible(true);
gameFrame.setSize(900,800);
}
}
I am not certain as to why you are receiving a Final error. It works fine.
From later edits to the question:
JButton button1 = new JButton("Button");
JPanel panel = new JPanel();
panel.setBackground(Color.yellow);
gameFrame.add(panel);
panel.add(button1);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(gameFrame.getComponent(0), "START");
}
});
Related
I am attempting to add components to a JFrame but the only thing being displayed is my ImageIcon when I run GameMenu.java. I have instantiated setVisible(); specifically after I have set my frame or added components to the panels or menubars. So I'm unsure as to why no components are showing up. I think it may have something to do with my formatting or main method.
Here are my two classes:
GameMenu.java:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
public class GameMenu{
public static void main(String[] args) {
FrameCaller obj = new FrameCaller();
}
}
class FrameCaller extends JFrame {
public FrameCaller(){
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new JLabel(new ImageIcon("logo.png")));
pack();
setLocationRelativeTo(null);
JMenuBar mb = new JMenuBar();
JMenu m1 = new JMenu("Game List");
JMenu m2 = new JMenu("Help");
JMenu m3 = new JMenu("Stats");
mb.add(m1);
mb.add(m2);
mb.add(m3);
JMenuItem showRulesButton = new JMenuItem("View game rules");
m2.add(showRulesButton);
JMenuItem m77 = new JMenuItem("View past game stats");
m3.add(m77);
mb.setVisible(true);
JPanel panel = new JPanel();
JButton newGameButton = new JButton("New Game");
newGameButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new inGameFrame();
dispose();
}
});
panel.add(newGameButton);
panel.setVisible(true);
setVisible(true);
}
}
EightOff.java:
import javax.swing.*;
public class EightOff {
public static void main(String[] args)
{
inGameFrame obj = new inGameFrame();
}
}
class inGameFrame extends JFrame
{
public inGameFrame() {
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
}
Any tips would be wonderful. Thanks.
I'm working on a very complicated, multi-layered Swing GUI, and the main issue I'm running into right now involves having a JButton ActionListener perform setVisible() on a separate JFrame and immediately dispose() of the current JFrame. Because of the length of my code, it's important that main, both JFrames, and the ActionListener are all split into individual class files. I wrote a VERY simplified version of my problem, split into 4 tiny class files. Here they are:
File 1:
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame g1 = new GUI1();
g1.pack();
g1.setLocation(200,200);
g1.setVisible(true);
JFrame g2 = new GUI2();
g2.pack();
g2.setLocation(400,200);
g2.setVisible(false);
}
}
File 2:
import javax.swing.*;
public class GUI1 extends JFrame {
JPanel panel;
JButton button;
public GUI1() {
super("GUI1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
button = new JButton("Create GUI2");
button.addActionListener(new Listener());
add(panel);
add(button);
}
}
File 3:
import javax.swing.*;
public class GUI2 extends JFrame {
JPanel panel;
JLabel label;
public GUI2() {
super("GUI2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
label = new JLabel("I'm alive!");
add(panel);
add(label);
}
}
File 4:
import java.awt.event.*;
public class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
GUI2.setVisible(true);
GUI1.dispose();
}
}
As you can see, the only function of the ActionListener is to set GUI2 to visible and dispose of GUI1, but it runs the error "non-static method (setVisible(boolean) and dispose()) cannot be referenced from a static context". I figure this is because both methods are trying to reference objects that were created in main, which is static. My confusion is how to get around this, WITHOUT combining everything into one class.
Any suggestions? Thanks!
EDIT:
Here's the above code compiled into one file... although it returns the exact same error.
import javax.swing.*;
import java.awt.event.*;
public class Test {
public static void main(String[] args) {
JFrame g1 = new GUI1();
g1.pack();
g1.setLocation(200,200);
g1.setVisible(true);
JFrame g2 = new GUI2();
g2.pack();
g2.setLocation(400,200);
g2.setVisible(false);
}
}
class GUI1 extends JFrame {
JPanel panel;
JButton button;
public GUI1() {
super("GUI1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
button = new JButton("Create GUI2");
button.addActionListener(new Listener());
add(panel);
add(button);
}
}
class GUI2 extends JFrame {
JPanel panel;
JLabel label;
public GUI2() {
super("GUI2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
label = new JLabel("I'm alive!");
add(panel);
add(label);
}
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
GUI2.setVisible(true);
GUI1.dispose();
}
}
You have to pass instances of frame1 and frame2 to your ActionListener.
import java.awt.event.*;
public class Listener implements ActionListener {
private JFrame frame1, frame2;
public Listener(JFrame frame1, JFrame frame2) {
this.frame1 = frame1;
this.frame2 = frame2;
}
public void actionPerformed(ActionEvent e) {
frame2.setVisible(true);
frame1.dispose();
}
}
This means you have to pass an instance of frame2 to your GUI1 class.
import javax.swing.*;
public class GUI1 extends JFrame {
JPanel panel;
JButton button;
public GUI1(JFrame frame2) {
super("GUI1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
button = new JButton("Create GUI2");
button.addActionListener(new Listener(this, frame2));
add(panel);
add(button);
}
}
This means you have to create the frames in the reverse order.
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame g2 = new GUI2();
g2.pack();
g2.setLocation(400,200);
g2.setVisible(false);
JFrame g1 = new GUI1(g2);
g1.pack();
g1.setLocation(200,200);
g1.setVisible(true);
}
}
Basically, I'm trying to get the JButton in Frame1 to edit the JLabel in Frame2. I know it can work if I set the JLabel and getLabel() method in Frame2 to static, and have the ActionListener reference Frame1 directly, but I want to know if there's a way to do it without using static variables or methods.
Here's the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test {
public static void main(String[] args) {
Frame2 f2 = new Frame2();
f2.pack();
f2.setLocation(700, 400);
f2.setVisible(true);
Frame1 f1 = new Frame1(f2);
f1.pack();
f1.setLocation(400, 400);
f1.setVisible(true);
}
}
class Frame1 extends JFrame {
JButton button;
public Frame1(JFrame f) {
super("Frame 1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
button = new JButton("Button");
add(button);
button.addActionListener(new Listener(f.getLabel()));
}
}
class Frame2 extends JFrame {
JLabel label;
public Frame2() {
super("Frame 2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
label = new JLabel("hello");
add(label);
}
public JLabel getLabel() {
return label;
}
}
class Listener implements ActionListener {
private JLabel lab;
public Listener(JLabel lab) {
this.lab = lab;
}
public void actionPerformed(ActionEvent e) {
lab.setText("nice");
}
}
Any suggestions? Thanks!
EDIT: Here's a compilable version of the code -- label and getLabel() are static, and the ActionListener references JFrame1 directly when it's called. My goal is to have no static variables or methods (outside of main).
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test {
public static void main(String[] args) {
Frame2 f2 = new Frame2();
f2.pack();
f2.setLocation(700, 400);
f2.setVisible(true);
Frame1 f1 = new Frame1(f2);
f1.pack();
f1.setLocation(400, 400);
f1.setVisible(true);
}
}
class Frame1 extends JFrame {
JButton button;
public Frame1(JFrame f) {
super("Frame 1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
button = new JButton("Button");
add(button);
button.addActionListener(new Listener(Frame2.getLabel()));
}
}
class Frame2 extends JFrame {
static JLabel label;
public Frame2() {
super("Frame 2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
label = new JLabel("hello");
add(label);
}
public static JLabel getLabel() {
return label;
}
}
class Listener implements ActionListener {
private JLabel lab;
public Listener(JLabel lab) {
this.lab = lab;
}
public void actionPerformed(ActionEvent e) {
lab.setText("nice");
}
}
Oracle has a really nifty Swing tutorial. I think your studying the tutorial would be a really good idea.
I had to make a bunch of changes to your code to get it to execute.
The main change I made was to keep the reference to the JLabel in the Frame2 class. I passed an instance of Frame2 to the Listener class. Just like I did yesterday with your previous question.
Here's the code. Take the time to study what I did before you ask another question tomorrow.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DoubleJFrameTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Frame2 f2 = new Frame2();
f2.pack();
f2.setLocation(700, 400);
f2.setVisible(true);
Frame1 f1 = new Frame1(f2);
f1.pack();
f1.setLocation(400, 400);
f1.setVisible(true);
}
});
}
}
class Frame1 extends JFrame {
private static final long serialVersionUID = 1L;
private JButton button;
public Frame1(Frame2 f) {
super("Frame 1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
button = new JButton("Button");
button.addActionListener(new Listener(f));
panel.add(button, BorderLayout.CENTER);
add(panel);
}
}
class Frame2 extends JFrame {
private static final long serialVersionUID = 1L;
private JLabel label;
public Frame2() {
super("Frame 2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
label = new JLabel("hello");
panel.add(label, BorderLayout.CENTER);
add(panel);
}
public void setLabelText(String text) {
label.setText(text);;
}
}
class Listener implements ActionListener {
private Frame2 frame;
public Listener(Frame2 frame) {
this.frame = frame;
}
#Override
public void actionPerformed(ActionEvent e) {
frame.setLabelText("nice");
}
}
I want to keep my Controller panel as type JPanel as I will be incorporating into a tab later, I want to swap between Main and NextPage using buttons on those specific screens, I don't want to have consistent buttons on the bottom for both screens that switch between cards(i.e I don't want to have add & back to be appearing on both screens), I am trying to get the add button in Main to go to NextPage and back button in NextPage to go to Main. This is what I have so far:
For Controller:
import java.awt.CardLayout;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Controller extends JPanel {
private static Controller instance = new Controller();
JPanel cards;
Main mainPanel;
NextPage nextPage;
public Controller() {
setLayout(new BorderLayout());
setSize(810, 510);
cards = new JPanel(new CardLayout());
mainPanel = new Main();
nextPage = new NextPage();
cards.add(mainPanel, "Main");
cards.add(nextPage, "Next");
add(cards);
setVisible(true);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("MainPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Controller con = new Controller();
frame.getContentPane().add(con);
frame.setSize(800, 600);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public void changeCard(String card) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, card);
}
public static Controller getInstance() {
return instance;
}
}
For main:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class Main extends JPanel implements ActionListener {
private JButton search, add, delete;
private JTextField textField;
public Main() {
search = new JButton("Search");
add = new JButton("Add");
delete = new JButton("Delete");
textField = new JTextField(20);
add.addActionListener(this);
delete.addActionListener(this);
setLayout(new BorderLayout());
JPanel top = new JPanel();
top.add(search);
add(top, BorderLayout.NORTH);
JPanel bottom = new JPanel();
bottom.add(add);
bottom.add(delete);
add(bottom, BorderLayout.SOUTH);
setVisible(true);
setSize(400, 500);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == add) {
Controller.getInstance().changeCard("Next");
} else if (e.getSource() == delete) {
System.out.println("do something");
}
}
}
For NextPage:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class NextPage extends JPanel implements ActionListener {
private JButton back;
private JTextField textField;
public NextPage() {
back = new JButton("Back");
textField = new JTextField(20);
back.addActionListener(this);
setLayout(new BorderLayout());
add(back);
setVisible(true);
setSize(400, 500);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == back) {
Controller.getInstance().changeCard("Next");
}
}
}
Check out Card Layout Actions.
It is an extension of CardLayout that provides you with Previous/Next buttons that you can easily add to a panel separate from the CardLayout.
I've got a problem, I've got 5 Classes. 1 of them is the MainGUI, the other one is a JPanel with Buttons (but the buttons are not from the JPanels Class but from the 3rd, 4th and 5th class) and the 3 Button Classes.
I don't know if the structure is kinda dumb (correct me if I am wrong, it's just for experience).
So the biggest Problem here is that I can't use the ActionListeners for each Button. I'd like to change the text of a (J)Textfield from another class called JPanelTime.
The Code looks like this:
MainGUI.java
package view;
//Removed the javax.swing.*, etc imports because it's taking too much space
import listener.StartButton;
public class MainGUI{
private JFrame frame = new JFrame("Stoppuhr");
public static void main(String[] args) throws IOException{
MainGUI gui = new MainGUI();
gui.run();
}
public void run() throws IOException{
frame.setSize(400, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanelTime timePanel = new JPanelTime();
frame.add(timePanel.getGUI(), BorderLayout.NORTH);
JPanelButtons buttonPanel = new JPanelButtons();
frame.add(buttonPanel.getGUI(), BorderLayout.SOUTH);
JPanelPicture picturePanel = new JPanelPicture();
frame.add(picturePanel.getGUI(), BorderLayout.CENTER);
frame.setVisible(true);
}
}
JPanelButtons.java
package view;
//Same as above
import listener.MeantimeButton;
import listener.StartButton;
import listener.StopButton;
public class JPanelButtons extends JPanel{
private JPanel buttonPanel = new JPanel();
public JPanelButtons(){
StartButton startButton = new StartButton();
StopButton stopButton = new StopButton();
MeantimeButton meantimeButton = new MeantimeButton();
buttonPanel.setBorder(BorderFactory.createTitledBorder("Buttons"));
buttonPanel.setLayout(new GridLayout(1,3));
startButton.setText("Start");
meantimeButton.setText("Zwischenzeit");
stopButton.setText("Stopp");
buttonPanel.add(startButton);
buttonPanel.add(meantimeButton);
buttonPanel.add(stopButton);
}
public JComponent getGUI(){
return buttonPanel;
}
}
StartButton.java
package listener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JButton;
import view.MainGUI;
public class StartButton extends JButton implements ActionListener{
public StartButton() {
JButton startButton = new JButton();
startButton.addActionListener(this);
startButton.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
Date now = new Date();
SimpleDateFormat thisDate = new SimpleDateFormat("HH:mm:ss.SSS");
String getDate = thisDate.format(now);
}
}
Any help appreciated! Thanks in advance :)