0

Okay, I'm trying to make my JButton run an executable in a different directory. It is a previous console application I wrote and I want this button to run the executable. I'm fairly new to the Java programming language but here is my code.

import java.util.*;

import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;



public class main
{
    public static void main(final String[] args) throws IOException {
        JFrame f = new JFrame("Test");
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500, 500);
        JPanel p = new JPanel();
        JButton b1 = new JButton("Calculate");
        f.add(p);
        p.add(b1);
        Process proce = Runtime.getRuntime().exec("C:/Ctest.exe");
    }
    private static void test1() {
        // TODO Auto-generated method stub

    }
    {
        JFrame f = new JFrame("Test");
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500, 500);
        JPanel p = new JPanel();
        JButton b1 = new JButton("Calculate");
        f.add(p);
        p.add(b1);
        b1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

            }
        });
     }
}

Also if you have any tips for me please feel free to tell them to me. I use the eclipse IDE.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
Groax
  • 23
  • 1
  • 1
  • 9
  • possible duplicate of [Running a bash shell script in java](http://stackoverflow.com/questions/13707519/running-a-bash-shell-script-in-java) – StackFlowed Oct 07 '14 at 01:48
  • 1
    I'm sorry, but your code makes no sense and looks like a programming "flight of ideas" -- random programming thoughts crammed together. As for your question, what do you mean exactly by "run a console program"? Is this a Java console program? Is it a type of program where the user will interact with the program via the console? If so, what is the purpose of running it from a GUI? These details will help others understand your problem better. – Hovercraft Full Of Eels Oct 07 '14 at 01:48
  • Please edit your code. It seemed that you pasted a block twice. – PM 77-1 Oct 07 '14 at 01:49
  • @PM77-1 Yeah, It was just an experimental program that would open a new window when I clicked the button but thank you for pointing that out. – Groax Oct 07 '14 at 02:06
  • @HovercraftFullOfEels Okay, what I meant by run a console program is, it would run a console wrapped program. The user would interact with it directly through the scanners using the System.in BUT I am asking this question right now so I can use it in more advanced ways in the future. Please forgive me for being extremely unclear. – Groax Oct 07 '14 at 02:08
  • Better to leave the console world to itself and the event-driven world to itself, since the user interactions in the two are completely different, which would make for UI code that should not be meshed. Better to concentrate on creating decent models that are UI agnostic and so can be used in either console programs or UI programs with ease. – Hovercraft Full Of Eels Oct 07 '14 at 02:10
  • @HovercraftFullOfEels So what you're suggesting is that I keep the two programs separate, is that correct? – Groax Oct 07 '14 at 02:12
  • No. I'm suggesting that you extract out of your console program its core concepts to create a Model, a collection of classes that hold the logic and key data that underpins your program, but that has no user interaction code whatsoever. And then use this model in a console program and in your GUI program. Consider telling and showing us more regarding your console program. – Hovercraft Full Of Eels Oct 07 '14 at 02:22

3 Answers3

3

Start by taking a look at ProcessBuilder.

Swing is a single threaded framework, so you won't want to start the Process within the current context of the Event Dispatching Thread (in which the actionPerformed is called) and will need to execute it within it's own thread context.

This raises the issue of synchronising results from the Process back to the UI, which should only ever be done within the context of the EDT. To this end, you should consider using a SwingWorker

Take a look at Concurrency in Swing and Worker Threads and SwingWorker for more details

Have a look at

for more examples...

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    Thank you I will definitely take this into consideration, I'll have to learn ProcessBuilder but I'm sure that it isn't the worst thing in the world or the hardest thing to learn. Again thank you for your answer – Groax Oct 07 '14 at 02:10
2

What I'm saying is that you should consider extracting the core logic and data from your console program to create a model class or classes, and then use them in your console program or in a GUI.

For instance say you had a simple console program that got name and birth date information from someone:

class SimpleConsole {
   public static void main(String[] args) throws ParseException {
      Scanner scanner = new Scanner(System.in);
      System.out.print("Please enter your name: ");
      String name = scanner.nextLine();

      System.out.print("Please enter your date of birth as mm/dd/yyyy: ");
      String dateString = scanner.nextLine();
      Date dateOfBirth = new SimpleDateFormat("MM/dd/yyyy").parse(dateString);

      Calendar birthday = Calendar.getInstance();
      birthday.setTime(dateOfBirth);
      Calendar today = Calendar.getInstance();
      int age = today.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
      birthday.set(Calendar.YEAR, today.get(Calendar.YEAR));
      if (birthday.compareTo(today) > 0) {
         age--;
      }

      System.out.println("Hello, " + name + ". Your age is: " + age);

   }
}

First thing I'd do would be to extract the key information and logic from this program and make a class, say called Person, that holds a name String, a dateOfBirth Date field, and a calculateAge() method:

class Person {
   String name;
   Date dateOfBirth;

   public Person(String name, Date dateOfBirth) {
      this.name = name;
      this.dateOfBirth = dateOfBirth;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public Date getDateOfBirth() {
      return dateOfBirth;
   }

   public void setDateOfBirth(Date dateOfBirth) {
      this.dateOfBirth = dateOfBirth;
   }

   public int getAge() {
      Calendar birthday = Calendar.getInstance();
      birthday.setTime(dateOfBirth);
      Calendar today = Calendar.getInstance();
      int age = today.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
      birthday.set(Calendar.YEAR, today.get(Calendar.YEAR));
      if (birthday.compareTo(today) > 0) {
         age--;
      }
      return age;
   }
}

and now you can create a console program that uses Person:

class BetterConsole {
   public static void main(String[] args) throws ParseException {
      Scanner scanner = new Scanner(System.in);
      System.out.print("Please enter your name: ");
      String name = scanner.nextLine();

      System.out.print("Please enter your date of birth as mm/dd/yyyy: ");
      String dateString = scanner.nextLine();
      Date dateOfBirth = new SimpleDateFormat("MM/dd/yyyy").parse(dateString);

      Person person = new Person(name, dateOfBirth);


      System.out.println("Hello, " + person.getName() + ". Your age is: " + person.getAge());
      scanner.close();
   }
}

But more importantly, the Person class can be easily used in any type of GUI program that you desire. I must go to sleep so I can't show a GUI now, but may tomorrow.


Ah heck, here's the GUI example:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;

public class BirthdayGui extends JPanel {
   private static final String PATTERN = "MM/dd/yyyy";
   private JTextField nameField = new JTextField(10);
   private SimpleDateFormat simpleDateFormat = new SimpleDateFormat(PATTERN);
   private JFormattedTextField birthDayField = new JFormattedTextField(simpleDateFormat);
   private PersonTableModel tableModel = new PersonTableModel();
   private JTable table = new JTable(tableModel);

   public BirthdayGui() {
      setLayout(new BorderLayout());;
      add(new JScrollPane(table), BorderLayout.CENTER);
      add(createDataEntryPanel(), BorderLayout.PAGE_END);
   }

   private JPanel createDataEntryPanel() {
      birthDayField.setColumns(nameField.getColumns());
      JPanel dataInPanel = new JPanel();
      dataInPanel.add(new JLabel("Enter Name:"));
      dataInPanel.add(nameField);
      dataInPanel.add(new JLabel("Enter Birthday as " + PATTERN + ":"));
      dataInPanel.add(birthDayField);
      dataInPanel.add(new JButton(new AddPersonAction("Add Person", KeyEvent.VK_A)));
      return dataInPanel;
   }

   private class AddPersonAction extends AbstractAction {
      public AddPersonAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         String name = nameField.getText();
         Date dateOfBirth = (Date) birthDayField.getValue();
         Person person = new Person(name, dateOfBirth);
         tableModel.addRow(person);
      }
   }

   private class PersonTableModel extends AbstractTableModel {
      public final String[] COL_NAMES = {"Name", "Age"};
      List<Person> personList = new ArrayList<>();

      @Override
      public String getColumnName(int column) {
         return COL_NAMES[column];
      }

      @Override
      public int getColumnCount() {
         return COL_NAMES.length;
      }

      @Override
      public int getRowCount() {
         return personList.size();
      }

      @Override
      public Object getValueAt(int rowIndex, int columnIndex) {
         if (rowIndex < 0 || rowIndex >= getRowCount()) {
            throw new ArrayIndexOutOfBoundsException(rowIndex);
         }
         if (columnIndex < 0 || columnIndex >= getColumnCount()) {
            throw new ArrayIndexOutOfBoundsException(columnIndex);
         }

         Person person = personList.get(rowIndex);
         if (columnIndex == 0) {
            return person.getName();
         } else if (columnIndex == 1) {
            return person.getAge();
         }
         return null;
      }

      @Override
      public java.lang.Class<?> getColumnClass(int column) {
         if (column == 0) {
            return String.class;
         } else if (column == 1) {
            return Integer.class;
         } else {
            return super.getColumnClass(column);
         }
      };

      public void addRow(Person person) {
         personList.add(person);
         int firstRow = personList.size() - 1;
         fireTableRowsInserted(firstRow, firstRow);
      }

   }

   private static void createAndShowGui() {
      BirthdayGui mainPanel = new BirthdayGui();

      JFrame frame = new JFrame("ConsoleGuiEg");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }   
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
-1

You have to do the following:

  1. Create an ActionListener and override the method actionPerformed
  2. Call the Runtime.getRuntime().exec() in your overridden action performed method.
  3. Set the ActionListener to your button by calling button.setActionListener()
  • *"Call the `Runtime.getRuntime().exec()`.."* What are you coding for, Java 1.4?!? For Java 1.5+, use a `ProcessBuilder` since it makes it much easier to make the code robust (as opposed to this suggestion, which would fail more often than it works, and even when it works, would block the EDT). -1 – Andrew Thompson Oct 07 '14 at 05:20