Не может ссылаться на неоконечное отображение локальной переменной, определенное во включающей области - PullRequest
1 голос
/ 13 июля 2020

Это может быть очень простой c вопрос. Но я застрял на этом. Ошибка, которую я получаю для переменной String display, гласит:

Cannot refer to the non-final local variable display defined in an enclosing scope.

Если я использую ключевое слово final, я получаю сообщение:

The final local variable display cannot be assigned, since it is defined in an enclosing slope.*

Код:

public class Frame {

public static void main(String[] args) {
    String display=" ";
    Frame ob=new Frame();
    JFrame frame=new JFrame("Test");
    frame.setBounds(300,100,800,500);
    //Container c=frame.getContentPane(); 
    frame.setLayout(null);
    final JTextField name=new JTextField();
    name.setBounds(500,212,150,20);
    JLabel nameLabel=new JLabel("Name: ");
    nameLabel.setForeground(Color.WHITE);
    nameLabel.setBounds(450,171,100,100);
    JTextField ohr=new JTextField();
    ohr.setBounds(500,282,150,20);
    JLabel ohrID=new JLabel("OHR ID: ");
    ohrID.setForeground(Color.WHITE);
    ohrID.setBounds(450,241,100,100);

    final JButton button=new JButton("Submit");
    button.setBounds(530,350,90,20);
    frame.add(name);
    frame.add(ohr);
    frame.add(ohrID);
    frame.add(nameLabel);
    frame.add(button);
    frame.getContentPane().setBackground(Color.DARK_GRAY);
    frame.setVisible(true);

    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            if(e.getSource()==button){
                display=name.getText();
                JOptionPane.showMessageDialog(null, "Hi "+ display);
                System.exit(0);
            }
        }
    });
}

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 13 июля 2020

В вашем коде есть несколько проблем, и мы решим их прямо здесь, прямо сейчас и решим вашу проблему одновременно.

  1. public class Frame { в этой конкретной строке ошибка, Frame - это имя класса AWT, поэтому оно может запутать вас или любого, кто позже прочитает этот код, дайте ему более осмысленное имя и избегайте тех имен, которые можно спутать с другими Java пакетами.

  2. Frame ob=new Frame(); вы создаете экземпляр своего класса и никогда не используете его снова, почему?

  3. frame.setLayout(null); НИКОГДА , пожалуйста, не используйте null-layout. Swing должен иметь дело с несколькими PLAF, размерами и разрешениями экрана, разными ОС, приложениями с идеальным пикселем, может показаться самым простым способом создания сложных пользовательских интерфейсов, но позже вы обнаружите эти ошибки вот так случаются очень часто.

  4. .setBounds(...) на каждом компоненте, опять же, это связано с null-layout, но лучше использовать менеджеры компоновки

  5. final JTextField name=new JTextField(); Нет необходимости декларировать являются любыми из ваших компонентов как final, это связано с плохой конструкцией вашего класса, ваши компоненты должны быть объявлены как члены класса (вне любого метода, включая main).

  6. Говоря о main, разделите свою программу на более мелкие части, не бросайте все на main или, по крайней мере, создавайте метод, отличный от static, чтобы вы могли вызвать его после создания экземпляра вашего класса ( иначе позже вы получите кучу static переменных, и это снова плохой дизайн вашего класса).

  7. System.exit(0); это остановит JVM, это никогда не стоит делать это, лучше .dispose() JFrame и установить JFrame s defaultCloseOperation на EXIT_ON_CLOSE, который безопасно удалит ваше приложение, а затем остановит JVM.

  8. display=name.getText();, в данном конкретном случае display может быть внутренней переменной, а не членом класса. Это решит ваш конкретный вопрос

  9. JOptionPane.showMessageDialog(null, "Hi "+ display); что null должно быть ссылкой на ваш JFrame, это поместит ваш диалог в середину это JFrame, а не в середине экрана.

  10. Вы никогда не размещаете свою программу внутри EDT, см. пункт 2 в этом ответе .

Итак, имея в виду все вышеперечисленное, вот улучшенная версия вашего кода.

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class UsingVariablesInsideActionListenerExample {
    //We declare our components here
    private JFrame frame;
    private JButton button;
    private JTextField name;
    private JTextField ohr;
    private JLabel nameLabel;
    private JLabel ohrID;
    private JPanel pane;
    private JPanel namePane;
    private JPanel ohrPane;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new UsingVariablesInsideActionListenerExample()::createAndShowGUI); //This is using Java 8 lambdas to place your program in the EDT
    }

    private void createAndShowGUI() {
        frame = new JFrame("Test"); //Create your JFrame 
        
        pane = new JPanel();
        pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS)); //This will make this JPanel to arrange components vertically
        
        namePane = new JPanel(); //By default, JPanels have FlowLayout which will arrange components horizontally
        ohrPane = new JPanel();
        
        name = new JTextField(10); //We create a JTextField with 10 columns 
        nameLabel = new JLabel("Name: ");
        nameLabel.setForeground(Color.WHITE);
        
        ohr = new JTextField(10);
        ohrID = new JLabel("OHR ID: ");
        ohrID.setForeground(Color.WHITE);

        button = new JButton("Submit");
        
        //Add the action listener
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == button) {
                    String display = name.getText(); //The display variable is now an inner variable rather than a class member
                    JOptionPane.showMessageDialog(frame, "Hi " + display);
                    frame.dispose(); //We dispose the JFrame and it will be closed after due to EXIT_ON_CLOSE below.
                }
            }
        });
        
        //We add the components to the namePane (horizontally), the order matters
        namePane.add(nameLabel);
        namePane.add(name);
        
        //Now we add these components to the ohrPane (horizontally again)
        ohrPane.add(ohrID);
        ohrPane.add(ohr);
        
        //We then add the name and ohr panes to a bigger JPanel (pane, which if you remember will add them vertically) and we add the button at the end
        pane.add(namePane);
        pane.add(ohrPane);
        pane.add(button);
        
        //We make them non opaque (transparent) so that we can see the background color of the JFrame
        namePane.setOpaque(false);
        ohrPane.setOpaque(false);
        pane.setOpaque(false);
        
        frame.add(pane);
        
        frame.getContentPane().setBackground(Color.DARK_GRAY);
        frame.pack(); //This will get every component's preferred size and make the JFrame as small as possible where it looks good on every OS, PLAF, screen size and resolution.
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true); //We make the frame visible (always at the very end, when we've added everything to it).
    }
}

И вот как это выглядит сейчас.

введите описание изображения здесь

Пользовательский интерфейс может не полностью совпадать с тем, который у вас есть, но я уверен, что вы можете поиграть с разными менеджерами компоновки и вложить различные JPanel s, чтобы получить гораздо лучше выглядящий интерфейс чем мой, или, по крайней мере, более похожий на тот, что был у вас.

0 голосов
/ 13 июля 2020

Переменная, используемая во внутреннем классе, должна быть фактически окончательной. Вы можете использовать строку [] длины 1 вместо строки, чтобы решить эту проблему. Пожалуйста, прочтите сообщение ниже для получения более подробной информации

Разница между final и фактически final

Также проверьте этот пост для более подробной информации

Переменная, используемая в лямбда-выражение должно быть окончательным или фактически окончательным

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