LINUX.ORG.RU

Не срабатывает ActionListener

 ,


0

1

Взялся за изучение Java, пишу калькулятор. Не могу понять в чем проблема: при использовании массивов для хранения номеров и ярлыков кнопок ActionListener не срабатывает и при запуске программы, при нажатии кнопок ничего не происходит.

А должно появляться окно:

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;

public class CalculatorEngine implements ActionListener {
	
	public void actionPerformed (ActionEvent e){
		JOptionPane.showConfirmDialog(null,
				"Something happend...",
				"Just a test",
				JOptionPane.PLAIN_MESSAGE);
			}
}

Графическая часть:

import javax.swing.*;


import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.GridBagConstraints;

public class CalculatorB {
	
//Declaration of all calculator components
	
	JPanel windowContent;
	JTextField displayField;
	static JButton button[];
	JPanel p1;
	JPanel p2;
	
	
	
	String buttonNames[] = {"1","2","3","4","5","6","7","8","9","0",".","=","+","-","*","/"};
	
// Constructor creates the components in memory
// and adds them to the frame, using combination
// of BorderLayout and GridLayout
	

CalculatorB () {
	windowContent = new JPanel();
	
	
// Set the layout manager for this panel

GridBagLayout gb1 = new GridBagLayout();
windowContent.setLayout (gb1);

//Create an instance of the GrifBagConstraints
//You'll have to repeat these lines for each component
// that you'd like to add to the grid cell
GridBagConstraints constr = new GridBagConstraints ();

//setting coordinates for calculators display field:

//x coordinate on the grid

constr.gridx=0;

//y coordinate on the grid
constr.gridy=0;

//this cell has the same height as other cells
constr.gridheight=0;

//this cell has wide as 6 other ones
constr.gridwidth=6;

//fill all space in the cell
constr.fill=GridBagConstraints.BOTH;

//proportion of the horizontal space taken by this component
constr.weightx = 1.0;

//proportion of the vertical space taken by this component
constr.weighty = 1.0;

//Position of the component within the cell
constr.anchor= GridBagConstraints.CENTER;


// Create the display field
displayField = new JFormattedTextField ("0");
displayField.setHorizontalAlignment(JFormattedTextField.RIGHT);

//set constraints for this field
gb1.setConstraints(displayField,constr);


windowContent.add (displayField);

//Create the  panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones,
// and buttons with point and equal sign

p1 = new JPanel();
GridLayout g1 = new GridLayout ();
p1.setLayout(g1);


// Add the panel p1 to the center area of
// the window

windowContent.add("Center",p1);


// Create buttons using constructor of the class
//JButton that takes the label of the button as a parameter


for (int i=0;i<8;i++){
		button[i]= new JButton (buttonNames[i]);
				p1.add(button[i]);
				}
		
//Create the  panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones,
// and buttons with point and equal sign

p2 = new JPanel();
GridLayout g2 = new GridLayout (4,1);
p2.setLayout(g2);
	
for (int i=9;i<15;i++){
	button[i]= new JButton (buttonNames[i]);
		p2.add(button[i]);
		}	
	
// Add the panel p2 to the east area of
// the window
	
	windowContent.add("East",p2);
	
// Create the frame and set its content pane
	
	JFrame frame = new JFrame ("Calculator");
	frame.setContentPane (windowContent);
	
// Set the size the size of the window to be big 
// enough to accommodate all controls
	
	frame.pack();
	
// Finally, display the window
	
	frame.setVisible(true);
	}
	
public static void main (String[] args) {
	Calculator calc = new Calculator ();
	CalculatorEngine calcEngine = new CalculatorEngine ();
	for (int i=0;i<15;i++){
    button[i].addActionListener(calcEngine);
	}
	}


	

}

При этом если описывать и размещать каждую кнопку отдельно - окошко появляется. Помогите разобраться где ошибка.

Перемещено post-factum из general

★★

Calculator calc = new Calculator ();

Это первая ошибка. Класс называется CalculatorB, а _видимые_ кнопки судя по всему принадлежат экземпляру Calculator, которого здесь мы не видим. Если подправить вызов, то этот кодовый кусок (код класса CalculatorB) всё равно неработоспособен, поскольку код падает прямо в конструкторе CalculatorB. На этом можно прекратить разбор примера.

P.S.: а за такое использование статик-атрибутов, какое вы продемонстрировали тут, Вас надо сжечь на медленном огне.

