i have a class (Class ButtonX) that contains a button
when user clicks the button, it will create instance of the class DialogX
when I create instance of the class DialogX it will show up JDialog
public class ButtonX {
public ButtonX() {
JFrame me = new JFrame();
JButton n = new JButton("show dialog");
n.addActionListener(ListenerX.listen);
me.getContentPane().add(n);
me.pack();
me.setVisible(true);
}
public static void main (String[]args){
new ButtonX();
}
}
listener of that JButton
public class ListenerX {
public static ActionListener listen = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
DialogX dialogx = null;
dialogx = new DialogX();
}};
}
class that contains JDialog
public class DialogX {
static JDialog g = new JDialog();
public DialogX() {
JLabel label = new JLabel("label");
g.getContentPane().setLayout(new FlowLayout());
g.getContentPane().add(label);
g.pack();
g.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
g.setVisible(true);
}
}
what I try to achieve is, that when user clicks the button, it will destroy instance of class DialogX ( if it exist ) and then create again instance of DialogX
What to do?
thanks..
forgive my english..
You cannot explicitly destroy objects in Java. Once there are no more references (think of pointers) to an Object left, it will be marked as eligible for being garbage collected. Your code therefore is almost fine, as it removes the old reference to the DialogX instance and creates a new one.
What you need to do is either extend JDialog with your DialogX class (then you can delete the JDialog variable completely) or remove the static keywoard before the JDialog variable g. Then you can call dialogx.dispose() (you extended JDialog) or a custom method you need to implement which forwards the call to g.dispose() (you did not extend JDialog).
Related
What I have:
Two Classes that instantiate two JFrames.
What I am trying to achieve:
One with a button and the other that will become invisible when a action is fired on the button.
Problems:
I do not know how to pursue this. How should I go about coding this?
Class 1
public class test1{
public static void main(String[] args){
JFrame frame = new JFrame("Blinkly Frame");
frame.setSize(100, 100);
frame.setVisible(true);
}
}
Class 2
public class test2{
public static void main(String[] args){
JButton button = new JButton();
//when i will click this button i want to make invisible frame
}
}
Solution:
Create an instance of the class that has a Jframe or extends a JFrame.
First we need the JFrame that will be disappearing.
public class BClass extends JFrame{
// Disappearing frame
public BClass()
{
this.setSize(300,300);//sets frame properties
this.setLocationRelativeTo(null);
}
}
Next we need the Frame that will be holding the buttons. (Documentation added)
public class ACLass {
public static void main(String[] args) {
JFrame frame = new JFrame("Magician"); // instantiates
BClass b = new BClass(); // instantiates class that extends JFrame
b.setVisible(true);//
frame.setSize(300,300);//
frame.setVisible(true);//
frame.setLocationRelativeTo(null);//
JButton disappearButton = new JButton("Disappear"); //Adds button
disappearButton.addActionListener(new ActionListener() { // Adds action -When button is "clicked"
public void actionPerformed(ActionEvent e) { // method called when action fired
b.setVisible(false); //visibility changed
}
});
disappearButton.setBounds(0,0,300,150);
JButton appearButton = new JButton("appear"); //Adds button
appearButton.addActionListener(new ActionListener() { // Adds action -When button is "clicked"
public void actionPerformed(ActionEvent e) { // method called when action fired
b.setVisible(true); //visibility changed
}
});
disappearButton.setBounds(0,100,300,150);
frame.add(disappearButton, BorderLayout.PAGE_START); //adds button to frame
frame.add(appearButton, BorderLayout.PAGE_END); //adds button to frame
//I used border layout however use the a layout manager that works with your components/frame
}
}
Exotic Explanation
I'm going to explain this in terms of a magic show as it provides better understanding.
So first, we have one magician(JFrame) and his wand(JButton) and then we have the helper(the second JFrame) that will disappear and a stage that has been set(all properties defined etc.)
First the magician adds some magic power to his wand(actionListener that handles the button being pushed) that will react when the magician waves it(action fired a.k.a button being pushed).
Next we show the audience the helper(instantiating JFrame to disappear).
As we have shown the audience the helper, we can now show him/her disappearing (Now we can call setVisible through the instance variable of the class).
Finally, the magician waves his wand(firing an action), and the helper gets the signal(actionPerformed method) to disappear. The helper then can call the
b.setVisible(false); //making the frame invisible
General Explanation
https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html
Basically, by instantiating an object in another class you can also call the objects methods in that class i.e. setVisible(boolean b).
Other less preferable solutions:
If your disappearing class has does not extend a JFrame but instantiates one..
You would need to create an instance variable
private JFrame j;
Then use getters/setters to access the object which will then allow you to call its methods.
secondClass.getFrame().setVisible(true);//getFrame returns the JFrame
Then add that to the actionPerformed method.
You can also use a static instance variable and statically reference it in the actionPerformed method... (not recommended)
secondClass.frame.setVisible(true);
I have 2 classes - a JFrame with a button, and a JDialog (a pop up) with few textfields on it. Now, when I click the button in JFrame a JDialog shows up:
/*** someClass class ****/
JButton btnNewButton = new JButton("");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
jd = new jDialog();
jd.setModal(true);
jd.setVisible(true);
}
});
public void doStuff(String one....String five){
... ..
}
Now a jDialog pops up and i need to fill up some textfields inside it and click another button to confirm.
/*** jDialog class ***/
JButton btnConfirm = new JButton("");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
one = 1_tf.getText();
two = 2_tf.getText();
three = 3_tf.getText();
four = 4_tf.getText();
five = 5_tf.getText();
doAnything(one,two,three,four,five);
1_tf.setText("");
2_tf.setText("");
3_tf.setText("");
4_tf.setText("");
5_tf.setText("");
}
});
public void doAnything(String one,String two,String three,String four,String five){
someClass sc = new someClass();
sc.doStuff(one,two,three,four,five);
}
The textfield's values will be passed to doAnything() method, inside doAnything() is an instance of someClass class to access sc.doStuff() method and pass the values.
The problem now is that, Whenever I click confirm on jDialog class a new JFrame appears so there are 2 JFrames which is not what I want.. It's like whenever I do something on jdialog it creates a new JFrame instead of over lapping the original JFrame.
In the doAnything() don't recreate the someClass (it's better to read java naming convention -classes should start from capital letter) instances.
Define class field for the someClass instance? create it just once (if it's null) and reuse it.
That's probably because in the someClass constructor you create an show a JFrame. To avoid this problem, make a static reference to the doStuff() method.
Declare it as:
public static doStuff(one, two, three, four, five) {
...
}
and use it as:
someClass.doStuff(one, two, three, four, five);
Now, when you use the method, you don't have to create an object of someClass class, and then you don't have to call the constructor method.
import java.awt.*;
import java.awt.event.*;
public class but extends Frame {
but() {
Button b = new Button("OK");
add(b);
b.addActionListener(new MyAn_innerclass());
}
public static void main(String args[]) {
but obj = new but();
obj.setSize(200, 100);
obj.setVisible(true);
}
}
class MyAn_innerclass implements ActionListener {
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
}
i have this code and i wonder why do we write this add(b); in constructor of the button class while adding button to the frame.I know that add(b); is used to push button to the frame but why write it in constructor,also if i remove the constructor the add function is not recognized by the compiler.why is it so?
Sorry if it sounds lame but i am a beginner to java
because when you creating swing frames you need to add components as soon as you start frame .when you create new instance of a class ,constructor get called .adding component is good to do in constructor .but you can also make a method and call it from constructor instead putting add in constructor but both are same ..
public class but extends Frame
{
but(){
Button b= new Button("OK");//add component immediately to frame
add(b);
}
}
if you didn't add in the constructor you will see empty frame until you add components to it.
you can also add component in another method but you have to call it from constructor
public class but extends Frame
{
but(){
initcomponent();//call component creating and adding method
}
public void initcomponent(){
Button b= new Button("OK");//add component immediately to frame
add(b);
}
}
If you asking about Button class itself (i.e Button b = new Button("OK");), then "OK" is the label of the button and you DON'T have to add it to the button while creating it. You can create the button then add the label after that:
Button b = new Button();
b.setLabel("OK");
If you asking about add(b);, at first it's a method not a constructor, then it's pretty logical to enforce you to add an argument to it, as you are adding some component to the frame, so what's that component? an empty one? it must be some component(Button, Text, ...etc).
Ok so i have a comboBox, and a JTextField, whenever i chose the quantity, it would be displayed on the textfield. I have another class, which will retrieve the whatever inside the textfield, but the order class doesn't retrieve the information from catalogue class.
class Catalogue extends JPanel {
String[] h1Quantity = {"0","1","2","3","4","5","6","7","8","9","10"};
h1CBox = new JComboBox <String> (h1Quantity);
h1CBox.setSelectedIndex(0);
h1CBox.addActionListener (new Listener());
h1CBox.setPreferredSize ( new Dimension (50,30));
JLabel noBooks = new JLabel ("Quantity");
booksF = new JTextField(8);
public class Listener implements ActionListener {
public void actionPerformed (ActionEvent event) {
int total = h1CBox.getSelectedIndex();
booksF.setText(Integer.toString(total));
}
}
public String booksFText() {
return booksF.getText();
}
}
class Order extends JPanel {
Catalogue catalogue ;
public Order (Catalogue catalogue)
{
this.catalogue = catalogue;
JPanel panel = new JPanel ();
String text2= catalogue.booksFText();
textArea1 = new JTextArea (text2, 20, 35);
add(textArea1);
add(panel);
}
}
I'm new to java so please keep it simple. thanks alot.
You have 2 constructors in the Order class and catalogue is only set in the first one. Set this in the second contructor as well and the NPE should go away (although hard to know for sure without the stacktrace!)
Always try to post complete code. and stack trace too.
See your order class.
class Order extends JPanel {
public Order (Catalogue catalogue)
{
add(textArea);
}
}
If you use the second constructor , then the class variable catalogue will not be given memory. Thus NULL POINTER EXCEPTION . The code inside the second constructor has been moved to the first one.
The other reason may be that the variable being passed in order constructor is not defined properly. Should be done something like this.
Catalogue catalogue = new Catalogue();
Order order = new Order(catalogue);
See Updated Catalogue class.
class Catalogue extends JPanel {
String[] h1Quantity = {"0","1","2","3","4","5","6","7","8","9","10"};
JComboBox<String> h1CBox ; //Assuming you forgot to define it.
JLabel noBooks ;
JTextField booksF ;
//Define a new constructor
public Catalogue () {
//set jlabel
noBooks = new JLabel ("Quantity");
//set combobox
h1CBox = new JComboBox <String> (h1Quantity);
h1CBox.setSelectedIndex(0);
h1CBox.addActionListener (new Listener());
h1CBox.setPreferredSize ( new Dimension (50,30));
//set textfield
booksF = new JTextField(8);
//add UI items to your panel class
add(h1CBox); //combobox
add(noBooks); // label
add(booksF); // textfield
}
public class Listener implements ActionListener {
public void actionPerformed (ActionEvent event) {
int total = h1CBox.getSelectedIndex();
booksF.setText(Integer.toString(total));
}
}
public String booksFText() {
return booksF.getText();
}
}
Always define your UI like this . Of course , there are better ways . Thus code looks clean and you understand things. Learn to put comments to remind you what you tried to do somewhere.
The MAIN Class
public class Main {
static JTextArea textArea = new JTextArea(40,40);
static class Order extends JPanel{
public Order(){
add(textArea);
}
}
static class Catalogue extends JPanel{
....
private ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
textArea.setText(h1CBox.getSelectedIndex()+"");
}
};
}
public static void main(String args[]){
//Construct a frame and add panels and you are good to go.
}
}
One last suggestion, if you plan on NOT changing the data of textarea yourself , use textfield or label instead of textarea. Sometimes the text inside textarea is set , but user is unable to see because of improper bounds . So , to be sure just replace the textarea with label or textfield. Cheers :)
G'day all,
I am coding a main menu for a project. The menu displays properly. I have also set up ActionListeners for the three buttons on the menu.
What I wish to do is reuse the JPanel for a new set of radio buttons when the user chooses "Start a New Game".
However, coding ActionPerformed to remove the existing components from the JPanel has me stumped. I know removeAll is somehow important, but unfortunately NetBeans informs me I cannot call it on my mainMenu JPanel object within ActionPerformed. So i have commented it out in my code below, but left it in so you can see what I am trying to do.
Your thoughts or hints are appreciated.
Here is my main code:
public class Main {
public static void main(String[] args) {
MainMenu menu = new MainMenu();
menu.pack();
menu.setVisible(true);
}
}
Here is my mainMenu code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainMenu extends JFrame implements ActionListener {
JButton startNewGame = new JButton("Start a New Game");
JButton loadOldGame = new JButton("Load an Old Game");
JButton seeInstructions = new JButton("Instructions");
public MainMenu() {
super("RPG Main Menu");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainMenu = new JPanel();
mainMenu.setLayout(new FlowLayout());
startNewGame.setMnemonic('n');
loadOldGame.setMnemonic('l');
seeInstructions.setMnemonic('i');
startNewGame.addActionListener(this);
loadOldGame.addActionListener(this);
seeInstructions.addActionListener(this);
mainMenu.add(startNewGame);
mainMenu.add(loadOldGame);
mainMenu.add(seeInstructions);
setContentPane(mainMenu);
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == startNewGame) {
// StartNewGame code goes here
// mainMenu.removeAll();
}
if (source == loadOldGame) {
// LoadOldGame code goes here
}
if (source == seeInstructions) {
// Quit code goes here
}
}
}
Consider using a CardLayout instead, which manages two or more components (usually JPanel instances) that share the same display space. That way you don't have to fiddle with adding and removing components at runtime.
You need mainMenu to be a member variable:
public class MainMenu extends JFrame implements ActionListener {
JButton startNewGame = new JButton("Start a New Game");
JButton loadOldGame = new JButton("Load an Old Game");
JButton seeInstructions = new JButton("Instructions");
JPanel mainMenu = new JPanel();
Why do you feel the need to re-use this object?
You don't have a reference to mainMenu actionPerformed use. If you declare mainMenu with the buttons. It would work.
The problem is that the actionPerformed method is trying to call the JPanel mainMenu which is out of scope, i.e. the mainMenu variable is not visible from the actionPerformed method.
One way to get around this is to have the JPanel mainMenu declaration in the class itself and make it an instance field which is accessible to all instance methods of the class.
For example:
public class MainMenu extends JFrame implements ActionListener
{
...
JPanel mainMenu;
public MainMenu()
{
...
mainMenu = new JPanel();
...
}
public void actionPerformed(ActionEvent e)
{
...
mainMenu.removeAll();
}
}
Avoid attempting to "reuse" stuff. Computers are quite capable of tidying up. Concentrate on making you code clear.
So instead of attempting to tidy up the panel, simply replace it with a new one.
Generally a better way to write listeners is as anonymous inner classes. Code within these will have access to final variables in the enclosing scope and to members of the enclosing class. So, if you make mainMenu final and you ActionListeners anonymous inner classes, your code should at least compile.
Also don't attempt to "reuse" classes. Try to make each class do one sensible thing, and avoid inheritance (of implementation). There is almost never any need to extend JFrame, so don't do that. Create an ActionListener for each action, rather than attempting to determine the event source.
Also note, you should always use Swing components on the AWT Event Dispatch Thread. Change the main method to add boilerplate something like:
public static void main(final String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
runEDT();
}});
}