Adding parameters to a GUI constructor stops GUI pop up - java

I've started learning Java with Eclipse, and I altered the main function to pass two strings to the similarly altered GUI constructor (there was nothing passed before).
The GUI doesn't pop up on the screen now, but can be accessed from the task bar at the bottom of the screen. I was just wondering why this happened? I've pasted the shortened code below.
I've tried it multiple times, and tried to find the problem with keywords on the web.
public class MainButton
{
public static void main(String[] args)
{
String A = "title"; String B = "Button";
Agui a = new Agui(A,B);
//BEFORE Agui a = new Agui();
}
}
import javax.swing.*;
public class Agui extends JFrame
{
//BEFORE public Agui()
public Agui(String A, String B)
{
setTitle(A);
setSize(400, 400);
// Create JButton and JPanel
JButton button = new JButton(B);
JPanel panel = new JPanel();
// Add button to JPanel
panel.add(button);
// And JPanel needs to be added to the JFrame itself!
this.getContentPane().add(panel);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
It'd be great to get the pop up without going to the task bar at the bottom of the screen, and to understand the logic of why this problem occurs.

Related

Why can´t I click on the JButtons?

Hey I am a beginner and I have wrote the following code in java, but I can´t click on the JButtons. The program includes three clases - Main, Frame and Actionhandler. My goal was to create a Frame with two buttons: Singleplayer and Mulitplayer. I wanted to test if they work, but I can´t click them. Can anyone help me please?
This is the Main class:
public class Main {
public static void main (String [] args) {
new Frame ();
}
}
This is the Frame class:
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Frame extends JFrame {
public static Object multi;
public static Object single;
Frame() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setLocationRelativeTo(null);
//Layout in Frame
this.setLayout(new GridLayout(2,1));
this.setVisible(true);
// Buttons in Main Menu
JButton single = new JButton("Singleplayer");
JButton multi = new JButton("Multiplayer");
// specify single button
single.setBounds(200,100,250,80);
single.setForeground(Color.GREEN);
single.setBackground(Color.LIGHT_GRAY);
single.setOpaque(true);
single.setBorder(BorderFactory.createLineBorder(Color.BLACK));
single.setFont(new Font("Comic Sans",Font.BOLD,25));
single.addActionListener(new ActionHandler());
//specify multi button
multi.setBounds(800,100,250,80);
multi.setForeground(Color.GREEN);
multi.setBackground(Color.GRAY);
multi.setOpaque(true);
multi.setFont(new Font("Comic Sans",Font.BOLD,25));
multi.setBorder(BorderFactory.createLineBorder(Color.BLACK));
multi.addActionListener(new ActionHandler());
// add Buttons to Frame
this.add(single);
this.add(multi);
}
}
This is the ActionHandler class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ActionHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == Frame.multi) {
System.out.println("You have clicked on Singleplayer");
if(e.getSource() == Frame.single) {
System.out.println("You have clicked on Multiplayer");
}
}};
}
You can click on the buttons fine. They just won't do anything because of how you've wired the program:
public class Frame extends JFrame {
public static Object multi; // this is null
public static Object single; // and so is this
Frame() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setLocationRelativeTo(null);
//Layout in Frame
this.setLayout(new GridLayout(2,1));
this.setVisible(true);
// Buttons in Main Menu
JButton single = new JButton("Singleplayer"); // this is a new *local* variable
JButton multi = new JButton("Multiplayer"); // and so is this:
You are initializing local variables that have the same name as your static class fields, and you're leaving the same static class fields null, a situation known as "variable shadowing", and so in your listeners, you check if the source is the null static field. Which won't work.
So in your listener:
public void actionPerformed(ActionEvent e) {
if(e.getSource() == Frame.multi) {
You're testing if a null variable is the button that was pressed, and this will not work.
One simple solution is to not re-declare the multi and single variables, to assign your JButtons to these public static fields by changing this:
JButton single = new JButton("Singleplayer");
JButton multi = new JButton("Multiplayer");
to this:
single = new JButton("Singleplayer");
multi = new JButton("Multiplayer");
This would sort-of work. You'd have do do some casting to add these JButton objects to the container since the variables are Object, not JButton. But this would be a bad idea because you'd be throwing out the OOPs baby with the bathwater, discarding encapsulation completely.
Best not to throw out OOPs rules with public static (non-constant) fields and instead work with them. Better to use constant Strings to be passed into your JButtons and then test for them using the ActionEvent's actionCommand property:
public class Frame extends JFrame {
public static String SINGLE_PLAYER = "Single Player";
public static String MULTI_PLAYER = "Multi Player";
Frame() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setLocationRelativeTo(null);
//Layout in Frame
this.setLayout(new GridLayout(2,1));
this.setVisible(true);
// Buttons in Main Menu
JButton single = new JButton(SINGLE_PLAYER); // this is a new *local* variable
JButton multi = new JButton(MULTI_PLAYER); // and so is this:
in the listener:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ActionHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals(Frame.MULTI_PLAYER)) {
System.out.println("You have clicked on Multi Player");
} else {
// ...
}
}};
}
Other problems with your code include:
Don't name your class Frame since this clashes with the name of class in the core Java library, java.awt.Frame. Name it something unique to avoid confusion
Avoid setting bounds, sizes and such. Let the GUI, its layout managers and component preferred sizes do the sizing by calling pack() on the top-level window (JFrame, JDialog,...) after adding components
Call .setVisible(true) on the top-level window after adding all components.
This looks like it will display as a sub-window or dialog window, and you might want to show this portion of the GUI in a modal JDialog, not in a JFrame.