Nastishka ★★★★★
()
Ответ на: комментарий от Nastishka

а за такое использование статик-атрибутов, какое вы продемонстрировали тут, Вас надо сжечь на медленном огне.

Можно поподробнее для нубов?

damnemall
()
Ответ на: комментарий от Nastishka

Спасибо большое за ответ! Буду разбираться.

Поясните, пожалуйста, что ужасного я сделал со статик-атрибутами, т.к. я только начал разбираться с java - выполняю задания по книге. Эклипс выругался, что писать как я нельзя и предложил исправление :)

Napitok ★★
() автор топика
Ответ на: комментарий от Nastishka

Вот так ругается:

Exception in thread "main" java.lang.NullPointerException
	at CalculatorA.<init>(CalculatorA.java:61)
	at CalculatorA.main(CalculatorA.java:103)

на вот эту строку:

button[i]= new JButton (buttonNames[i]);
Napitok ★★
() автор топика
Ответ на: комментарий от anonymous

Ведроид. Он почему-то упорно по-дефолту предлагал нью с большой буквы.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Ошибки были в следующем:

  • 1) Разные названия класса и экземпляра класса, который. Соответственно код был для одного класса, а графика отрисовывалась для другого класса. Это спрятало многие ошибки
  • 2) Поправив первую ошибку полезла куча ошибок в графике. В общем пришлось откатиться на прошлую версию калькулятора, реализация которой была хорошо описана в учебнике.
  • 3) В этой версии также была ошибка из пункта 1. Исправив её обнаружил проблемы в описании массивов. В общем я разобрался с массивами и все наладилось.

Вот так заработало:

import javax.swing.*;


import java.awt.GridLayout;
import java.awt.BorderLayout;

public class CalculatorA {
	//Declaration of all calculator components
	
	JPanel windowContent;
	JTextField displayField;
	static JButton buttons[];
	JPanel p1;
	JPanel p2;
	
	
	
	
	// Constructor creates the components in memory
	// and adds them to the frame, using combination
	// of BorderLayout and GridLayout
	

CalculatorA () {
	windowContent = new JPanel();
	
	// Set the layout manager for this panel

BorderLayout b1 = new BorderLayout();
windowContent.setLayout (b1);

	// Create the display field and place it in the
	// north are of the window


displayField = new JFormattedTextField ("0");
displayField.setHorizontalAlignment(JFormattedTextField.RIGHT);

windowContent.add ("North",displayField);

//Create the  panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones,
// and buttons with point and equal sign

p1 = new JPanel();
GridLayout g1 = new GridLayout (4,3);
p1.setLayout(g1);


// Add the panel p1 to the center area of
// the window

windowContent.add("Center",p1);


// Create buttons using constructor of the class
	//JButton that takes the label of the button as a parameter
buttons = new JButton[16];
String [] buttonNames = {"1","2","3","4","5","6","7","8","9","0",".","=","+","-","*","/"};
for (int i=0;i<=11;i++){
		buttons[i]= new JButton (buttonNames[i]);
		p1.add(buttons[i]);
	}
		
//Create the  panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones,
// and buttons with point and equal sign

p2 = new JPanel();
GridLayout g2 = new GridLayout (4,1);
p2.setLayout(g2);
	
for (int i=12;i<16;i++){
	buttons[i]= new JButton (buttonNames[i]);
	p2.add(buttons[i]);
}	
	
	
	
	
	
	// Add the panel p2 to the east area of
	// the window
	
	windowContent.add("East",p2);
	
	// Create the frame and set its content pane
	
	JFrame frame = new JFrame ("Calculator");
	frame.setContentPane (windowContent);
	
	// Set the size the size of the window to be big 
	// enough to accomodate all controls
	
	frame.pack();
	
	// Finally, display the window
	
	frame.setVisible(true);
	}
	
public static void main (String[] args) {
	CalculatorA calc = new CalculatorA ();
	CalculatorEngine calcEngine = new CalculatorEngine ();
	for (int i=0;i<16;i++){
	buttons[i].addActionListener(calcEngine);
}
}
}

Napitok ★★
() автор топика
Ответ на: комментарий от damnemall

Можно поподробнее для нубов?

