5

As a beginner Java programmer I would like some help as to understanding the best way or technique for building a swing UI for my console app.

The console app works well now I would like to convert it to a swing app. I would like to have a swing JTextArea in a JScrollPane that the user can edit to input their string then click a countwords button and get an output as a int.

The code for my console app and my attempt to the swing app as well is below. I have spent quite a bit of time trying to research this but I can't seem to get it right.

My console app :

 import java.util.*;
 public class WordCounter{

 public static void main(String args[])
    {
     // Create Scanner object
     Scanner s=new Scanner(System.in);

    // Read a string
     String st=s.nextLine();

     //Split string with space
     String words[]=st.trim().split(" ");

     System.out.println("No. of words "+words.length);
    }
  }

My attempt at Swing :

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JTextArea;

import java.util.*;

class Countswords extends JPanel {

    public Countswords() {
        myTextArea();

    }

    private void myTextArea() {
        this.setLayout(new BorderLayout());
        this.setPreferredSize(new Dimension(400, 200));

        JTextArea textArea = new JTextArea(5, 40);
        JScrollPane scrollPane = new JScrollPane(textArea);
        // textArea.setEditable(true);
        JTextArea.setText(userInput);

    }

    public static void showFrame() {
        JPanel panel = new Countswords();
        panel.setOpaque(true);

        JFrame frame = new JFrame("My Text Area");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        // Create Scanner object
        // Scanner s=new Scanner(System.in);

        // Read a string
        // String st=s.nextLine();

        // Split string with space
        // String words[]=st.trim().split(" ");

        // System.out.println("No. of words "+words.length);
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                Countswords.showFrame();
            }
        });
    }
}
ouflak
  • 2,458
  • 10
  • 44
  • 49
Reign
  • 289
  • 1
  • 9
  • 3
    It's generally felt that you cannot 'convert' an app. from command line based to GUI based. It requires an entirely different approach that is simply 'too broad' to be explained in an SO answer. See the [Creating a GUI With JFC/Swing](http://docs.oracle.com/javase/tutorial/uiswing/) trail of the Java tutorial for how to create a GUI. – Andrew Thompson Jun 23 '14 at 10:34
  • 1
    *"My attempt at Swing"* So.. what's wrong with it? Where are you stuck? – Andrew Thompson Jun 23 '14 at 10:36
  • 1
    `this.setPreferredSize(new Dimension(400, 200));` See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/q/7229226/418556) (Yes.) – Andrew Thompson Jun 23 '14 at 10:36
  • Well you have all the GUI elements but just didn't connect them together. The frame should contain the JScrollPane and JScrollPane should contain the JTextArea. Check the links by Andrew. – dARKpRINCE Jun 23 '14 at 10:46
  • Using GUI is one part. I would suggest you to separate your Graphical/console interface from your service/processing utilities. i.e. class implementing a GUI component should not provide functionality for how its data will be processed, rather read the state of the component and pass it to your classes (common to both interfaces) dedicated for data processing. This way it will be much easier to plug in a new interface in your existing application. – Shailesh Aswal Jun 23 '14 at 11:26

1 Answers1

3

You can make use of this code to make your app as Swing based.

import java.io.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import java.util.*;

public class CountWords extends JFrame {
JTextArea   textArea;
JScrollPane scrollPane;
Container   container;

JPanel      panel;
JLabel      label;

JButton     button;

public CountWords() {
    initialize();
    addToPanel();
}

public void initialize() {
    container = getContentPane();
    textArea = new JTextArea(5,20);
    scrollPane = new JScrollPane(textArea);

    button = new JButton(" Count Words ");

    panel = new JPanel();
    label = new JLabel(" Total Words : ");

    label.setBackground(Color.yellow);
}

public void addToPanel() {

    panel.add(button);

    container.add(scrollPane, BorderLayout.NORTH);
    container.add(panel, BorderLayout.SOUTH);
    container.add(label, BorderLayout.CENTER);

    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent ae) {
            label.setText("No.of Words : "+ getTotalWords(textArea.getText()));
        }
    });
}

public int getTotalWords( String text ){
    String words[]= text.trim().split(" ");
    return words.length;
}
public static void main(String args[]) {
    CountWords cw = new CountWords();
    cw.setDefaultCloseOperation(3); // JFrame.EXIT_ON_CLOSE => 3
    cw.pack();
    cw.setSize(400,300);
    cw.setVisible(true);
}
}
chandra
  • 41
  • 3
  • 1
    1) `cw.setDefaultCloseOperation(3);` Don't use magic numbers, use the defined constant. 2) GUIs should be started on the EDT. 3) With size suggestions (columns and rows) for the text field and text area, `cw.setSize(400,300);` should be unnecessary. 4) Don't extend `JFrame` unless changing functionality. Prefer composition to inheritance. 5) `container.add(scrollPane, BorderLayout.NORTH);` Better to use the more localization friendly `container.add(scrollPane, BorderLayout.PAGE_START);` .. – Andrew Thompson Jun 23 '14 at 11:40
  • thanks i found that .... String words[]= text.trim().split("\\w\\s+"); is a better way to split the words by spaces as it strips multiple spaces like tabs and gives a more accurate word count! always better to strip regular expressions. – Reign Jun 25 '14 at 08:44