Making JButton in one class open seperate JDialog class - java

I am creating a quiz and have created a class with a JFrame which sort of acts like the main menu. On this menu, I have created a JButton which I want to open the seperate JDialog (which will contain the questions etc).
The JDialog is a seperate class called questionDialog.java
I believe you have to implement an action listener calling setVisible(true) however when I do that, I get a cannot make static reference to non-static method setvisible error.
Any help would be greatly appreciated, I am using eclipse and Jigloo for the GUI
here is my code in my main menu JFrame class, specifically the code for the button I want to open the new JDialog
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
NewJFrame inst = new NewJFrame();
inst.setLocationRelativeTo(null);
inst.setVisible(true);
}
});
}
startButton = new JButton();
getContentPane().add(startButton);
startButton.setText("Start Quiz");
startButton.setBounds(454, 239, 65, 23);
And here is the code which gives me the error
startButton = new JButton();
getContentPane().add(startButton);
startButton.setText("Start Quiz");
startButton.setBounds(454, 239, 65, 23);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionevent)
{
questionDialog.setVisible(true);
}
});
Here is the code from the seperate JDialog class
package ZillionaireGUI;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class questionDialog extends javax.swing.JDialog {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
questionDialog inst = new questionDialog(frame);
inst.setVisible(true);
}
});
}
public questionDialog(JFrame frame) {
super(frame);
initGUI();
}
private void initGUI() {
try {
setSize(400, 300);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Here's what you should do.
Get rid of the main method in the JDialog class. Your application should only have one main method, and that should be in your JFrame class.
Don't create a new JFrame to pass it to your dialog.
To open it on a button click just create a new questionDialog() passing the current frame to it. Something like this
public class MyFrame extends JFrame {
public MyFrame() {
JButton but = new JButton("but");
but.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
QuestionDialog dialog = new QuestionDialog(MyFrame.this);
dialog.setVisible(true);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new MyFrame();
}
});
}
}
public class QuestionDialog extends JDialog {
public QuestionDialog(Frame parent) {
super(parent);
}
}
Bonus
You are getting the error doing questionDialog.setVisible(true) because setVisible is an instance method and you are trying to call it in a static way. You need to create a new instance of your dialog class to call it.
Use Java naming convention. Class names begin with capital letters.questionDialog → QuestionDialog

In your main menu write the following
startButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
questionDialog inst = new questionDialog(frame);
inst.setVisible(true);
}
});
}
});