static JButton button[] - это грубая (грубейшая) ошибка. Набор кнопок внутри окна является подмножеством атрибутов экземпляра этого окна, и за static в этом месте надо пороть розгами. В своем пример создайте два экземпляра объекта CalculatorB, и потом попробуйте определить какая кнопка нажата, не прибегая к ухищрениям с проверкой класса объекта (а не кнопка ли это? И какого класса кнопка? А может это JMyButton, а не JButton? А если это JLabel с текстом «1» или JToolButton? А в каком окне эта кнопка нажата?). Потом, вы тащите код присоединения листенера в main, создавая этим прецедент, когда оказывается недостаточно просто вызвать конструктор класса, чтобы получить работающий экземпляр. По логике, вам бы сделать что-то вот такое:

class Calculator implements ActionListener {
     JButton buttons[];
     JFreame window;
     public Calculator() {
        butons = new JButton[...];
        for (int i=0;i<...;i++) {
            buttons[i] = new JButton(...);
            buttons[i].addActionListener(this);
        }
    }
    public void actionPerformed(ActionEvent e) {
        if (button[1]==e.getSource()) { ... нажата кнопка '1'; }
        ...
    }
    public static void main(String args[]) {
        c1 = new Calculator();
        c2 = new Calculator();
    }
}

И потом, если появится желание, можно вытянуть код листенера в отдельный класс (анонимный или нет - это второй вопрос) и заняться прочими изысками.

Nastishka ★★★★★
()
Ответ на: комментарий от Nastishka

Спасибо за науку! Не все понял из Вашего поста, но, как Вы и предложили, полез читать и пробовать.

Понял что, static означает принадлежность атрибута классу, а не экземпляру класса. Соответственно создав в первом коде второй экземпляр класса события собирались только с одного.

Изначально запихнул Листенер в main потому как в книге было написано добавить в конец кода, в других местах Эклипс на него ругался, а в main он был готов с ним работать только в случае статического JButton. В итоге я выяснил, что нужно больше головой думать в дальнейших уроках и пробовать больше вариантов. В итоге заработало так:

import javax.swing.*;


import java.awt.GridLayout;
import java.awt.BorderLayout;

public class CalculatorC {
	//Declaration of all calculator components
	
	JPanel windowContent;
	JTextField displayField;
	JButton buttons[];
	JPanel p1;
	JPanel p2;
	
	
	// Constructor creates the components in memory
	// and adds them to the frame, using combination
	// of BorderLayout and GridLayout
	

CalculatorC () {
	windowContent = new JPanel();
	
	// Set the layout manager for this panel

BorderLayout b1 = new BorderLayout();
windowContent.setLayout (b1);

	// Create the display field and place it in the
	// north are of the window


displayField = new JFormattedTextField ("0");
displayField.setHorizontalAlignment(JFormattedTextField.RIGHT);

windowContent.add ("North",displayField);

//Create the  panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones,
// and buttons with point and equal sign

p1 = new JPanel();
GridLayout g1 = new GridLayout (4,3);
p1.setLayout(g1);


// Add the panel p1 to the center area of
// the window

windowContent.add("Center",p1);


// Create buttons using constructor of the class
	//JButton that takes the label of the button as a parameter
buttons = new JButton[16];
String [] buttonNames = {"1","2","3","4","5","6","7","8","9","0",".","=","+","-","*","/"};
for (int i=0;i<=11;i++){
		buttons[i]= new JButton (buttonNames[i]);
		p1.add(buttons[i]);
	}
		
//Create the  panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones,
// and buttons with point and equal sign

p2 = new JPanel();
GridLayout g2 = new GridLayout (4,1);
p2.setLayout(g2);
	
for (int i=12;i<16;i++){
	buttons[i]= new JButton (buttonNames[i]);
	p2.add(buttons[i]);
}	
	
	
	
	
	
	// Add the panel p2 to the east area of
	// the window
	
	windowContent.add("East",p2);
	
	// Create the frame and set its content pane
	
	JFrame frame = new JFrame ("Calculator");
	frame.setContentPane (windowContent);
	
	// Set the size the size of the window to be big 
	// enough to accommodate all controls
	
	frame.pack();
	// Set the ActionListener to the buttons
	CalculatorEngine calcEngine = new CalculatorEngine ();
	for (int i=0;i<16;i++){
	buttons[i].addActionListener(calcEngine);
}
	// Finally, display the window
	
	frame.setVisible(true);
	}
	
public static void main (String[] args) {
	CalculatorC calc = new CalculatorC ();
	CalculatorC calc1 = new CalculatorC ();
	
}
}


Теперь события обрабатываются с каждого экземпляра класса.
Napitok ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.