"Kan niet verwijzen naar een niet-definitieve variabele" van actie-afhandelaar?

Ik beloof dat ik hier ontelbare berichten over heb gelezen, dus ik vermoed dat ik niet kan vertalen wat ik lees naar wat ik probeer te doen. Eerst het verhaal. Aan de basis, wat ik wil doen is een lijst met objecten ontwikkelen in mijn voorbeeld dat de objecten auto's zijn. De lijst met auto's wordt weergegeven in mijn hoofdvenster. Wanneer ik een nieuwe auto wil toevoegen, open ik een dialoogvenster om de kenmerken in te stellen en deze te maken.

Het probleem is dat ik steeds in cirkels ronddraai met de objectreferenties. Ik heb geprobeerd subklassen te maken met openbare methoden en objecten in constructors door te geven. Deze pogingen resulteren in fouten over niet-statische velden of niet-definitieve variabelen. Als ik een goed voorbeeld zou zien van hoe de referenties gemaakt moeten worden, denk ik dat de rest op zijn plaats zou vallen.

het object

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;
}
}

hoofd venster

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 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

    }

}

}

het dialoogvenster

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); //<
2
Wat is het probleem precies? Welke coderegels werken niet zoals u denkt dat ze zouden moeten doen? En nee, alsjeblieft, vertel niet dat de hele 50+ regels het "probleem" zijn :)
toegevoegd de auteur Victor Sorokin, de bron
Op een snelle manier doorlezen ... Ik zie ook niet waar een CarList wordt gebouwd? (moet waarschijnlijk in de constructor zitten voor het MainGUI-glas dat de referentie bezit)
toegevoegd de auteur BRFennPocock, de bron

1 antwoord

Voor "Kan geen statische verwijzing naar het niet-statische veld mainGUI maken"

Het probleem is (EditDialogs) main is statisch en heeft daarom alleen toegang tot statische leden of een lid van een instantie van een expliciet object (bijvoorbeeld het object.member -formulier). In dit geval is mainGUI geen statisch lid en kan daarom niet worden geopend: wat goed is, omdat er geen MainGUI-instantie wordt gemaakt als die "hoofd" wordt aangeroepen! (Vergeet niet dat er slechts één hoofd wordt gebruikt elke keer dat de toepassing wordt gestart! Verwijder "main" in EditDialog om verwarring te voorkomen.)

Overweeg dit in plaats daarvan (maar zie de opmerking van Dave voor een betere aanpak helemaal!):

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

Voor "Kan niet verwijzen naar een niet-definitieve variabele mainGUI binnen een innerlijke klasse gedefinieerd in een andere methode"

De fout is dat alleen lidvariabelen (van het insluitende type) of "definitieve" lokale variabelen kunnen worden gebruikt binnen een anonieme binnencategorie ( nieuwe ActionListener() {...} ).

Nu zou je kunnen gaan "maar mainGUI is een ledenvariabele!"

Nou, het is, maar het wordt shadowed door een lokale variabele met dezelfde naam ( this.mainGUI versus mainGUI ). Dit zijn de oplossingen die ik ken:

  1. Wijzig de naam van de lokale variabele om schaduwvorming te voorkomen: public EditDialog (MainGUI theMainGUI) ...

  2. Kwalificeer mainGUI om aan Java te laten weten dat de ledvariabele gewenst is, die de shadowing omzeilt: EditDialog.this.mainGUI.addCar (...) , waar EditDialog is de naam van het omhullende type. (Deze zelfde aanpak is hierboven gedaan voor MainGUI.this .)

  3. Annoteer de mainGUI parameter met final : public EditDialog (final MainGUI mainGUI) ... . De ledvariabele wordt nog steeds in de schaduw geplaatst, maar de lokale variabele voldoet aan de toegangseisen omdat deze "definitief" is.

Happy codering.

6
toegevoegd
Nog een suggestie - scheid uw model en weergave. Door addCar() in de GUI-klasse vanuit het dialoogvenster aan te roepen, wijzigt u het model via de weergave. Het is beter om het model rechtstreeks aan te passen. Kijk naar het ontwerppatroon van Model-View-Controller.
toegevoegd de auteur Dave, de bron