I think it is likely that you are trying to do something to a non-static member while you are in main (which is a static method). You should just use main to create an instance and then call some method of that instance. I've put some working code below:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Zillionaire extends JFrame implements ActionListener {
JButton startButton;
public static void main(String[] args) {
Zillionaire zillionaire = new Zillionaire();
zillionaire.init();
}
private void init() {
startButton = new JButton();
// Removed: we just use add now, and bets to do this last.
// getContentPane().add(startButton);
startButton.setText("Start Quiz");
startButton.setBounds(454, 239, 65, 23);
startButton.addActionListener(this);
// Add after the button is configured, not before
add(startButton);
// This just makes our JFrame pretty and visible
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
// Anything that implements the ActionListener interface can listen
// for the button being pressed and activate the JDialog
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Button pressed, but Dialog doesn't do much");
QuestionDialog questionDialog = new QuestionDialog(this);
}
}
class QuestionDialog extends javax.swing.JDialog {
public QuestionDialog(JFrame frame) {
super(frame);
initGUI();
}
// Set it visible when we make our GUI
private void initGUI() {
try {
setSize(400, 300);
// Added so we can see something
add(new JLabel("I should add something!"));
setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

ActionListener for JButton from another class not triggering

My main class with a static CardLayout JPanel which includes a JPanel from the Home class.
import java.awt.*;
import javax.swing.*;
public class Runner1 extends JPanel{
public Runner1() {
initComponents();
}
private void initComponents() {
setLayout(new CardLayout());
pnlHome = new Home();
pnlSignIn = new SignIn();
add(pnlHome, "Home");
add(pnlSignIn, "SignIn");
}
public static void showJPanel(String s) {
CardLayout cl = (CardLayout) (pnlRunner.getLayout());
cl.show(pnlRunner, s);
}
public static void createAndShowGUI(){
pnlRunner = new Runner1();
JFrame frame = new JFrame();
frame.setTitle("Delivery System");
frame.setSize(new Dimension(500, 400));
frame.getContentPane().add(pnlRunner);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static Runner1 pnlRunner;
private JPanel pnlHome;
private JPanel pnlSignIn;
}
My other class where the actionlistener for the JButton doesn't get triggered, when debugging, the btnNewOrderActionPerformed doesn't get executed.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Home extends JPanel {
public Home() {
initComponents();
}
private void initComponents(){
setLayout(new BorderLayout());
add(new TextArea("Active Orders"),BorderLayout.CENTER);
JButton btnNewOrder1 = new JButton("New Order");
btnNewOrder1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
btnNewOrderActionPerformed(e);
}
});
add(btnNewOrder1, BorderLayout.PAGE_END);
}
private void btnNewOrderActionPerformed(ActionEvent e){
System.out.println("test");
}
private OrderMap[] JOrders; //Lists of JPanel of orders
private JButton btnNewOrder;
}
Another question regarding static implementation of the CardLayout JPanel, is there a non-static way of accomplishing the same thing (where the shown JPanel can be controlled by components from external classes)?
My other class where the actionlistener for the JButton doesn't get triggered
Works fine for me, after fixing up the code so it compiles. See comment of your initial question.
is there a non-static way of accomplishing the same thing (where the shown JPanel can be controlled by components from external classes)?
First, get rid of the static keyword on the method.
Then you have a couple of options:
pass a reference of the Runner1 class to each child panel.
in the child panel you can use the getParent() method to get a reference to the Runner1 class.
Once you have a reference you can then reference any method in the Runner1 class.

Swing : Exit application actionListener

I am trying to figure out how can we exit the application with button click.
The problem i faced which makes me unable to exit the application is because i am using "extend JFRame" from the main class.
For an example,
app.class
public class app{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
JFrame frame = new MainFrame("Exercise one");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
.. .. ..
frame.setVisible(true);
})
}
}
MainFrame.java
public class MainFrame extends JFrame(){
public MainFrame(String title){
super(title)
//set layout manager
setLayout(new BorderLayout());
//swing components
JButton exit = new JButton("Exit");
//add container
Container container = getContentPane();
container.add(exit);
//create actionlist logic
exit.addActionListener(new ActionListener()){
#Override
public void actionPerformed(ActionEvent arg0){
// on click , this logic will end the application
}
}
}
}
I fully understand how i can cancel the application from app class.But in scenarios where i want to cancel the application from MainFrame.Can it be done ?
Thank you in advance.
The defaultCloseOperation is only processed by the frame when it encounters a WINDOW_CLOSING event, neither setVisible or dispose trigger this event, which means the the defaultCloseOperation won't be processed
The only way to ensure that this operation is triggered is to manually dispatch a WINDOW_CLOSING event
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
One of the main reasons for wanting to follow this path is that it ensures the application is following the configured defaultCloseOperation and making up it's own mind (like calling System.exit manually)
The following demonstrates hiding, disposing and dispatching approaches. Only the dispatch approach will close the window and terminate the JVM
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import static javax.swing.Action.NAME;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
frame.add(new JButton(new HideAction(frame)), gbc);
frame.add(new JButton(new DisposeAction(frame)), gbc);
frame.add(new JButton(new DispatchAction(frame)), gbc);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.out.println("Closing");
}
#Override
public void windowClosed(WindowEvent e) {
System.out.println("Closed");
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class HideAction extends AbstractAction {
private JFrame frame;
public HideAction(JFrame frame) {
this.frame = frame;
putValue(NAME, "Hide");
}
#Override
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
}
}
public class DisposeAction extends AbstractAction {
private JFrame frame;
public DisposeAction(JFrame frame) {
this.frame = frame;
putValue(NAME, "Dispose");
}
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
}
public class DispatchAction extends AbstractAction {
private JFrame frame;
public DispatchAction(JFrame frame) {
this.frame = frame;
putValue(NAME, "Dispatch");
}
#Override
public void actionPerformed(ActionEvent e) {
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
}
}
If I run this in my IDE, unless I use the dispatch option, the JVM is left running and I have to terminate the session to close it fully.
I also noted that calling dispose only triggers the WINDOW_CLOSED event, while the dispatch method will trigger the WINDOW_CLOSING event
Problem solved.
Credits to #XtremeBaumer.
Basically, when using "classname" extend JFRame.
We can input dispose() which will kill the application completely. This will causes the JFrame window to be destroyed and cleaned up by the operating system. :)
Indeed, dispose() is the right solution. I also suggest to add a pack() call so the UI shows up properly:
public class MainFrame extends JFrame {
public MainFrame(String title) {
super(title);
...
// create actionlist logic
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("--> closing app programmatically");
MainFrame.this.dispose();
}
});
this.pack();
}
}
You can test the events with a WindowListener on the MainFrame. They are invoked as if the user pressed the close button:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new MainFrame("Exercise one");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
// .. .. ..
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("--> closing...");
}
public void windowClosed(WindowEvent e) {
System.out.println("--> closed...");
}
});
}
});
}

