Java - enter multiple values into array via a single textfield [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
With this code, i want to develop a program that enables the user to enter 5 int values into a single textfield. These values will be stored in an array and upon pressing the button, a bar graph will be drawn to represent the entered values. Class BtnHandler handles the button click event and class gegHandler handles the textfield enter event. I can't get the user input to be collected in the array. Here is my code.
package voorbeeld0805;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Vb0805 extends JFrame {
public static void main( String args[] ) {
JFrame frame = new Vb0805();
frame.setSize( 300, 300 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setTitle( "Voorbeeld 0805" );
frame.setContentPane( new Tekenpaneel() );
frame.setVisible( true );
}
}
class Tekenpaneel extends JPanel {
private Staafdiagram staafdiagram;
private JButton knopTeken;
private JTextField gegevensVak;
private JLabel lblNo;
private int[] lengtes = new int [5];
public Tekenpaneel() {
setBackground( Color.ORANGE );
knopTeken = new JButton("Teken");
knopTeken.addActionListener(new BtnHandler());
gegevensVak = new JTextField(5);
gegevensVak.addActionListener(new gegHandler());
lblNo = new JLabel("Enter Value");
add(knopTeken);
add (gegevensVak);
add (lblNo);
}
public void paintComponent( Graphics g ) {
super.paintComponent( g );
if (staafdiagram != null)
{
staafdiagram.teken( g, 50, 250 );
}
this.requestFocusInWindow();
}
class BtnHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
//To test using the first constructor. Works perfectly
/*int [] lengtes = { 144, 98, 117, 130, 172, 173 };
staafdiagram = new Staafdiagram( lengtes, 30 );*/
repaint();
}
}
class gegHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Here user input should be collected, placed in an array and
//saved in staafdiagram.setLengtes();
for (int i = 0; i < lengtes.length; i++){
lblNo.setText("Next Value Is " + i++);
lengtes[i] = Integer.parseInt( gegevensVak.getText());
gegevensVak.setText("");//clear textfield after entering a value
}
}
}
}
class Staafdiagram {
private int[] lengtes;
private int witruimte;//this generates the spaces between the bars
//First contructor with 2 arguments array en space
public Staafdiagram( int[] lengtes, int witruimte ) {
this.lengtes = lengtes;
this.witruimte = witruimte;
}
//Second constructor with only 1 argument space
public Staafdiagram(int witruimte ) {
this.witruimte = witruimte;
}
//With this, i want the user input to be collected in an array
public void setLengtes(int[] lengtes) {
this.lengtes = lengtes;
}
//To calculate the bar with the highest value
public int bepaalMax(){
int maximum = lengtes [0];
for (int i = 1; i < lengtes.length; i++){
if (lengtes[i] > maximum)
{
maximum = lengtes[i];
}
}
return maximum;
}
//To calculate the bar with the lowest value
public int bepaalMin(){
int minimum = lengtes [0];
for (int i = 1; i < lengtes.length; i++){
if (lengtes[i] < minimum)
{
minimum = lengtes[i];
}
}
return minimum;
}
public void teken( Graphics g, int x, int y ) {
int startX = x;
// Draw the bars
for( int lengte : lengtes ) {
if (lengte == bepaalMax())
g.setColor(Color.red);
else if (lengte == bepaalMin())
g.setColor(Color.green);
else
g.setColor(Color.black);
g.fillRect( x, y - 20 - lengte, 20, lengte );
x += witruimte;
}
// Display the values under the bars
x = startX;
for( int lengte : lengtes ) {
g.drawString( String.format( "%d", lengte ), x, y );
x += witruimte;
}
}
}

If you add an ActionListener on a JTextField, the actionPerformed() method is called when you "action" this field : here is the enter key pressed.
If you want associate the button to your action, you should rather enrich the ActionListener you defined on the JButton to also get the values entered by the user. The idea is chaining the both as both operations should performed one after the other one :
These values will be stored in an array and upon pressing the button,
a bar graph will be drawn to represent the entered values.
class BtnHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
// collection information from textfield
for (int i = 0; i < lengtes.length; i++){
lblNo.setText("Next Value Is " + i++);
lengtes[i] = Integer.parseInt( gegevensVak.getText());
gegevensVak.setText("");//clear textfield after entering a value
}
// rendering
staafdiagram = new Staafdiagram( lengtes, 30 );*/
repaint();
}
}