Why JLabel is not visible at mine JFrame class?

I am trying to learn java,but I met some problems where finding answers is not so simply for me.
Task I wanna do seems to be quite simply.
I wanna add a label to Frame. MyFrame is a JFrame class with some basics modyfications like size, color etc.
Main code looks like this:
public class Main {
public static void main(String[] args)
{
// a GUI window to add components
MyFrame myFrame = new MyFrame();
ImageIcon image = new ImageIcon("Images/background.png");
//a GUI display area for a string of text,image or both
JLabel label = new JLabel("Why it is happening?",image,JLabel.CENTER);
myFrame.add(label);
//label.setText("Why it is happening?");// set text of label
//label.setIcon(image);
label.setHorizontalTextPosition(JLabel.CENTER);
}
}
And the result I get is this which I want:
correct result
When I comment last line about label it is changing appearance of mine UI. It is displaying only JFrame without my label at all.
Not working code:
public class Main {
public static void main(String[] args)
{
// a GUI window to add components
MyFrame myFrame = new MyFrame();
ImageIcon image = new ImageIcon("Images/background.png");
//a GUI display area for a string of text,image or both
JLabel label = new JLabel("Why it is happening?",image,JLabel.CENTER);
myFrame.add(label);
//label.setText("Why it is happening?");// set text of label
//label.setIcon(image);
//Commented
//label.setHorizontalTextPosition(JLabel.CENTER);
}
}
Here is graphic result:
not working label
Did I miss some basics information ?
I think both should work the same.
This is an interesting one. At first glance I agreed with #VGR. But then if it is all down to the order of painting etc. - then I would have expected a call to 'repaint()' or even 'invalidate()' to fix the problem. Doesn't seem like it... so perhaps this is a bug in swing.
import javax.swing.*;
public class Main
{
public static void main(String[] args)
{
// a GUI window to add components
JFrame myFrame = new JFrame();
ImageIcon image = new ImageIcon("Images/background.png");
myFrame.setSize(500,250);
myFrame.setVisible(true);
JLabel label = new JLabel("Why it is happening?", image, JLabel.CENTER);
myFrame.add(label);
//label.setHorizontalTextPosition(JLabel.CENTER);
label.repaint(); //Should have the same effect as the line above, but doesn't!
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

Change attribute in other jframe when a button is clicked in another JFrame

I have 2 jframes, 1 is kinda like the main menu, i want an attribute to change in the level jframe when a button is pressed so i tried:
SpeelVeld frame = new SpeelVeld();
frame.level = 1;
System.out.println(frame.level);
I used the sout to see what really happens because it wasnt working, but i see that the level goes from 0 to 1 back to 0 and goes on and on, does someone know why and how to fix?
SpeelVeld frame = new SpeelVeld();
frame.setBounds(0,0,519,591);
frame.setLocationRelativeTo(null);
frame.getContentPane().setBackground(Color.WHITE);
frame.setTitle("RWINA");
frame.setVisible(true);
frame.setLevel(1);
this is in the main method of my original GameProject file.
How can i make a jdialog
I have 2 jframes, 1 is kinda like the main menu,
You shouldn't use 2 JFrames for this. The dependent sub-window, likely your main menu window, should in fact be a JDialog, probably a non-modal dialog from the looks of it.
I want an attribute to change in the level jframe when a button is pressed so i tried:
SpeelVeld frame = new SpeelVeld();
frame.level = 1;
System.out.println(frame.level);
and here's a big problem. Understand that in this code, you're creating a new SpeelVeld object, the stress being on the word new. Changing the state of this object will have no effect on the other SeelVeld object that is currently being displayed. Do do that, your second window will need a valid reference to the displayed SeelVeld object. How to do this will depend all on code not yet shown, but often it can be done simply by passing in the displayed SpeelVeld object into the main menu object by use of a constructor parameter or setter method.
For example:
import java.awt.Dialog.ModalityType;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
// JPanel for our main GUI
public class SpeelVeldFoo {
private static void createAndShowGui() {
// JPanel used by the main JFrame
SpeelVeldPanel speelVeldPanel = new SpeelVeldPanel();
// JPanel used by the main menu JDialog. Pass the above into it
MainMenuPanel mainMenuPanel = new MainMenuPanel(speelVeldPanel);
// create your JFrame
JFrame frame = new JFrame("Speel Veld");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(speelVeldPanel); // add the JPanel
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
// create your non-modal JDialog
JDialog menuDialog = new JDialog(frame, "Main Menu", ModalityType.MODELESS);
menuDialog.add(mainMenuPanel); // add the JPanel that holds its "guts"
menuDialog.pack();
menuDialog.setLocationByPlatform(true);
menuDialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
#SuppressWarnings("serial")
class SpeelVeldPanel extends JPanel {
private int level = 1; // simple example just has a level int
private JLabel levelLabel = new JLabel("1"); // and displays it in a JLabel
public SpeelVeldPanel() {
add(new JLabel("Level:"));
add(levelLabel);
int ebGap = 50;
setBorder(BorderFactory.createEmptyBorder(ebGap, 2 * ebGap, ebGap, 2 * ebGap));
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
// whenever level is changed, update the display
this.level = level;
levelLabel.setText(String.valueOf(level));
}
}
// class for the JPanel held by the JDialog
#SuppressWarnings("serial")
class MainMenuPanel extends JPanel {
private JSpinner levelSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 5, 1));
private SpeelVeldPanel speelVeldPanel = null; // reference to the main GUI
// note the parameter.... you pass in the displayed main GUI so you can
// change it
public MainMenuPanel(final SpeelVeldPanel speelVeldPanel) {
this.speelVeldPanel = speelVeldPanel; // set the field
// respond when the spinner's data changes
levelSpinner.addChangeListener(new LevelListener());
add(new JLabel("Set the Speel Veld's level:"));
add(levelSpinner);
int ebGap = 10;
setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
}
private class LevelListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
// when the spinner's data changes
int level = (int) levelSpinner.getValue(); // get the data
speelVeldPanel.setLevel(level); // and send it to the main GUI
}
}
}
You'll note that I don't like extending JFrame or JDialog if I can avoid it. My feeling is that one can paint oneself into a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
You probably want the JFrame to be the top-level container, then have a JPanel that holds your menu. The menu could be whatever you want, I'm using a JTextArea. Then, you need a JButton for the JPanel or JFrame that when pressed, changes the text in the JTextArea. Here is an implementation that you could work from. I'm using the ActionEvent as the trigger for when to mess with the JTextArea:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class SimpleSwing {
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
JPanel mainMenuPanel = new JPanel();
JTextArea textAttribute = new JTextArea("Original Text");
JButton changeAttributeButton = new JButton("Change Attribute");
changeAttributeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
textAttribute.setText("Whatever new text you want");
}
});
mainMenuPanel.add(textAttribute);
mainMenuPanel.add(changeAttributeButton);
mainFrame.add(mainMenuPanel);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 500);
mainFrame.setVisible(true);
}
}