Cannot create a new JPanel

I am making Pong in Java, and I have already implemented the main game, but I also want to have a menu screen pop up at the beginning. I created the menu screen, but I can't figure out how to start the game when I press the "start game" button. I have a class that contains my main method:
public class main {
public static void main(String[]args)
{
PongRunner runner = new PongRunner();
runner.menuScreen();
//System.out.println(""+display.getHeight()+" "+display.getWidth());
}
}
And I also have a class for running the menu and main game:
import javax.swing.JFrame;
public class PongRunner extends JFrame{
JFrame frame = new JFrame("MLG Pong");
public PongRunner()
{
}
public void menuScreen()
{
Menu menu = new Menu();
frame.add(menu);
frame.setSize(1280,720);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
}
public void startGame()
{
frame.removeAll();
game game = new game();
frame.add(game);
}
}
I'm trying to make it so when I press the button to start the game, I will call the startGame() method and clear, or "delete", the menu JPanel inside my JFrame and replace it with the JPanel from my game class. Here is the actionListener from the menu class:
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("startgame")){
redraw = false;
//System.out.println("test");
PongRunner runner = new PongRunner();
runner.startGame();
}
}
Any ideas on how to do this?
Don't create a new PongRunner in your action listener. Use the initially created instance.
Also, don't use add with your JFrame use the method setContentPane to set the main content of the frame. So you need PongRunner and Menu to be subclasses of Container which every swing JComponent is).
So the code should be like :
public class main {
public static void main(String[]args) {
PongRunner runner = new PongRunner();
runner.menuScreen();
}
}
public class game extends ... { // should extends at least Container
}
public class Menu extends JPanel implements ActionListener {
private PongRunner theRunner;
public Menu(PongRunner p) {
theRunner = p;
JButton b = new JButton("Start");
b.setActionCommand("startgame");
this.add(b);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("startgame")) {
theRunner.startGame();
}
}
}
public class PongRunner extends JFrame {
JFrame frame = new JFrame("MLG Pong");
public void menuScreen() {
Menu menu = new Menu(this);
frame.setContentPane(menu);
frame.setSize(1280,720); // don't use such a thing, set the preferred size of the contentPane to a desired value
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
}
public void startGame() {
frame.setContentPane(new game());
frame.pack();
}
}

Implementing a way to change a JLabel from another class in my game Part 3?