Get the input from the text field as text
split to string array
Convert to int
MOdify your code as follows.
class BtnHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
//To test using the first constructor. Works perfectly
/*int [] lengtes = { 144, 98, 117, 130, 172, 173 };
staafdiagram = new Staafdiagram( lengtes, 30 );*/
String textInt=gegevensVak .getText(); //gegevensVak is the name of the textfield you mentioned
String[] strArray = textInt.split();
//now convert the string to int and add to a new array
repaint();
}
}

Related

Searching for characters in a set of strings

I made this program where you can input a string and it will record it and display back to the user the amount of characters in that string and the number of strings entered. For example, if the user types in "Sally" into the text box and clicks the button, it will say the
Number of string: 1
Number of characters: 5
And the user can input more strings if they want, like "Alex" and that will change the number from 1 string to 2 and the number of characters to 9
Anyway I want to make it so there is a second text box where the user can type in a few characters and search for those characters to see how many strings entered previously by the user contains the characters searched by the user
Here is an example of what it should do:
So if the user inputs: "Sally", 'Jack", and "Dachshunds" the program should read back saying that there are 3 strings and 20 characters.
Now if the user types "ac" into the search box, the program will say "The number of strings with 'ac' is 2
(Strings Jack and Dachshunds contain 'ac')
Here is my code for the entire program if what I said above was confusing
I just need help on how to code the part for searching for specific characters in those strings
I know there is something called get.contains() but I tried to implement it and I was having trouble with it
import javax.swing.*;
import java.awt.event.*;
public class good{
StringSet sSet;
JTextField inputStr;
JLabel numStr;
JLabel numChar;
JTextField inputStr2;
JLabel numofStr;
good() {
sSet=new StringSet();
JFrame f= new JFrame("StringSetYetAgain");
JLabel en=new JLabel("Enter a String:");
en.setBounds(50, 10, 100, 100);
numStr=new JLabel("Number of Strings: 0");
numStr.setBounds(50, 160, 400, 100);
numChar=new JLabel("Number of Characters: 0");
numChar.setBounds(50, 180, 400, 100);
inputStr=new JTextField();
inputStr.setBounds(50, 80, 400, 50);
JButton pushMe=new JButton("Push to include String");
pushMe.setBounds(50, 140, 400, 50);
JLabel enter=new JLabel("String to search for:");
enter.setBounds(50, 230, 400, 100);
inputStr2=new JTextField();
inputStr2.setBounds(50, 300, 400, 50);
JButton pushMe2=new JButton("Search");
pushMe2.setBounds(50, 360, 400, 50);
numofStr=new JLabel("Number of strings with: 0");
numofStr.setBounds(50, 405, 400, 50);
pushMe.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s=inputStr.getText();
sSet.add(s);
String ns=numStr.getText();
ns=ns.substring(0, ns.length() - 1)+sSet.size();
numStr.setText(ns);
String nc=numChar.getText();
nc=nc.substring(0, nc.length() - 1)+sSet.numChars();
numChar.setText(nc);
inputStr.setText("");
}
});
//I would add the code for the search part here
f.add(en);
f.add(inputStr);
f.add(pushMe);
f.add(numStr);
f.add(numChar);
f.add(enter);
f.add(inputStr2);
f.add(pushMe2);
f.add(numofStr);
f.setSize(550,600);
f.setLayout(null);
f.setVisible(true);
}
public static void main(String[] args) {
new good();
}
}
Here is the source code for the StringSet class
public class StringSet {
private String[] arr;
private int count;
public StringSet() {
arr = new String[200];
count = 0;
}
void add(String newStr){
arr[count++] = newStr;
}
int size(){
return count;
}
int numChars(){
int total = 0;
for(int i = 0; i < count; ++i){
total += arr[i].length();
}
return total;
}
int countStrings(int len){
int total = 0;
for(int i = 0; i < count; ++i){
if(arr[i].length() == len)
++total;
}
return total;
}
}
Here is the part so far for the searching of the characters
pushMe2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
public int countOf(String substring, StringSet sSet) {
int counter = 0;
for (int i = 0; i < sSet.size(); i++)
if (sSet.get(i).contains(substring))
counter++;
return counter;
}
}
});
Add that where you said
I would add the code for the search part here
buttonThatShouldCount.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int counter = 0;
String substring = inputStr2.getText();
for (int i = 0; i < sSet.size(); i++)
if (sSet.get(i).contains(substring))
counter++;
inputStr2.setText("The substring \"" + substring "\" occurs " + count + " times.");
}
}
You'll also need to add the following method to your StringSet class:
public String get(int index) {
return arr[index];
}
We need to do this, because otherwise there is no way to access the strings stored in the set.