Where have I messed up regarding creating a Game Menu?

I am trying to create a basic game menu for a game right now. I am just testing out the menu for now, and most of the options I wrote are just to test out whether the menu actually works or not. So I have a Menu class and a OptionPanel class as well.
Here is the Menu Class:
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Main extends JFrame {
JPanel cardPanel;
public Main(String title) {
super(title);
setBounds(100, 100, 800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cardPanel = new JPanel();
CardLayout cl = new CardLayout();
cardPanel.setLayout(cl);
OptionPanel panel1 = new OptionPanel(this);
Board panel2 = new Board();
Rules panel3 = new Rules();
cardPanel.add(panel1,"1");
cardPanel.add(panel2,"2");
cardPanel.add(panel3,"3");
add(cardPanel);
setVisible(true);
}
public static void main(String[] args)
{
Main w = new Main("AP Animation Demo");
}
public void changePanel() {
((CardLayout)cardPanel.getLayout()).next(cardPanel);
requestFocus();
}
}
And here is my Option Panel class:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class OptionPanel extends JPanel implements ActionListener {
Main w;
public OptionPanel(Main w) {
this.w = w;
JButton button = new JButton("Press me!");
button.addActionListener(this);
add(button);
JButton button2 = new JButton("Game rules");
button2.addActionListener(this);
add(button2);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
setBackground(Color.BLACK);
}// Call JPanel's paintComponent method to paint the background
public void actionPerformed(ActionEvent e) {
w.changePanel();
}
}
How do I make it so when the menu pops up, I can click on one button that leads to the game, and when clicking on another button, get linked to another screen. I think it has something to do with the actionPerformed thing, so I tried adding if (e.getSource == button) and stuff like that, but it could not find any button variable. Any advice/feedback?
If you want the actionPerformed() method to be able to access a button variable, then the variable has to have an instance scope (or static, less preferable almost always). Referring to it in the method as you have it written won't work because the button variable is local to the constructor.
The suggestion in the comments is to make a separate ActionListener for each button; you only need to use the if (e.getSource() == button) if the one actionPerformed() method is getting called for multiple buttons. The difference between these is a little much for a SO answer; you can get a tutorial on action listeners in the Java tutorials at Oracle.
The way you have started above suggests you are going to use the OptionPanel as a single action listener for all buttons, and therefore it needs to test which button invoked it. If instead you have a separate action listener for each button, then it knows which button invoked it and doesn't need to test.
Try looking up "anonymous inner classes" as they relate to action listeners in Java.

How to create a text box that user can input a large amount of text into

I'm currently doing a Java assignment as a computer science fresher. As a part of that assignment I'm trying to bring up a secondary frame that the user can write UML code into which will then be passed into my main application and then into a class diagram.
The bit that I'm stuck with is that the JTextBox that I have put into this secondary frame is the size I want it to be, however the writing starts in the middle and does not change to a new line when it gets to the other size of the frame.
This is the image of what is currently happening:
Code
And this is the code that I currently have for this class if it's needed.
package classdesign;
import java.awt.*;
import javax.swing.*;
public class ClassCreation extends JFrame {
private JFrame frame;
private JLabel instructionlabel;
private JTextField inputUML;
private JButton upButton;
private String Message;
public void ClassCreation(){
frame = new JFrame();
frame.setSize(300, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Class Design");
JPanel CreationPanel = new JPanel();
CreationPanel.setLayout(new BorderLayout());
instructionlabel = new JLabel("Fill Class details in using UML");
CreationPanel.add(instructionlabel,BorderLayout.NORTH);
inputUML = new JTextField("",20);
CreationPanel.add(inputUML,BorderLayout.CENTER);
frame.add(CreationPanel);
}
public Frame getFrame() {
return frame;
}
}
So, to summarise what I was hoping somebody could tell me how to do is to get the text input from the user to start in the top left and change to the next line when it gets to the far right, like any normal text editor etc...
use JTextPane or JEditorPane. Sample can be found at
http://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html
JTextField is a lightweight component that allows the editing of a single line of text. (source)
As it is a single-line component, whatever its size is the cursor will always be centered and will never go to the next line.
I would suggest you use a JTextArea as it is a multi-line area and allow the user to enter input as you want him to.
An example of using a text area (with a few other tips thrown in free - check the comments).
import java.awt.*;
import javax.swing.*;
// Has an instance of frame, does not need to extend it.
public class ClassCreation { //extends JFrame {
private JFrame frame;
private JLabel instructionlabel;
// as mentioned by talnicolas
private JTextArea inputUML;
// Don't give a method the same name as a class!!
//public void ClassCreation(){
public void initGui(){
frame = new JFrame();
//frame.setSize(300, 400); //pack() instead!
//frame.setLocationRelativeTo(null); // do something better
frame.setLocationByPlatform(true); // better!
//frame.setVisible(true); // do later
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Class Design");
JPanel CreationPanel = new JPanel();
CreationPanel.setLayout(new BorderLayout());
instructionlabel = new JLabel("Fill Class details in using UML");
CreationPanel.add(instructionlabel,BorderLayout.NORTH);
inputUML = new JTextArea("",7,30);
// very important next 2 lines
inputUML.setLineWrap(true);
inputUML.setWrapStyleWord(true);
// add it to a scrollpane
CreationPanel.add(new JScrollPane(inputUML),BorderLayout.CENTER);
frame.add(CreationPanel);
frame.pack(); // assume the natural size!
frame.setVisible(true);
for (int ii=0; ii<150; ii++) {
inputUML.append(SENTENCE);
inputUML.setCaretPosition( inputUML.getText().length() );
}
}
public static void main(String[] args) {
// Swing GUIs should be created and altered on the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ClassCreation cc = new ClassCreation();
cc.initGui();
}
});
}
private static String SENTENCE = "The quick brown fox jumps over the lazy dog! ";
}

Categories

Resources