I am currently having trouble with being able to change the choiceDeclaration JLabel. My mindset behind the choiceDeclaration JLabel is to simply display text based on which JButton is clicked.
Here is my current code for the project:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.*;
public class prompt {
public static void main(String []args) {
/* Setting up the JPanel and its necessities for this program */
JFrame choicePrompt = new JFrame("Rock, Paper, Scissors Game");
JPanel choicePanel = new JPanel();
JButton rockButton = new JButton("ROCK");
JButton scissorsButton = new JButton("SCISSORS");
JButton paperButton = new JButton("PAPER");
JLabel choiceDeclaration = new JLabel();
choicePrompt.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
choicePrompt.setResizable(false);
choicePrompt.setSize(300, 300);
choicePrompt.setVisible(true);
choiceDeclaration.setVisible(true);
choicePrompt.add(choicePanel);
choicePanel.add(choiceDeclaration);
choicePanel.add(rockButton);
choicePanel.add(scissorsButton);
choicePanel.add(paperButton);
choiceDeclaration.setVerticalTextPosition(JLabel.TOP);
choiceDeclaration.setHorizontalTextPosition(JLabel.CENTER);
/* ActionListeners for the JButtons */
rockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*I have not placed any code in here because I have not gotten that far*/
}
});
scissorsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*I have not placed any code in here because I have not gotten that far*/
}
});
paperButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*I have not placed any code in here because I have not gotten that far*/
}
});
}
}
I cannot use a setText method in my ActionListeners as shown below because it conflicts with my main class method a line below the declaration of my class. They are both using String in their parameters.
public static void main(String []args) {
rockButton.addActionListener(new ActionListener() {
setText(String text) {
}
}
}
My concluding thought was to make another class that could use the setText method to change the JLabel on that frame. However, since JLabels cannot be called from one class to another like variables or methods, I am having trouble trying to implement this idea.
Have a separate method for it...
public static void settext() {
setText(String text)
}
then call it in your action listener...
rockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
settext();
}
});
I hope this is what you meant! :)

Swing JButton event

I have JButton and want on event call this class method show() when this button in pressed. I know how to this, if I want use method from another class, but I need call method from same class as button.
JButton search = new JButton(new ButtonAction("Search", KeyEvent.VK_A));
I try add
JButton search = new JButton(show());
But it works only 1 time when object creating, but not when button is pressed.
Not sure what you want here... but if you want to attach an actionListener() to a JButton, you can do the following. Why do you need to listen to A?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerExample1 extends JFrame
implements ActionListener, KeyListener {
private static final long serialVersionUID = 1L;
private JTextField searchText;
private JButton searchButton1;
private JButton searchButton2;
public ActionListenerExample1() {
initialize();
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
protected void initialize() {
searchText = new JTextField(30);
searchButton1 = new JButton("Search 1");
searchButton2 = new JButton("Search 2");
searchText.addKeyListener(this);
searchButton1.addActionListener(this);
searchButton2.addActionListener(new ButtonAction());
this.setLayout(new FlowLayout());
this.add(searchText);
this.add(searchButton1);
this.add(searchButton2);
}
public static void main(String[] args) {
new ActionListenerExample1();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == searchButton1) {
buttonAction("GLOBAL LISTENER");
}
}
private class ButtonAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
buttonAction("LOCAL LISTENER");
}
}
private void buttonAction(String label) {
JOptionPane.showMessageDialog(this,
String.format("%s: %s", label, searchText.getText()));
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_A) {
buttonAction("KEYBOARD");
}
}
#Override
public void keyReleased(KeyEvent e) { }
#Override
public void keyTyped(KeyEvent e) { }
}
If I understand you correctly, you want to call a method from the class that you created the button in rather than a method from another class.
First off, notice that while you are technically calling a method here
JButton search = new JButton(new ButtonAction("Search", KeyEvent.VK_A));
what is really going on is that you are passing a ButtonAction object to the JButton constructor. The closest thing that I can think of that will get what you want is having the class you are using extend ButtonAction.

Categories

Resources