How to know on which Label I clicked [Java]

I tried .equals() and ==, but nothing help. All labels I storage in ArrayList of my own class, which have JLabel.
How can I get the index of the label in ArrayList or something else?
Can my problem in using ArrayList?
MouseListener
private static MouseListener clicklvl1=new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
for (int i=0;i<shahtars.size();i+=1){
if (e.getSource()==shahtars.get(i).uiShahtar){
IDofClickedObject=i;
}
}
if (IDofClickedObject!=-1){
if (counter == 0) {
shahtars.get(IDofClickedObject).uiShahtar.setIcon(new ImageIcon("E:\\aaa\\ShahtarLvL1(Clicked).png"));
counter = 1;
} else if (counter == 1) {
// uiShahtar.setIcon(new ImageIcon("E:\\aaa\\ShahtarLvL1.png"));
shahtars.get(IDofClickedObject).uiShahtar.setIcon(new ImageIcon("E:\\aaa\\ShahtarLvL1.png"));
counter = 0;
}
}
System.out.print("x "+shahtars.get(IDofClickedObject).uiShahtar.getX()+" y "+shahtars.get(IDofClickedObject).uiShahtar.getY());
}
My class
class FillShahtar implements Cloneable {
static JLabel uiShahtar;
static int energy;
static double power;
static double speed;
String name;
And the last
FillShahtar(int chose) {
switch (chose){
case 1:{
plankaDown = 1;
plankaUp = 11;
int xRand = (int) ( 0+Math.random()*1000);
int yRand =(int) (0+Math.random()*600);
int counter=0;
/////////////////////////debug/////////////////
System.out.print(xRand+" "+yRand+"\n");
//////////////////////////////////////////////
energy = (int) (plankaDown + Math.random() * plankaUp );
power = (int) (plankaDown + Math.random() * plankaUp );
speed = (int) (plankaDown + Math.random() * plankaUp );
uiShahtar = new JLabel();
uiShahtar.setIcon(new ImageIcon("E:\\aaa\\ShahtarLvL1.png"));
uiShahtar.setLayout(new FlowLayout());
uiShahtar.setSize(50,50);
uiShahtar.setLocation(xRand,yRand);
uiShahtar.setVisible(true);
uiShahtar.addMouseListener(clicklvl1);
// mainPanel.add(shahtars.get(counter).uiShahtar);
counter+=1;
break;
}
Clicked image must change the image, but change only last Label.
Since JLabel inherits from swing's Component class, you can add a MouseListener (or MouseAdapter) to each of your clickable labels. Using this EventListener you can find the clicked label like this:
JLabel l = new JLabel();
l.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
JLabel clickedLabel = (JLabel) e.getComponent();
}
});
In order to get the index of the clicked label within the ArrayList, use the indexOf(Object) method provided by the ArrayList:
int index = list.indexOf(clickedLabel);

Java jFrame canvas draws dots instead of lines

