【问题标题】:ActionListener, List IssueActionListener,列表问题
【发布时间】:2021-12-29 19:55:18
【问题描述】:

我的程序遇到了问题。目标是收集输入(电影名称、媒体类型和年份)并在单击“添加电影”时将其附加到列表中。然后,当单击“显示电影”按钮时,列表将显示在文本区域中。我不确定我错过了什么或做错了什么。

import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class MovieDatabase extends JFrame implements ActionListener{
    
     //create LinkedList of Movie Objects
    LinkedList<Movie> list = new LinkedList<Movie>(); 
    
    //JPanel for input movie
    private JPanel inputJPanel;
    
    //JLable and JTextField for Movie Name
    private JLabel movieJLabel;
    private JTextField movieJTextField;

    //JLable and JTextField for Media
    private JLabel mediaJLabel;
    private JTextField mediaJTextField; 
    
    //JLable and JTextField for Release Year
    private JLabel yearJLabel;
    private JTextField yearJTextField;
    
    //JButton to add movie to a list
    private JButton addJButton;
    
    //JButton to show movie in text area
    private JLabel showJLabel;
    private JButton showJButton;

    //JTextArea to display movies from list
    private JTextArea showJTextArea;
    private JPanel listJPanel;
    
    //no argument constructor
    public MovieDatabase(){
        createUserInterface();
    }
    
    //create GUI window with components
    private void createUserInterface(){
        //get content pane window and set layout to null - no layout manager
        Container contentPane = getContentPane();
        contentPane.setLayout(null);
        
        //set up input panel
        inputJPanel = new JPanel();
        inputJPanel.setLayout(null);
        inputJPanel.setBorder(new TitledBorder("Input Movie")); //anonymous object
        inputJPanel.setBounds(20,4,260,178);// (x,y,w,h)
        contentPane.add(inputJPanel);
        
        //set up input panel
        showJLabel = new JLabel();
        showJLabel.setLayout(null);
        showJLabel.setText("Movies: "); 
        showJLabel.setBounds(300,0,260,25);// (x,y,w,h)
        contentPane.add(showJLabel);
        
        //set up payment JTextArea here
        showJTextArea = new JTextArea();
        showJTextArea.setBounds(300,30,300,145);// (x,y,w,h)
        showJTextArea.setEditable(false);
        contentPane.add(showJTextArea);
        
        //show movies JButton
        showJButton = new JButton();
        showJButton.setBounds(480,175,110,30);
        showJButton.setText("Show Movies");
        contentPane.add(showJButton);
       
        
        //movie name JLabel
        movieJLabel = new JLabel();
        movieJLabel.setBounds(10,24,100,21);// (x,y,w,h)
        movieJLabel.setText("Movie Name:");
        inputJPanel.add(movieJLabel);
        //movie name JTextField
        movieJTextField = new JTextField();
        movieJTextField.setBounds(104,24,120,21);
        movieJTextField.setHorizontalAlignment(JTextField.RIGHT);
        inputJPanel.add(movieJTextField);
        
        //media name JLabel
        mediaJLabel = new JLabel();
        mediaJLabel.setBounds(10,54,100,21);// (x,y,w,h)
        mediaJLabel.setText("Media:");
        inputJPanel.add(mediaJLabel);
        //media name JTextField
        mediaJTextField = new JTextField();
        mediaJTextField.setBounds(104,54,120,21);
        mediaJTextField.setHorizontalAlignment(JTextField.RIGHT);
        inputJPanel.add(mediaJTextField);        
        
        //year name JLabel
        yearJLabel = new JLabel();
        yearJLabel.setBounds(10,84,100,21);// (x,y,w,h)
        yearJLabel.setText("Release Year:");
        inputJPanel.add(yearJLabel);
        //year name JTextField
        yearJTextField = new JTextField();
        yearJTextField.setBounds(104,84,80,21);
        yearJTextField.setHorizontalAlignment(JTextField.RIGHT);
        inputJPanel.add(yearJTextField);
        
        //add movie JButton
        addJButton = new JButton();
        addJButton.setBounds(92,138,94,24);
        addJButton.setText("Add Movie");
        inputJPanel.add(addJButton);
        
        //set window properties
        setTitle("Movie"); //set title bar
        setSize(625, 250);//window size
        setVisible(true); //display window 
        
        addJButton.addActionListener(this);
        showJButton.addActionListener(this);
        
    }
    
     public void addButtonactionPerformed(ActionEvent e){
        String movieName = movieJTextField.getText();
        String media = mediaJTextField.getText();
        int year = Integer.parseInt(yearJTextField.getText());
        //create instance of Movie
        Movie movie = new Movie(movieName, media, year);
        list.add(movie);
        
        movieJTextField.setText("");
        mediaJTextField.setText("");
        yearJTextField.setText("");         
     }
    private void showButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        showJTextArea.setText("");
        String str = String.format("%-20s%-20s%-20s\n", "Year", "Media", "Title");
        showJTextArea.append(str);
        for (Movie movie : list) {
             str = String.format("%-20s%-19s%-22s\n", Integer.toString(movie.year), movie.media, movie.name);
             showJTextArea.append(str);
        }
    }  
         
}

 class Movie{
 String name;
 String media;
 int year;

 public Movie(String n, String m, int y){
 name = n;
 media = m;
 year = y;
 }


public class MovieGUI {


    public static void main(String[] args) {
        MovieDatabase application = new MovieDatabase();
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        
  
        

    }//close and stop application
    
}
 }

