«Невозможно обратиться к неконечной переменной» из обработчика действия? - PullRequest
2 голосов
/ 07 декабря 2011

Я обещаю, что я прочитал бесчисленные посты об этом, поэтому я предполагаю, что не могу перевести то, что я прочитал, в то, что я пытаюсь сделать. Сначала повествование. Исходя из этого, я хочу разработать список объектов, в моем примере объекты - автомобили. Список автомобилей отображается в моем главном окне. Когда я хочу добавить новый автомобиль, я открываю диалоговое окно, чтобы установить атрибуты и создать его.

Проблема в том, что я продолжаю бегать кругами со ссылками на объекты. Я пробовал создавать подклассы с открытыми методами и передавать объекты в конструкторы. Эти попытки приводят к ошибкам о нестатических полях или не конечных переменных. Если бы я мог просто увидеть хороший пример того, как сделать ссылки, я думаю, что все остальное встало бы на свои места.

объект

public class Car {
private String size;

public Car(String sizeIn){
    this.size = sizeIn;
}   
public void setSize(String sizeIn){
    this.size = sizeIn;
}
public String getSize(){
    return this.size;
}
public String toString(){
    return this.size;
}
}

главное окно

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JList;

public class MainGUI {

private JFrame frame;
private LinkedList<Car> carList;
private DefaultListModel model;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MainGUI window = new MainGUI();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public MainGUI() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton btnAddCar = new JButton("Add Car");
    btnAddCar.addActionListener(new EditLauncher());
    frame.getContentPane().add(btnAddCar, BorderLayout.NORTH);

    JList list = new JList(model);
    frame.getContentPane().add(list, BorderLayout.CENTER);
}

public void addCar(String size){
    Car car = new Car(size);
    carList.add(car);
    model.addElement(car);
    frame.getContentPane().invalidate();
    frame.getContentPane().validate();
}

public class EditLauncher implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub

    }

}

}

Диалог

import java.awt.BorderLayout;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JLabel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


public class EditDialog extends JDialog {

private final JPanel contentPanel = new JPanel();
private JTextField fldSize;
private MainGUI mainGUI;

/**
 * Launch the application.
 */
public static void main(String[] args) {

    try {
        EditDialog dialog = new EditDialog(mainGUI); //<<ERROR - Cannot make a static reference to the non-static field mainGU
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setVisible(true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * Create the dialog.
 */
public EditDialog(MainGUI mainGUI) {
    this.mainGUI = mainGUI;
    setBounds(100, 100, 225, 125);
    getContentPane().setLayout(new BorderLayout());
    contentPanel.setLayout(new FlowLayout());
    contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    getContentPane().add(contentPanel, BorderLayout.CENTER);
    JLabel lblSize = new JLabel("Size");
    contentPanel.add(lblSize);
    fldSize = new JTextField();
    contentPanel.add(fldSize);
    fldSize.setColumns(10);

    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
    getContentPane().add(buttonPane, BorderLayout.SOUTH);
    JButton okButton = new JButton("OK");
    okButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            mainGUI.addCar(fldSize.getText()); // << ERROR Cannot refer to a non-final variable mainGUI inside an inner class defined in a different method
        }
    });
    okButton.setActionCommand("OK");
    buttonPane.add(okButton);
    getRootPane().setDefaultButton(okButton);

    JButton cancelButton = new JButton("Cancel");
    cancelButton.setActionCommand("Cancel");
    buttonPane.add(cancelButton);

}

}

1 Ответ

6 голосов
/ 07 декабря 2011

Для «Невозможно сделать статическую ссылку на нестатическое поле mainGUI»

Проблема в том, что (EditDialogs) main является статической и может поэтому иметь доступ только к статическим членам или элементу явного экземпляра объекта(например, object.member форма).В этом случае mainGUI не является статическим членом, и поэтому к нему нельзя получить доступ: это нормально, потому что экземпляр MainGUI не создается, если вызывается этот «main»!(Помните, только один main используется при каждом запуске приложения! Избавьтесь от «основного» в EditDialog, чтобы избежать этой путаницы.)

Вместо этого учтите это (но см. Комментарий Дэйва для лучшего подхода полностью!):

btnAddCar.addActionListener(new ActionListener () {
    public void actionPerformed(ActionEvent e) {
        EditDialog dialog = new EditDialog(MainGUI.this);
        dialog.show(); // or whatever
    }
});

Для "Невозможно обратиться к неконечной переменной mainGUI внутри внутреннего класса, определенного в другом методе"

Ошибка в том, что из анонимного внутреннего типа (new ActionListener() { ... }) могут использоваться только переменные-члены (включающего типа) или «конечные» локальные переменные.

Теперь можноgo "но mainGUI является переменной-членом!"

Да, это , но это затемнение локальной переменной с тем же именем (this.mainGUIпротив mainGUI).Вот известные мне решения:

  1. Измените имя локальной переменной, чтобы избежать затенения: public EditDialog(MainGUI theMainGUI) ...

  2. Квалифицируйте mainGUI наскажите Java, что переменная-член желательна, что позволяет обойти теневое копирование: EditDialog.this.mainGUI.addCar(...), где EditDialog - имя включающего типа.(Этот же подход был сделан выше для MainGUI.this.)

  3. Аннотируйте параметр mainGUI с помощью final: public EditDialog(final MainGUI mainGUI) ....Переменная-член будет по-прежнему затенена, но локальная переменная будет соответствовать требованиям доступа, поскольку она «окончательная».

Счастливое кодирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...