I've been wanting to design a generator for dragon curves.
(If you want info on that check this out, but it doesn't really matter for the issue)
A dragon curve is a repeating mathematical construct.
I've already written a generator for what the canvas should draw, it works by returning a char array consisting of 'r' or 'l', saying whether the line has to turn left or right next. In the code here, it's the method input(). This part works perfectly.
The problem is that whenever I want to draw it on the canvas (using drawLine), it only draws the first two lines as actual lines, the rest are just dots.
The dots are on the right positions and if you make the thing really big, you can't tell the difference anymore, but nevertheless, there are supposed to be lines there.
Image:
This is the code I used:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
*
* Description
*
* #version 1.0 from 4/20/2016
* #author
*/
public class CurveGen extends JFrame {
// start attributes
private Canvas display = new Canvas();
private JButton startButton = new JButton();
private JLabel jLabel1 = new JLabel();
private JTextArea outText = new JTextArea("");
private JScrollPane outTextScrollPane = new JScrollPane(outText);
private JLabel jLabel2 = new JLabel();
private JSlider xSlider = new JSlider();
private JSlider ySlider = new JSlider();
private JNumberField iterationsNF = new JNumberField();
private JNumberField sizeNF = new JNumberField();
// end attributes
public CurveGen(String title) {
// Frame-Init
super(title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 1022;
int frameHeight = 731;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
// start components
display.setBounds(16, 64, 601, 601);
cp.add(display);
startButton.setBounds(736, 464, 241, 129);
startButton.setText("START!");
startButton.setMargin(new Insets(2, 2, 2, 2));
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
startButton_ActionPerformed(evt);
}
});
startButton.setFont(new Font("Dialog", Font.BOLD, 36));
cp.add(startButton);
jLabel1.setBounds(760, 96, 75, 41);
jLabel1.setText("Iterations:");
cp.add(jLabel1);
outTextScrollPane.setBounds(728, 392, 257, 57);
cp.add(outTextScrollPane);
jLabel2.setBounds(768, 144, 67, 41);
jLabel2.setText("Size:");
cp.add(jLabel2);
xSlider.setBounds(0, 8, 633, 49);
xSlider.setMinorTickSpacing(25);
xSlider.setMajorTickSpacing(100);
xSlider.setPaintTicks(true);
xSlider.setPaintLabels(true);
xSlider.setToolTipText("Starting point y-coordinate");
xSlider.setMaximum(600);
xSlider.setValue(300);
cp.add(xSlider);
ySlider.setBounds(624, 56, 65, 625);
ySlider.setMinorTickSpacing(25);
ySlider.setMajorTickSpacing(100);
ySlider.setPaintTicks(true);
ySlider.setPaintLabels(true);
ySlider.setOrientation(SwingConstants.VERTICAL);
ySlider.setMaximum(600);
ySlider.setInverted(true);
ySlider.setValue(300);
ySlider.setToolTipText("Starting point x-coordinate");
cp.add(ySlider);
iterationsNF.setBounds(856, 96, 81, 41);
iterationsNF.setText("");
cp.add(iterationsNF);
sizeNF.setBounds(856, 144, 81, 41);
sizeNF.setText("");
cp.add(sizeNF);
// end components
setVisible(true);
} // end of public CurveGen
// start methods
public static void main(String[] args) {
new CurveGen("CurveGen");
} // end of main
public char[] input(int iter) {
char oldOut[] = new char[0];
for (int i=1;i<=iter;i++) {
char newOut[] = new char[((int)Math.pow(2, i))-1];
for (int n=0;n<oldOut.length;n++) {
newOut[n] = oldOut[n];
if (oldOut[n]=='r') {
newOut[newOut.length-n-1] = 'l';
}
if (oldOut[n]=='l') {
newOut[newOut.length-n-1] = 'r';
} // end of if
} // end of for
newOut[oldOut.length]='l';
oldOut = newOut;
} // end of for
return oldOut;
}
public void startButton_ActionPerformed(ActionEvent evt) {
int iterations = iterationsNF.getInt();
int size = sizeNF.getInt();
char com[] = input(iterations);
outText.setText(String.valueOf(com));
int dir = 0;
int newDir = 0;
int lastPos[] = {xSlider.getValue(),ySlider.getValue()-size};
int newPos[] = {0,0};
Graphics g = display.getGraphics();
g.clearRect(0,0,601,601);
g.drawLine(xSlider.getValue(),ySlider.getValue(),xSlider.getValue(),ySlider.getValue()-size);
for (int i=0;i<=com.length-1;i++) {
dir = newDir;
if (dir==0) {
if (com[i]=='l') {
newPos[0] = lastPos[0]-size;
newPos[1] = lastPos[1];
newDir = 3;
}
if (com[i]=='r') {
newPos[0] = lastPos[0]+size;
newPos[1] = lastPos[1];
newDir = 1;
}
}
if (dir==1) {
if (com[i]=='l') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]-size;
newDir = 0;
}
if (com[i]=='r') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]+size;
newDir = 2;
}
}
if (dir==2) {
if (com[i]=='l') {
newPos[0] = lastPos[0]+size;
newPos[1] = lastPos[1];
newDir = 1;
}
if (com[i]=='r') {
newPos[0] = lastPos[0]-size;
newPos[1] = lastPos[1];
newDir = 3;
}
}
if (dir==3) {
if (com[i]=='l') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]+size;
newDir = 2;
}
if (com[i]=='r') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]-size;
newDir = 0;
}
}
g.drawLine(lastPos[0],lastPos[1],newPos[0],newPos[1]);
lastPos=newPos;
} // end of for
} // end of startButton_ActionPerformed
// end methods
} // end of class CurveGen
Okay, so I've gone back over the code...
Mixing heavyweight (java.awt.Canvas) and lightweight (Swing) components is unadvisable as they can cause or sorts of painting issues
getGraphics is not how paint should be done. Instead, I'd start with a custom JPanel and override its paintComponent. See Painting in AWT and Swing and Performing Custom Painting for more details
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
I believe the problem is associated with this...
lastPos=newPos;
All you are doing is making lastPos point to the same place in memory as newPos, so when you assign values to newPos, lastPos will have the same values, hence the reason you're seeing dots.
What I would do first, is separate the responsible for the generation of the data from the display.
I'd start with some kind of model (note, you could create a model which took iterations instead and which generated the data itself, but I was focusing on solving the initial problem)
public class DragonModel {
private Point startPoint;
private int size;
private char[] values;
public DragonModel(Point startPoint, int size, char[] values) {
this.startPoint = startPoint;
this.size = size;
this.values = values;
}
public Point getStartPoint() {
return startPoint;
}
public int getSize() {
return size;
}
public char[] getValues() {
return values;
}
}
and then the display...
public class DragonPane extends JPanel {
private DragonModel model;
public void setModel(DragonModel model) {
this.model = model;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (model != null) {
Graphics2D g2d = (Graphics2D) g.create();
int size = model.getSize();
int dir = 0;
int newDir = 0;
Point lastPos = model.getStartPoint();
Point newPos = new Point(0, 0);
for (char value : model.values) {
if (dir == 0) {
if (value == 'l') {
newPos.x = lastPos.x - size;
newPos.y = lastPos.y;
newDir = 3;
}
if (value == 'r') {
newPos.x = lastPos.x + size;
newPos.y = lastPos.y;
newDir = 1;
}
}
if (dir == 1) {
if (value == 'l') {
newPos.x = lastPos.x;
newPos.y = lastPos.y - size;
newDir = 0;
}
if (value == 'r') {
newPos.x = lastPos.x;
newPos.y = lastPos.y + size;
newDir = 2;
}
}
if (dir == 2) {
if (value == 'l') {
newPos.x = lastPos.x + size;
newPos.y = lastPos.y;
newDir = 1;
}
if (value == 'r') {
newPos.x = lastPos.x - size;
newPos.y = lastPos.y;
newDir = 3;
}
}
if (dir == 3) {
if (value == 'l') {
newPos.x = lastPos.x;
newPos.y = lastPos.y + size;
newDir = 2;
}
if (value == 'r') {
newPos.x = lastPos.x;
newPos.y = lastPos.y - size;
newDir = 0;
}
}
g.drawLine(lastPos.x, lastPos.y, newPos.x, newPos.y);
dir = newDir;
lastPos = new Point(newPos);
}
}
}
}
The idea here is to try and decouple of the responsibility a little, the responsibility for the generation and displaying of the data sit firmly in two different areas.
Then in your actionPerformed method you could simply do...
public void startButton_ActionPerformed(ActionEvent evt) {
int iterations = Integer.parseInt(iterationsNF.getText());
int size = Integer.parseInt(sizeNF.getText());
char com[] = input(iterations);
outText.setText(String.valueOf(com));
DragonModel model = new DragonModel(new Point(xSlider.getValue(), ySlider.getValue()), size, com);
display.setModel(model);
} // end of startButton_ActionPerformed
which could result in something like...
The drawing code should be inside the paint(Graphics) method to synchronize with the rendering loop properly. In an event handler, update the data model of the component (calculate the lines and keep them in a data structure inside the component), then call the method repaint() to trigger the event rendering loop, which will call your paint method.
There are some other variations of this, but the general idea is that you change the data and then request rendering. The rendering engine may call your paint method in other cases as well, not only when you change the data, so ideally paint() has all the data it needs to render fast, meaning it should not do calculations or heavy operations other than rendering on the Graphics object.
This means that you have to subclass JComponent in a new class, and implement paint inside it. This class should have an internal data structure with the lines ready to render at any point in time. Then use your new class in the JFrame.