【问题讨论】:

  • ActionListener 的接口只有一种方法可以实现actionPerformed(ActionEvent e) - 这将被两个按钮调用。根据ActionEventSource,您应该采取不同的行动
  • null 布局很烂,花点时间学习如何使用布局管理器Laying Out Components Within a Container;您还没有实现ActionListener 的要求(showButtonActionPerformed 表明您正在使用诸如 Netbeans 表单编辑器之类的东西)。也许你应该看看How to Write an Action Listener
  • 你可能还想看看How to Use Tables

标签: java list user-interface actionlistener


【解决方案1】:

null 布局将再次困扰您。没有“像素完美”布局之类的东西,只是有很多变量与不同硬件和操作系统之间渲染方式的差异相关,甚至可以考虑做出这种选择。

花时间学习如何使用布局管理器Laying Out Components Within a Container

您尚未实现ActionListener 的要求(showButtonActionPerformed 表明您正在使用 Netbeans 表单编辑器之类的东西)。

也许你应该看看How to Write an Action ListenerHow to Use Buttons, Check Boxes, and Radio Buttons

您可能还想查看How to Use Tables

在我看来,您需要采取稍微不同的策略,并专注于区分责任领域。收集电影信息与存储结果或显示结果无关,所以我会将它们分开到它自己的容器中,这样您就可以更轻松地管理它。

这就引出了一个问题,“当用户‘添加’一部电影时,你如何通知相关方?”。有趣的是,您已经对这个概念有些熟悉了。

本质上,您使用“侦听器”,或者更常见的说法是“观察者模式”。这使您可以通知相关方发生了某些事情,在这种情况下,用户创建了一部新电影。

例如...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MovieManagerPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Movie {

        String name;
        String media;
        int year;

        public Movie(String n, String m, int y) {
            name = n;
            media = m;
            year = y;
        }

        public String getName() {
            return name;
        }

        public String getMedia() {
            return media;
        }

        public int getYear() {
            return year;
        }


    }

    public class MovieManagerPane extends JPanel {

        private JTextArea moviesTextArea;
        private List<Movie> movies = new ArrayList<>(32);

        public MovieManagerPane() {
            setLayout(new BorderLayout());

            moviesTextArea = new JTextArea(20, 40);
            String str = String.format("%-20s%-20s%-20s\n", "Year", "Media", "Title");
            moviesTextArea.append(str);

            MoviePane moviePane = new MoviePane();
            moviePane.setBorder(new CompoundBorder(new TitledBorder("Input Movie"), new EmptyBorder(4, 4, 4, 4)));
            moviePane.addMovieListener(new MoviePane.MovieListener() {
                @Override
                public void movieWasAdded(MoviePane source, Movie movie) {
                    movies.add(movie);
                    String str = String.format("%-20s%-20s%-20s\n", movie.getYear(), movie.getMedia(), movie.getName());
                    moviesTextArea.append(str);
                }
            });

            add(moviePane, BorderLayout.LINE_START);
            add(moviesTextArea);
        }

    }

    public class MoviePane extends JPanel {

        public static interface MovieListener extends EventListener {

            public void movieWasAdded(MoviePane source, Movie movie);
        }

        //JLable and JTextField for Movie Name
        private JLabel movieJLabel;
        private JTextField movieJTextField;

        //JLable and JTextField for Media
        private JLabel mediaJLabel;
        private JTextField mediaJTextField;

        //JLable and JTextField for Release Year
        private JLabel yearJLabel;
        private JTextField yearJTextField;

        //JButton to add movie to a list
        private JButton addJButton;

        public MoviePane() {
            setLayout(new GridBagLayout());

            movieJLabel = new JLabel("Movie Name:");
            mediaJLabel = new JLabel("Media:");
            yearJLabel = new JLabel("Release Year:");

            movieJTextField = new JTextField(10);
            mediaJTextField = new JTextField(10);
            yearJTextField = new JTextField(10);

            addJButton = new JButton("Add Movie");

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = gbc.EAST;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(movieJLabel, gbc);
            gbc.gridy++;
            add(mediaJLabel, gbc);
            gbc.gridy++;
            add(yearJLabel, gbc);

            gbc.gridx++;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.anchor = gbc.WEST;

            add(movieJTextField, gbc);
            gbc.gridy++;
            add(mediaJTextField, gbc);
            gbc.gridy++;
            add(yearJTextField, gbc);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = 2;
            gbc.fill = GridBagConstraints.NONE;
            gbc.weighty = 1;
            gbc.anchor = gbc.SOUTH;

            add(addJButton, gbc);

            addJButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        // Use a JSpinner or JFornattedTextField to avoid this
                        int year = Integer.parseInt(yearJTextField.getText());
                        Movie movie = new Movie(movieJTextField.getText(), mediaJTextField.getText(), year);
                        fireMovieWasAdded(movie);
                    } catch (NumberFormatException exp) {
                        JOptionPane.showMessageDialog(MoviePane.this, "Invalid year", "Error", JOptionPane.ERROR_MESSAGE);
                    }
                }
            });
        }

        public void addMovieListener(MovieListener listener) {
            listenerList.add(MovieListener.class, listener);
        }

        public void removeMovieListener(MovieListener listener) {
            listenerList.remove(MovieListener.class, listener);
        }

        protected void fireMovieWasAdded(Movie movie) {
            MovieListener[] listeners = listenerList.getListeners(MovieListener.class);
            if (listeners.length == 0) {
                return;
            }

            for (MovieListener listener : listeners) {
                listener.movieWasAdded(this, movie);
            }
        }

    }
}

您可能还想看看 How to Use SpinnersHow to Use Formatted Text Fields 处理“非字符串”输入

【讨论】:

  • 谢谢。我还没有学过微调器。我看到我忘记了我的 get 和 set 方法,然后尝试 catch。我明白你使用网格布局的观点。
猜你喜欢
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-03
相关资源
最近更新 更多