Usando um JFileChooser com classs GUI Swing e ouvintes

Este é o meu menu atual:

public class DrawPolygons { public static void main (String[] args) throws FileNotFoundException { /** * Menu - file reader option */ JMenuBar menuBar; JMenu menu; JMenuItem menuItem; // Create the menu bar. menuBar = new JMenuBar(); // Build the first menu. menu = new JMenu("File"); menu.setMnemonic(KeyEvent.VK_F); menu.getAccessibleContext().setAccessibleDescription("I have items"); menuBar.add(menu); // a group of JMenuItems menuItem = new JMenuItem("Load",KeyEvent.VK_T); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK)); menuItem.getAccessibleContext().setAccessibleDescription("Load your old polygons"); menu.add(menuItem); menuItem = new JMenuItem("Save",KeyEvent.VK_U); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK)); menuItem.getAccessibleContext().setAccessibleDescription("Save the contents of your polygons"); menu.add(menuItem); // attaching the menu to the frame JFrame frame = new JFrame("Draw polygons"); frame.setJMenuBar(menuBar); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(new DrawingPanel()); frame.pack(); frame.setVisible(true); } } 

Tem duas opções para Load e Save . insira a descrição da imagem aqui

Agora, como posso append o JFileChooser ao método actionPerformed , aqui:

 /** * Main class * @author X2 * */ class DrawingPanel extends JPanel implements MouseListener, MouseMotionListener ,KeyListener { // code // code // and more code static DrawingPanel app ; private static final Dimension MIN_DIM = new Dimension(300, 300); private static final Dimension PREF_DIM = new Dimension(500, 500); public Dimension getMinimumSize() { return MIN_DIM; } public Dimension getPreferredSize() { return PREF_DIM; } JMenuItem open, save; JTextArea textArea ; JFileChooser chooser ; FileInputStream fis ; BufferedReader br ; FileOutputStream fos ; BufferedWriter bwriter ; public void actionPerformed( ActionEvent event ) { Object obj = event.getSource() ; chooser = new JFileChooser() ; if ( chooser.showOpenDialog( app ) == JFileChooser.APPROVE_OPTION ) if ( obj == open ) { try { fis = new FileInputStream( chooser.getSelectedFile() ) ; br = new BufferedReader( new InputStreamReader( fis ) ) ; String read ; StringBuffer text = new StringBuffer() ; while( ( read = br.readLine() ) != null ) { text.append( read ).append( "\n" ) ; } textArea.setText( text.toString() ) ; } catch( IOException e ) { JOptionPane.showMessageDialog( this , "Error in File Operation" ,"Error in File Operation" ,JOptionPane.INFORMATION_MESSAGE) ; } } } /** * The constructor */ DrawingPanel() { super(); addMouseListener(this); addMouseMotionListener(this); addKeyListener(this); setFocusable(true); requestFocusInWindow(); } // a lot of code more // and more // and more } 

Com o código inicial do menu e o Jpanel , que criei no main ?

Saudações

————————

EDITAR:

O “novo” código:

 public class DrawPolygons { public static void main (String[] args) throws FileNotFoundException { // attaching the menu to the frame JFrame frame = new JFrame("Draw polygons"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // JMenuBar // Create the menu and JmenuBar JMenuBar menuBar = new JMenuBar(); // Build the first menu. JMenu menu = new JMenu("File"); menu.setMnemonic(KeyEvent.VK_F); menu.getAccessibleContext().setAccessibleDescription("I have items"); menuBar.add(menu); // menu option - load // create the load option final JMenuItem loadItem = new JMenuItem("Load",KeyEvent.VK_T); // add the shortcut loadItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK)); // short description loadItem.getAccessibleContext().setAccessibleDescription("Load your old polygons"); // JFileChooser with filter JFileChooser fileChooser = new JFileChooser("."); // apply the filter to file chooser FileNameExtensionFilter filter = new FileNameExtensionFilter("scn files (*.scn)", "scn"); fileChooser.setFileFilter(filter); fileChooser.setControlButtonsAreShown(false); frame.add(fileChooser, BorderLayout.CENTER); final JLabel directoryLabel = new JLabel(" "); directoryLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36)); final JLabel filenameLabel = new JLabel(" "); filenameLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36)); // add listener to LOAD loadItem.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { JFileChooser theFileChooser = new JFileChooser(); String command = actionEvent.getActionCommand(); if (command.equals(JFileChooser.APPROVE_SELECTION)) { File selectedFile = theFileChooser.getSelectedFile(); directoryLabel.setText(selectedFile.getParent()); filenameLabel.setText(selectedFile.getName()); } else if (command.equals(JFileChooser.CANCEL_SELECTION)) { directoryLabel.setText(" "); filenameLabel.setText(" "); } }} // end listener ); // end listener to loadItem menu.add(loadItem); // now SAVE // create the option for save JMenuItem saveItem = new JMenuItem("Save",KeyEvent.VK_U); // key shortcut for save saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK)); saveItem.getAccessibleContext().setAccessibleDescription("Save the contents of your polygons"); // add the save to the menu menu.add(saveItem); frame.setJMenuBar(menuBar); frame.setContentPane(new DrawingPanel()); frame.pack(); frame.setVisible(true); } } 

O problema é, agora, quando eu bati em Load Under File , nada está acontecendo. Por quê ?

Eu adicionei o ouvinte, mas nada.

Como regra geral, você não deve ter suas classs de GUI, como a class que estende o JPanel, implementar qualquer interface de ouvinte, e na verdade você deve se esforçar para o contrário – separar as funções de controle do programa (os ouvintes e como) das funções de visualização do programa (a GUI). Então, minha resposta à sua pergunta “como posso append o JFileChooser ao método actionPerformed … [à minha class DrawingPanel que estende o JPanel], é me esforçar para não fazer isso.

Em vez disso, suas classs de visualização implementam interfaces que permitiriam que as classs de controle interagissem mais facilmente com elas.

Edit 1 : seu novo código você nunca exibe o diálogo JFileChooser. Você precisa exibir o diálogo aberto:

 // first make sure that you've declared the JFrame frame as final int result = theFileChooser.showOpenDialog(frame); if (result == JFileChooser.APPROVE_OPTION) { // ... code goes here } 

Editar 2

Exemplo de Swing Model-View-Control:

Por exemplo, aqui está uma implementação MVC ou Model-View-Control que mostra a exibição, o modelo e o controle. Tudo isso é muito simplista, e tudo o que faz no momento é abrir um arquivo de texto e exibi-lo em um JTextField, é isso, e ele tenta separar as funções de controle da exibição.

MvcMain class

 import javax.swing.SwingUtilities; public class MvcMain { private static void createAndShowGui() { MvcView view = new ShowTextView("Show Text"); MvcModel model = new ShowTextModel(); ShowTextControl control = new ShowTextControl(view, model); control.showView(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } 

Interface MvcModel

 import java.beans.PropertyChangeListener; public interface MvcModel { static final String TEXT = "text"; static final String STATUS = "STATUS"; String getText(); String getStatus(); void setText(String text); void setStatus(String text); void addPropertyChangeListener(PropertyChangeListener listener); void removePropertyChangeListener(PropertyChangeListener listener); } 

Interface do MvcView

 import java.awt.Window; import javax.swing.Action; public interface MvcView { void setVisible(boolean visible); void setFileAction(Action fileAction); void setOpenFileAction(Action openFileAction); void setSaveToFileAction(Action saveToFileAction); void setExitAction(Action exitAction); void setStatusText(String string); String getTextAreaText(); void setTextAreaText(String text); Window getTopWindow(); } 

Classe ShowTextView

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.awt.Window; import javax.swing.*; public class ShowTextView implements MvcView { private JFrame frame = new JFrame(); private JMenuBar menuBar = new JMenuBar(); private JMenu fileMenu = new JMenu(); private StatusBar statusBar = new StatusBar(); private ViewDisplayText displayText = new ViewDisplayText(); public ShowTextView(String title) { menuBar.add(fileMenu); frame.setTitle(title); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(displayText.getMainComponent(), BorderLayout.CENTER); frame.getContentPane().add(statusBar.getComponent(), BorderLayout.PAGE_END); frame.setJMenuBar(menuBar); } @Override public void setVisible(boolean visible) { frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } @Override public void setOpenFileAction(Action action) { displayText.setOpenFileButtonAction(action); fileMenu.add(new JMenuItem(action)); } @Override public void setSaveToFileAction(Action action) { displayText.setSaveToFileAction(action); fileMenu.add(new JMenuItem(action)); } @Override public void setExitAction(Action exitAction) { displayText.setExitAction(exitAction); fileMenu.add(new JMenuItem(exitAction)); } @Override public void setFileAction(Action fileAction) { fileMenu.setAction(fileAction); } @Override public String getTextAreaText() { return displayText.getTextAreaText(); } @Override public void setTextAreaText(String text) { displayText.setTextAreaText(text); } @Override public Window getTopWindow() { return frame; } @Override public void setStatusText(String text) { statusBar.setText(text); } } class ViewDisplayText { private static final int TA_ROWS = 30; private static final int TA_COLS = 50; private static final int GAP = 2; private JPanel mainPanel = new JPanel(); private JButton openFileButton = new JButton(); private JButton saveToFileButton = new JButton(); private JButton exitButton = new JButton(); private JTextArea textArea = new JTextArea(TA_ROWS, TA_COLS); public ViewDisplayText() { JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0)); buttonPanel.add(openFileButton); buttonPanel.add(saveToFileButton); buttonPanel.add(exitButton); mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); mainPanel.setLayout(new BorderLayout()); mainPanel.add(new JScrollPane(textArea), BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.PAGE_END); } public void setExitAction(Action exitAction) { exitButton.setAction(exitAction); } public JComponent getMainComponent() { return mainPanel; } public void setOpenFileButtonAction(Action action) { openFileButton.setAction(action); } public void setSaveToFileAction(Action action) { saveToFileButton.setAction(action); } public String getTextAreaText() { return textArea.getText(); } public void setTextAreaText(String text) { textArea.setText(text); } } class StatusBar { private static final String STATUS = "Status: "; private JLabel label = new JLabel(STATUS); public StatusBar() { label.setBorder(BorderFactory.createLineBorder(Color.black)); } public JComponent getComponent() { return label; } public void setText(String text) { label.setText(STATUS + text); } } 

Classe ShowTextModel

 import java.beans.PropertyChangeListener; import javax.swing.event.SwingPropertyChangeSupport; public class ShowTextModel implements MvcModel { private String text; private String status; private SwingPropertyChangeSupport propChangeSupport = new SwingPropertyChangeSupport(this); @Override public String getText() { return text; } @Override public void setText(String text) { String newValue = text; String oldValue = this.text; this.text = newValue; propChangeSupport.firePropertyChange(TEXT, oldValue, newValue); } @Override public void setStatus(String status) { String newValue = status; String oldValue = this.status; this.status = newValue; propChangeSupport.firePropertyChange(STATUS, oldValue, newValue); } @Override public void addPropertyChangeListener(PropertyChangeListener listener) { propChangeSupport.addPropertyChangeListener(listener); } @Override public void removePropertyChangeListener(PropertyChangeListener listener) { propChangeSupport.removePropertyChangeListener(listener); } @Override public String getStatus() { return status; } } 

Classe ShowTextControl

 import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; import java.util.concurrent.ExecutionException; import javax.swing.*; public class ShowTextControl { private MvcView view; private MvcModel model; public ShowTextControl(MvcView view, MvcModel model) { this.view = view; this.model = model; view.setFileAction(new FileAction("File", KeyEvent.VK_F)); view.setOpenFileAction(new OpenFileAction(view, model, "Open File", KeyEvent.VK_O)); view.setSaveToFileAction(new SaveToFileAction(view, model, "Save to File", KeyEvent.VK_S)); view.setExitAction(new ExitAction(view, model, "Exit", KeyEvent.VK_X)); model.addPropertyChangeListener(new ModelListener(view, model)); } public void showView(boolean visible) { view.setVisible(visible); } } @SuppressWarnings("serial") class OpenFileAction extends AbstractAction { private MvcView view; private MvcModel model; public OpenFileAction(MvcView view, MvcModel model, String name, int keyCode) { super(name); putValue(MNEMONIC_KEY, keyCode); this.view = view; this.model = model; } @Override public void actionPerformed(ActionEvent evt) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setMultiSelectionEnabled(false); int result = fileChooser.showOpenDialog(view.getTopWindow()); if (result == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); if (file.exists()) { if (file.getName().endsWith(".txt")) { model.setStatus("Opening file \"" + file.getName() + "\""); OpenFileWorker openFileWorker = new OpenFileWorker(file); openFileWorker.addPropertyChangeListener( new OpenFileWorkerListener(model)); openFileWorker.execute(); } else { model.setStatus("File \"" + file.getName() + "\" is not a text file"); } } else { model.setStatus("File \"" + file.getName() + "\" does not exist"); } } } } class OpenFileWorker extends SwingWorker { private File file; public OpenFileWorker(File file) { this.file = file; } public File getFile() { return file; } @Override protected String doInBackground() throws Exception { StringBuilder stringBuilder = new StringBuilder(); Scanner scan = null; try { scan = new Scanner(file); while (scan.hasNextLine()) { stringBuilder.append(scan.nextLine() + "\n"); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (scan != null) { scan.close(); } } return stringBuilder.toString(); } } class OpenFileWorkerListener implements PropertyChangeListener { private MvcModel model; public OpenFileWorkerListener(MvcModel model) { this.model = model; } @Override public void propertyChange(PropertyChangeEvent evt) { if (SwingWorker.StateValue.DONE == evt.getNewValue()) { OpenFileWorker openFileWorker = (OpenFileWorker) evt.getSource(); try { String text = openFileWorker.get(); model.setText(text); model.setStatus("File \"" + openFileWorker.getFile().getName() + "\" opened"); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } } @SuppressWarnings("serial") class FileAction extends AbstractAction { public FileAction(String name, int keyCode) { super(name); putValue(MNEMONIC_KEY, keyCode); } @Override public void actionPerformed(ActionEvent arg0) { // pretty much empty } } @SuppressWarnings("serial") class SaveToFileAction extends AbstractAction { private MvcView view; private MvcModel model; public SaveToFileAction(MvcView view, MvcModel model, String name, int keyCode) { super(name); putValue(MNEMONIC_KEY, keyCode); this.view = view; this.model = model; } @Override public void actionPerformed(ActionEvent e) { // TODO finish! } } @SuppressWarnings("serial") class ExitAction extends AbstractAction { private MvcView view; // private MvcModel model; // TODO: may use this later public ExitAction(MvcView view, MvcModel model, String name, int keyCode) { super(name); putValue(MNEMONIC_KEY, keyCode); this.view = view; // this.model = model; // TODO: may use this later } @Override public void actionPerformed(ActionEvent e) { view.getTopWindow().dispose(); } } class ModelListener implements PropertyChangeListener { private MvcView view; private MvcModel model; public ModelListener(MvcView view, MvcModel model) { this.view = view; this.model = model; } @Override public void propertyChange(PropertyChangeEvent pcEvt) { if (MvcModel.TEXT.equals(pcEvt.getPropertyName())) { view.setTextAreaText(model.getText()); } else if (MvcModel.STATUS.equals(pcEvt.getPropertyName())) { view.setStatusText(model.getStatus()); } } } 

Neste exemplo, combinei classs Java em um arquivo para fins de concisão, mas no aplicativo eles estariam em seus próprios arquivos, mas todos compartilham o mesmo pacote. Note que, embora isso possa ser um “over-kill” para esse aplicativo simples, usei esse tipo de estrutura com vários aplicativos Swing muito grandes com bom êxito. O principal benefício para mim é quando preciso depurar ou aprimorar um programa meses após a criação, pois essa separação de interesses, informações e comportamentos tornou muito mais fácil para mim fazer alterações em uma parte do programa sem ofender ou perturbar outra parte do programa. o programa.

Além disso, a razão para as interfaces é que você pode criar GUIs novas ou diferentes com aparência diferente, mas que podem responder da mesma maneira. Também os usei com frequência para ajudar a criar classs simuladas que me permitem testar melhor meus módulos isoladamente.

Eu recomendaria usar ação (s) para usar lá. Em cada ação você tem algum actionlistener específico, configure seu painel como ouvinte se você quiser:

Ação explicada

Para elaborar o que o Kitesurfer disse, eu usaria uma Action porque na maioria das vezes eu tenho botões da barra de ferramentas ou outros componentes executando as mesmas ações que itens de menu. Para evitar código desnecessário ou duplicado em algum lugar da class (ou em qualquer local onde eu possa acessá-lo a partir da class atual), criei um campo Action que eu possa reutilizar, se necessário, ou mova se decidir refatorar meu código. Aqui está um exemplo.

 JMenuItem miLoad = new JMenuItem(actionLoad); Action actionLoad = new AbstractAction("Load") { public void actionPerformed(ActionEvent e) { //your code to load the file goes here like a normal ActionListener } }; 

Definitivamente, confira a API para ver quais parâmetros podem ser passados ​​para a class AbstractAction , usei uma String para que o JMenuItem exiba a string, você também pode definir o Icon , não me lembro de todos os construtores, então valeria a pena Dando uma olhada. Ah, e passar os JMenuItems para o construtor da class DrawingPanel não é necessariamente uma má idéia, mas se ele herdar do JPanel , não acredito que você possa adicionar uma barra de menu a um JPanel então certifique-se de que ele seja adicionado ao seu JFrame também . Espero que ajude.

A solução rápida para o seu problema é fornecer um manipulador para que você possa append o ActionListener. Você faz o JMenus em main() , mas você não tem visibilidade para eles em seu DrawingPanel . Uma maneira barata de fazer isso seria passar os JMenuItems para o seu construtor DrawingPanel. Modifique o construtor para algo como:

 DrawingPanel(JMenuItem save, JMenuItem open) { // the stuff you already got this.save = save; this.open = open; save.addActionListener(this); open.addActionListener(this); } 

Então você os passaria para o seu DrawingPanel no main :

 JMenuItem loadMenuItem = new JMenuItem("Load"); JMenuItem saveMenuItem = new JMenuItem("Save"); ... frame.getContentPane(new DrawingPanel(saveMenuItem, loadMenuItem)); 

De uma perspectiva no estilo Java, não está claro se o DrawingPanel é o melhor local para manipular ações de salvamento e carregamento. Como outros mencionaram, criar Ações (separadas) para cada JMenuItem é geralmente um padrão melhor. No seu caso, você pode ser capaz de fornecer outros methods auxiliares ou auxiliares dentro do DrawingPanel que forneçam aos trabalhadores do saver / loader as informações necessárias para executar suas ações.


Edit: (para abordar o “novo código” do OP)

Eu acho que o problema com o “novo código” é que você está fazendo um new JFileChooser no método actionPerformed , e não usando o existente que você fez anteriormente e adicionou ao quadro. Se você fizer o primeiro final , poderá usar o mesmo JFileChooser no método actionPerformed .