Update new position for Jlabel

I'm new to Java and I am having some trouble with my assignment.
I have a Panel containing 100 JLabels:
for(int i=0;i<100;i++)
{
num[i] = new JLabel(""+i, JLabel.CENTER);
mainPanel.add(num[i]);
}
And a button to set image icon for the label when clicked
public void actionPerformed(ActionEvent ae)
{
int a = ran.nextInt(6) +1;//random number
int b +=a;
if(b>=100)
{
b=99;
num[b].setIcon(icon);
}
else
{
num[b].setIcon(icon);
}
}
How can i remove the icon from the last position and update it to a new position?
You can try to remember the index of the array of the label, for which you tried to set the icon.
For example-
int b = 0; // make b an instance variable
public void actionPerformed(ActionEvent ae)
{
int a = ran.nextInt(6) +1;//random number
num[b].setIcon(null); //remove the icon from from previously set label
b=a; //since b already has some value, b+=a might create unexpected result, hence just assigned a
if(b>=100)
{
b=99;
num[b].setIcon(icon);
}
else
{
num[b].setIcon(icon);
}
}

Java: Calling a class within a for loop

I've just started learning Java, so I apologize if this question is somewhat basic, and I'm sure my code is not as clean as it could be. I've been trying to write a small quiz program that will input a list of German verbs from a txt file (verblist.txt). Each line of the text file contains five strings: the German verb (verbger), the English translation (verbeng), the praeteritum and perfekt conjugations conjugations (verbprae and verbperf) and whether it uses haben or sein as the auxiliary verb (H or S, stored as verbhaben). The verb set is chosen by generating a random number and selecting the "row" of the two dimensional array. The GUI then displays the first two variables, and the user has to input the last three. If the last three match the values in the txt file, the user gets it correct and moves on to another verb.
I'm at the point where the code is working the way I want it to - for one verb. The way I've been organizing it is in two classes. One, VerbTable, imports the text file as a two dimensional array, and the other, RunVerb, generates the GUI and uses an ActionListener to compare the user input to the array. What I can't figure out now is how, after the user gets one verb set correct, I can then loop through the entire set of verbs.
I was thinking of creating a for loop that loops through the number of rows in the text file (saved in the code as height), generating a new random number each time to select a different verb set (or "row" in the two dimensional array.) Essentially, I'd like to get a loop to run through the entire VerbRun class, and pause for the ActionListener, until all of the verb sets have been displayed.
Here is the VerbTable class, which generates the array and random number to select the row:
package looptest;
import java.io.*;
import java.util.*;
public class VerbTable {
public int width;
public int height;
public int randnum;
public String verbger = new String("");
public String verbeng = new String("");
public String verbprae = new String("");
public String verbperf = new String("");
public String verbhaben = new String("");
public VerbTable() {
File file = new File("verblist.txt");
try {
/* For array height and width */
Scanner scanner1 = new Scanner(file).useDelimiter("\n");
int height = 0;
int width = 0;
while (scanner1.hasNextLine()) {
String line = scanner1.nextLine();
height++;
String[] line3 = line.split("\t");
width = line3.length;
}
System.out.println("Height: " + height);
System.out.println("Width: " + width);
this.width = width;
this.height = height;
/* Array height/width end */
/* random number generator */
int randnum1 = 1 + (int)(Math.random() * (height-1));
this.randnum = randnum1;
/* random number generator end */
Scanner scanner = new Scanner(file).useDelimiter("\n");
String verbtable[][];
verbtable = new String[width][height];
int j = 0;
while (scanner.hasNextLine()){
String verblist2 = scanner.next();
String[] verblist1 = verblist2.split("\t");
System.out.println(verblist2);
verbtable[0][j] = verblist1[0];
verbtable[1][j] = verblist1[1];
verbtable[2][j] = verblist1[2];
verbtable[3][j] = verblist1[3];
verbtable[4][j] = verblist1[4];
j++;
}
this.verbger = verbtable[0][randnum];
this.verbeng = verbtable[1][randnum];
this.verbprae = verbtable[2][randnum];
this.verbperf = verbtable[3][randnum];
this.verbhaben = verbtable[4][randnum];
}
catch (FileNotFoundException e){
e.printStackTrace();
}
}
public int getRand(){
return this.randnum;
}
public int getWidth(){
return this.width;
}
public int getHeight(){
return this.height;
}
public String getVerbger(){
return this.verbger;
}
public String getVerbeng(){
return this.verbeng;
}
public String getVerbprae(){
return this.verbprae;
}
public String getVerbperf(){
return this.verbperf;
}
public String getVerbhaben(){
return this.verbhaben;
}
public static void main(String[] args) throws IOException {
}
}
And here is the RunVerb class:
package looptest;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class RunVerb extends JFrame {
VerbTable dimensions = new VerbTable();
int width = dimensions.getWidth();
int height = dimensions.getHeight();
int randnum = dimensions.getRand();
String verbgerin = dimensions.getVerbger();
String verbengin = dimensions.getVerbeng();
String verbpraein = dimensions.getVerbprae();
String verbperfin = dimensions.getVerbperf();
String verbhabenin = dimensions.getVerbhaben();
String HabenSeinSelect = new String("");
public JTextField prae = new JTextField("",8);
public JTextField perf = new JTextField("",8);
public JLabel verbger = new JLabel(verbgerin);
public JLabel verbeng = new JLabel(verbengin);
public JRadioButton haben = new JRadioButton("Haben");
public JRadioButton sein = new JRadioButton("Sein");
public RunVerb() {
JButton enter = new JButton("Enter");
enter.addActionListener(new ConvertBtnListener());
prae.addActionListener(new ConvertBtnListener());
perf.addActionListener(new ConvertBtnListener());
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(verbger);
verbger.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
content.add(verbeng);
verbeng.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 40));
content.add(new JLabel("Praeteritum:"));
content.add(prae);
content.add(new JLabel("Perfekt:"));
content.add(perf);
content.add(haben);
haben.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 10));
haben.setSelected(true);
content.add(sein);
sein.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
ButtonGroup bg = new ButtonGroup();
bg.add(haben);
bg.add(sein);
content.add(enter);
setContentPane(content);
pack();
setTitle("Verben");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
class ConvertBtnListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String outprae = prae.getText();
int praenum = 0;
if (outprae.equals(verbpraein)){
praenum = 1;
}
String outperf = perf.getText();
int perfnum = 0;
if (outperf.equals(verbperfin)){
perfnum = 1;
}
boolean habenselect = haben.isSelected();
boolean seinselect = sein.isSelected();
if (habenselect == true){
HabenSeinSelect = "H";
}
else {
HabenSeinSelect = "S";
}
int habennum = 0;
if (HabenSeinSelect.equals(verbhabenin)) {
habennum = 1;
}
int numtot = praenum + perfnum + habennum;
if (numtot == 3){
System.out.println("Correct.");
}
else{
System.out.println("Incorrect.");
}
numtot = 0;
}
}
public static void main(String[] args) {
window.setVisible(true);
}
}
So what would be the best way to cycle through the entire verbtable array until all of the rows have been displayed? Should I create a for loop, and if so, where should it go? Should I make a new class that contains the loop and references the VerbRun class? If so, what would be the best way to go about it?
I hope this makes sense! Thank you!
To go through all the verbs exactly in a random order, you may not want to generate random numbers each time, as the random number can repeat. You have to create a random permutation of verbs, one way to do it is Collections.shuffle
see http://download.oracle.com/javase/6/docs/api/java/util/Collections.html
Also You dont have to create a new RunVerb Object, instead create once, and use setters to change the UI, and the functionality of Action Listeners. So pseudo code would be
Collections.shuffle(verbsList);
for(verb : verbsList)
{
setLabel1(verb[0]);
setLabel2(verb[1]);...
}
I would have a method like getNextRandomVerb() in then VerbTable class that generates the next verb to be shown. It will keep track of the verbs that have been shown ( for a given user-session ofcourse ) already and ensure the next one picked is not a repeat. Your RunVerb class seems to more responsible for managing the GUI , so this is not the place to define how to get the next verb to display.

Categories