java update Jpanel component - java

I am using a Custome jPanel in my Gui Builder JFram Class A, the problem i am facing is to update the components (Lable) in my JPanel when I click button in JFrame.here is the button in Gui Builder JFrame ClassA: it changes the color of Jpl and also remove all the labels but not update the new labels.
private void btnShowActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Random randomGenerator = new Random();
for (int idx = 1; idx <= 10; ++idx) {
q = randomGenerator.nextInt(100);
}
jpl1.removeAll();
new Jpl().printMe(ClassA.q);
jpl1.revalidate();
jpl1.setBackground(Color.BLUE);
jpl1.repaint();
}
here is Jpl class that is used as a custome component in GuiBuilder JFrame Class A.
public class Jpl extends JPanel {
public Jpl() {
printMe(ClassA.q);
}
public void printMe(int q) {
for (int i = 0; i <q; i++) {
System.out.println(i+"rinting lable");
String htmlLabel = "<html><font color=\"#A01070\">" + i + " New Lable </font></html>";
JLabel lbl = new JLabel(htmlLabel);
setLayout(new GridLayout(0, 1));
add(lbl, Jpl.RIGHT_ALIGNMENT);
lbl.setForeground(Color.BLUE);
Border border = BorderFactory.createLineBorder(Color.lightGray);
lbl.setBorder(border);
lbl.add(new JSeparator(SwingConstants.HORIZONTAL));
lbl.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel) e.getSource();
JOptionPane.showMessageDialog(null, "You Slected");
System.out.println(label.getText() + "NO AKKA is Selected");
}
});
}
}

You are calling printMe() on a new instance of Jpl, try that:
private void btnShowActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Random randomGenerator = new Random();
for (int idx = 1; idx <= 10; ++idx) {
q = randomGenerator.nextInt(100);
}
jpl1.removeAll();
jpl1.printMe(ClassA.q); // HERE - REMOVED new and using jpl1 instance
jpl1.setBackground(Color.BLUE);
jpl1.revalidate();
jpl1.repaint();
}
In don't understand why you loop 10 times for your random number. Only the last result will be kept, maybe a you wanted to use q += randomGenerator.nextInt(100);. Also, ClassA.q should be replaced by q if it's the same variable.

Related

need help accessing variable inside inner class for loop

I am having problem accessing the variable int i inside the inner class
Code:
public class OnColumnSelectPanel {
JFrame jFrame;
JPanel mainJPanel;
//JPanel jPanel1;
//JTextField jTextField;
//JButton jButton;
//JComboBox jComboBox [];
MigLayout layout;
MigLayout frameLayout;
//column names
ColumnNames cn = new ColumnNames();
List<String> listedColumnNames = cn.getColumnNames();
String columnNames[] = listedColumnNames.toArray(new String[0]);
public OnColumnSelectPanel(int n) {
//jPanel1 = new JPanel();
jFrame = new JFrame("Create Structure of Columns");
// mainJPanel = new JPanel();
layout = new MigLayout("flowy", "[center]rel[grow]", "[]10[]");
frameLayout = new MigLayout("flowx", "[center]rel[grow]", "[]10[]");
//mainJPanel.setLayout(new BoxLayout(mainJPanel, BoxLayout.X_AXIS));
//MigLayout mainJPanelLayout = new MigLayout("flowy", "[]rel[grow]", "[]5[]");
// declare & initialize array
JPanel jPanel[] = new JPanel[n];
JComboBox jComboBox[] = new JComboBox[n];
JButton jButton[] = new JButton[n];
final int num = 0;
for (int i = 0; i < n; i++) {
//assign array
jComboBox[i] = new JComboBox(columnNames);
jButton[i] = new JButton("add Sub Heading");
jPanel[i] = new JPanel();
System.out.println("Loop number: " + i);
jButton[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
for (int j = 0; j < n; j++) {
if (j <= n) {
jComboBox[j] = new JComboBox(columnNames);
jPanel[j].add(jComboBox[j]);
jFrame.revalidate();
} else {
JOptionPane.showMessageDialog(null, "You have exceeded your limit");
}
}
}
});
//set layout
jPanel[i].setLayout(layout);
//jPanel[i].setPreferredSize(new Dimension(50, 400));
//mainJPanel.setLayout(mainJPanelLayout);
jFrame.setLayout(frameLayout);
System.out.println(" height " + jPanel[i].getHeight());
jPanel[i].add(jComboBox[i], new CC().newline());
//jPanel.add(jTextField);
jPanel[i].add(jButton[i]);
//mainJPanel.add(jPanel[i], "spany");
jPanel[i].repaint();
jFrame.add(jPanel[i]);
jFrame.pack();
jPanel[i].revalidate();
jFrame.revalidate();
//mainJPanel.revalidate();
//jFrame.revalidate();
}
//mainJPanel.setSize(600, 400);
//jFrame.add(jPanel1);
jFrame.setVisible(true);
jFrame.setSize(600, 400);
jFrame.setAlwaysOnTop(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Output Frame
As you can see the output image. The problem here is that when i click on the add subheading button, combobox is added to every jpanel. this is because i can;t pass the value i to the inner class.
It would be interesting to know possible solutions for this.
FYI I am using Mig Layout.
Thanks in advance.
Only effectively final variables can be accessed from anonymous classes.
i is modified by the loop, so it is not effectively final.
A workaround would look like this:
for (int i = 0; i < n; i++) {
...
final int effectivelyFinal = i;
jButton[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
...
// use effectivelyFinal instead of i
});
}
But as other suggested, it would be way better to extract the anonymous class into a real class and pass all required parameters using the constructor. This can look like this:
class MyListener implements ActionListener {
private final int index;
// add more fields for other required parameters
public MyListener(int index) {
this.index = index;
}
#Override
public void actionPerformed(ActionEvent e) {
// use index
}
}
Usage:
jButton[i].addActionListener(new MyListener(i));

Calling an actionlistener from another class or somehow order the multiple actionlisteners that are placed on one button?

For my tic tac toe project, I am have an actionlistener for the buttons in my TTTBoard Class which updates the score when a player has won and an actionlistener in GUI which updates the scoreboard to show the scores.
However when I run the code, the actionlistener for GUI seems to go before the actionlistener for the TTTBoard. So what happens is that I am always one click behind.
Here is what it looks like on console
enter image description here
Here is a part of my TTTBoard Code
public class TTTBoard extends JPanel implements ActionListener
{
private TTTSquare[][] square;
private ScoreBoard gameScore;
private Random generator = new Random();
private int turn = 0;
private int a = 0;
private int p = 0;
public TTTBoard(ScoreBoard sb)
{
super(new GridLayout(3,3));
square = new TTTSquare[3][3];
for(int r = 0; r < 3; r++)
{
for(int c = 0; c < 3; c++)
{
square[r][c] = new TTTSquare();
add(square[r][c]);
square[r][c].addActionListener(this);
}
}
gameScore = sb;
}
public void actionPerformed(ActionEvent e)
{
gameScore = new ScoreBoard();
TTTSquare btn = (TTTSquare)e.getSource();
btn.clicked();
turn++;
if(winningMove(1))
{
a++;
gameScore.setPlayer(a);
}
else
{
if(turn < 5)
{
computersTurn();
if(winningMove(2))
{
p++;
gameScore.setComputer(p);
}
}
else
{
}
}
System.out.println("GameScore From Loop "+gameScore.getPlayer()+" , "+gameScore.getComputer());
System.out.println();
gameScore.update();
}
}
Here is my GUI code
public class GUI extends JFrame
{
private TTTBoard board;
private ScoreBoard score;
private JButton btnGame;
private JButton btnReset;
public GUI()
{
super();
setLayout(new BorderLayout());
JPanel pnlSouth = new JPanel();
score = new ScoreBoard();
pnlSouth.add(score);
board = new TTTBoard(score);
add(board,BorderLayout.CENTER);
for(int r = 0; r < 3; r++)
{
for(int c = 0; c < 3; c++)
{
board.getSquare(r,c).addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("GameScore From GUI "+board.getGameScore().getPlayer()+" , "+board.getGameScore().getComputer());
score.setPlayer(board.getGameScore().getPlayer());
score.setComputer(board.getGameScore().getComputer());
}
}
);
}
}
}
}
I could only think of two ways to solve this problem and that is either by somehow ordering the two action events that occur on the button so that the action event from the TTTBoard goes before that in the GUI
Or by calling the actionlistener from TTTBoard in the GUI Class maybe like something at the bottom:
for(int r = 0; r < 3; r++)
{
for(int c = 0; c < 3; c++)
{
board.getSquare(r,c).addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
/*
for(int r = 0; r < 3; r++)
{
for(int c = 0; c < 3; c++)
{
board.getSquare(r,c).addActionListener(SOMEHOW CALL ACTIONLISTENER FROM ANOTHER CLASS);
}
}
*/
System.out.println("GameScore From GUI "+board.getGameScore().getPlayer()+" , "+board.getGameScore().getComputer());
score.setPlayer(board.getGameScore().getPlayer());
score.setComputer(board.getGameScore().getComputer());
}
}
);
}
}
I guess my last resort is to bring the huge chunk of code from TTTBoard Class to GUI and see if it works then, but I really do not want to do that. Any help, advise, suggestions is needed and welcomed.
Thank you so much

Paint Method in an Applet (Sort Algorithms in Java)

I have two classes: One applet for the GUI and one class to sort numbers.
Sort Class:
public class Sortierung {
public int[] Zahlen = {5,2,3,1,4};
int z;
public static int zufallszahl (int z){
int dauer = ((int)(Math.random()*z))+1;
return dauer;
}
public void ArrayErstellen(int l){
int[] myIntArray = new int[l];
for(int f=0;f<myIntArray.length;f++){
myIntArray[f]=zufallszahl(10);
}
Zahlen=myIntArray;
}
public int[] BubbleSort() {
for(int p=0;p<Zahlen.length-1;p++){
for(int i=0;i<Zahlen.length-1;i++){
if(Zahlen[i]<Zahlen[i+1]){
continue; //beendet den derzeitigen Schleifenablauf
}
else{
z=Zahlen[i];
Zahlen[i]=Zahlen[i+1];
Zahlen[i+1]=z;
}
}
}
return Zahlen;
}
public int[] InsertionSort() {
int f = 0; //Variable 1
int j = 0; //Variable 2
for(int i = 1;i < Zahlen.length;i++){
j = i;
while((j>0)&&(Zahlen[j-1]>Zahlen[j])){
f = Zahlen[j-1];
Zahlen[j-1] = Zahlen[j];
Zahlen[j] = f;
j--;
}
}
return Zahlen;
}
public int[] SelectionSort(){
for (int i = 0; i < Zahlen.length - 1; i++){
int s = i; //Neue Variable für die Schleife
for (int j = i + 1; j < Zahlen.length; j++)
if (Zahlen[j] < Zahlen[s]){
s = j;
}
int smallerNumber = Zahlen[s];
Zahlen[s] =Zahlen[i];
Zahlen[i] = smallerNumber;
}
return Zahlen;
}
public void ArrayWiedergeben(int[] eimer){
for(int u=0;u<eimer.length;u++){
System.out.println(eimer[u]);
}
} }
Gui (Applet):
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Gui extends JApplet {
JTextField tf;
JButton b;
JButton k;
JLabel s;
JLabel u;
int anzahl;
int test = 0;
JPanel p = new JPanel();
JPanel h = new JPanel();
JPanel f = new JPanel();
Sortierung neu = new Sortierung();
Choice Sortierungsmethode = new Choice();
ActionListener startOhr = new ActionListener() {
public void actionPerformed(ActionEvent e) {
anzahl = Integer.parseInt(tf.getText());
if (anzahl > 100) {
tf.setText("Wert zu hoch.");
return;
}
neu.ArrayErstellen(anzahl);
tf.setText("Array[" + anzahl + "] erstellt.");
}
};
ActionListener sortOhr = new ActionListener() {
public void actionPerformed(ActionEvent e) {
switch (Sortierungsmethode.getSelectedIndex()) {
case 0:
int[] eimer = neu.BubbleSort();
neu.ArrayWiedergeben(eimer);
test = 1;
repaint();
break;
case 1:
int[] eimer2 = neu.InsertionSort();
neu.ArrayWiedergeben(eimer2);
break;
case 2:
int[] eimer3 = neu.SelectionSort();
neu.ArrayWiedergeben(eimer3);
break;
default:
break;
}
}
};
public void init() {
tf = new JTextField(8);
b = new JButton("Erstellen");
k = new JButton("Bestätigen");
s = new JLabel("Array Länge");
u = new JLabel("Sortmethode");
Sortierungsmethode.add("Bubblesort");
Sortierungsmethode.add("Insertionsort");
Sortierungsmethode.add("Selectionsort");
setLayout(new BorderLayout());
p.add(s);
p.add(tf);
p.add(b);
h.add(u);
h.add(Sortierungsmethode);
h.add(k);
this.add(p, BorderLayout.NORTH);
this.add(h, BorderLayout.CENTER);
this.add(f, BorderLayout.SOUTH);
b.addActionListener(startOhr);
k.addActionListener(sortOhr);
}
}
My intention is to draw the sorted array in a coordinate system with a paint
method. The problem is, that when I try to create a paint method, the whole screen is white and I cant see anything
You need to address several details:
You should create a class which overrides JPanel to do your custom drawing. You can create an instance of the class in your Gui class.
You should override paintComponet() rather than paint().
The first line in paintComponent(Graphics g) should be super.paintComponent(g) in order to ensure that the super class can paint itself.
You need to be careful that your sorting algorithm doesn't take over the main thread. This will cause your app to freeze and nothing will paint until the sorting has finished.
You need to create a Thread object and set it to call run method 30 times per second. In this method, call repaint() method of main JPanel.

Alert user when all cards are paired

I have this program about memory game that when user pairs all the cards there should be alert that. The user won. However I cannot find ways to identify if all cards are paired up. Can someone help me on this.
public class MemoryGame extends JFrame {
static String files[] = {
"japan.jpg",
"greece.jpg",
"canada.jpg",
"brazil.jpg",
"jamaica.jpg"};
static JButton buttons[];
ImageIcon closedIcon;
int numButtons;
ImageIcon icons[];
Timer myTimer;
int numClicks = 0;
int oddClickIndex = 0;
int currentIndex = 0;
public MemoryGame() {
// Set the title.
setTitle("Memory Game");
// Specify an action for the close button.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create a BorderLayout manager.
setLayout(new GridLayout(2, files.length));
closedIcon = new ImageIcon("closed.JPG");
numButtons = files.length * 2;
buttons = new JButton[numButtons];
icons = new ImageIcon[numButtons];
for (int i = 0, j = 0; i < files.length; i++) {
icons[j] = new ImageIcon(getClass().getResource(files[i]));
buttons[j] = new JButton("");
buttons[j].addActionListener(new ImageButtonListener());
buttons[j].setIcon(closedIcon);
add(buttons[j++]);
icons[j] = icons[j - 1];
buttons[j] = new JButton("");
buttons[j].addActionListener(new ImageButtonListener());
buttons[j].setIcon(closedIcon);
add(buttons[j++]);
}
// randomize icons array
Random gen = new Random();
for (int i = 0; i < numButtons; i++) {
int rand = gen.nextInt(numButtons);
ImageIcon temp = icons[i];
icons[i] = icons[rand];
icons[rand] = temp;
}
setSize(300,200);
setVisible(true);
myTimer = new Timer(1000, new TimerListener());
// myTimer.start();
}
private class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
buttons[currentIndex].setIcon(closedIcon);
buttons[oddClickIndex].setIcon(closedIcon);
myTimer.stop();
}
}
private class ImageButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// we are waiting for timer to pop - no user clicks accepted
if (myTimer.isRunning())
return;
numClicks++;
System.out.println(numClicks);
// which button was clicked?
for (int i = 0; i < numButtons; i++) {
if (e.getSource() == buttons[i]) {
buttons[i].setIcon(icons[i]);
currentIndex = i;
}
}
// check for even click
if (numClicks % 2 == 0) {
// check whether same position is clicked twice!
if (currentIndex == oddClickIndex) {
numClicks--;
return;
}
// are two images matching?
if (icons[currentIndex] != icons[oddClickIndex]) {
// show images for 1 sec, before flipping back
myTimer.start();
}
} else {
// we just record index for odd clicks
oddClickIndex = currentIndex;
}
}
}
public static void main(String[] args) {
new MemoryGame();
}
}
Why not simply increment a counter variable when the icons match, and then checking the value of this variable?
Perhaps here:
if (icons[currentIndex] != icons[oddClickIndex]) {
// show images for 1 sec, before flipping back
myTimer.start();
} else {
pairCounter++;
if (pairCounter >= MAX_PAIRS) {
// NOTIFY USER
// end game
// reset pairCounter
}
}

How can i stop the program from skipping my check the second time around?

I am creating a program to take in sets of binary digits and convert them into hammingcodes (Effectively take in 8 digits, turn into 12, print out) but i am having trouble. Currently, i am using a JTextField for the user to enter their number, then they press a JButton to enter the data. I then do funky shit with that number to put it into a list and confirm that this is the last of the numbers they wish to enter. If they click a JButton called yes (New text in button, but same button) if goes on to do what i need. But if they click the other JButton called no, it goes back and repeats the same process. My problem is after clicking no once, the program stops allowing you to press no at the step to check if you want to add another list of numbers. IT appears to skip the check all together and assume they pressed yes as it does the rest of the working out thats done after all entry is finished.
My code is a tad messy due to messing with it for a few hours.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
public class MainProgram extends JFrame
{
public MainProgram()
{
}
public static void main(String[] args)
{
MainProgram mp = new MainProgram();
mp.run();
}
private void run()
{
java.util.List<Integer> streamSplit = new ArrayList<>();
java.util.List<Integer> tempEight = new ArrayList<>();
java.util.List<Integer> finalStream = new ArrayList<>();
yes.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
checkYes = true;
}
});
no.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
checkNo = true;
}
});
init();
yesChange("Enter");
boolean confirm = false;
int aCheck = 0;
while (aCheck == 0)
{
confirm = false;
while (!confirm)
{
setTopText("<html>Please enter your next 8 bits. Do not enter more than 8 bits.<br> Press Enter when done</html>");
yesChange("Enter");
confirm = checkYes();
}
confirm = false;
setTopText("Digits Successfully added.");
int stream = checkInput();
do
{
streamSplit.add(stream % 10);
stream /= 10;
} while (stream != 0);
setYesNo();
setTopText("<html>Are you finished entering streams?</html>");
yesChange("YES");
noChange("NO");
aCheck = 2;
checkYes();
checkNo();
while (aCheck == 2)
{
if ( checkNo())
{
aCheck = 0;
System.out.println("CrapNo");
}
else if (checkYes())
{
aCheck = 1;
System.out.println("CrapYes");
}
}
}
int arrayLength = streamSplit.size();
int bufferLength = 8 - arrayLength % 8;
int numberOfStreams = 0;
if (bufferLength != 8)
{
numberOfStreams = arrayLength / 8 + 1;
} else
{
numberOfStreams = arrayLength / 8;
}
int tempStreams = numberOfStreams;
System.out.println(numberOfStreams + "<Streams Buffer>" + bufferLength);
while (bufferLength > 0 && bufferLength != 8)
{
streamSplit.add(0);
bufferLength--;
}
while (tempStreams > 0)
{
for (int i = 0; i < 8; i++)
{
tempEight.add(streamSplit.get(i));
}
if ((tempEight.get(0) + tempEight.get(1) + tempEight.get(3) + tempEight.get(4) + tempEight.get(6)) % 2 == 0)
{
tempEight.add(0, 0);
} else
{
tempEight.add(0, 1);
}
if ((tempEight.get(1) + tempEight.get(3) + tempEight.get(5) + tempEight.get(6) + tempEight.get(7)) % 2 == 0)
{
tempEight.add(1, 0);
} else
{
tempEight.add(1, 1);
}
if ((tempEight.get(3) + tempEight.get(4) + tempEight.get(5) + tempEight.get(8) + tempEight.get(9)) % 2 == 0)
{
tempEight.add(3, 0);
} else
{
tempEight.add(3, 1);
}
if ((tempEight.get(7) + tempEight.get(8) + tempEight.get(9) + tempEight.get(10)) % 2 == 0)
{
tempEight.add(7, 0);
} else
{
tempEight.add(7, 1);
}
tempStreams--;
for (int i = 0; i < 12; i++)
{
finalStream.add(tempEight.get(0));
tempEight.remove(0);
}
}
Collections.reverse(streamSplit);
System.out.print("Your original bit-stream was: ");
for (int i = 0; i < numberOfStreams * 2; i++)
{
for (int j = 0; j < 4; j++)
{
System.out.print(streamSplit.get(j + (i * 4)));
}
System.out.print(" ");
}
System.out.println();
System.out.print("Your new HammingCode bit-stream is: ");
for (int i = 0; i < numberOfStreams * 3; i++)
{
for (int j = 0; j < 4; j++)
{
System.out.print(finalStream.get(j + (i * 4)));
}
System.out.print(" ");
}
System.out.println();
}
public Boolean checkYes = false;
public Boolean checkNo = false;
private JFrame frame = new JFrame("Absolute Layout Example");
private JPanel contentPane = new JPanel();
private JLabel topText = new JLabel("Welcome to my Hamming Code Generator", JLabel.CENTER);
private JTextField inputText = new JTextField();
private JButton yes = new JButton("YES");
private JButton no = new JButton("NO");
public void init()
{
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane.setOpaque(true);
contentPane.setBackground(Color.WHITE);
contentPane.setLayout(null);
topText.setLocation(0, 0);
topText.setSize(400, 50);
topText.setBorder(BorderFactory.createLineBorder(Color.black));
inputText.setLocation(0,50);
inputText.setSize(400,75);
inputText.setBorder(BorderFactory.createLineBorder(Color.black));
yes.setSize(80, 40);
yes.setLocation(60, 135);
no.setSize(80, 40);
no.setLocation(260, 135);
contentPane.add(topText);
contentPane.add(inputText);
contentPane.add(yes);
contentPane.add(no);
frame.setContentPane(contentPane);
frame.setSize(400, 225);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public void setTopText(String s)
{
topText.setText(s);
}
public void setYesNo()
{
checkYes = false;
checkNo = false;
}
public Boolean checkYes() {return checkYes;}
public Boolean checkNo() {return checkNo;}
public int checkInput()
{
String temp1 = inputText.getText();
int temp = Integer.parseInt(temp1);
return temp;
}
public void yesChange(String s)
{
yes.setText(s);
}
public void noChange(String s)
{
no.setText(s);
}
}
I find it tough to answer this question not fully knowing what your code is doing, especially the part where you "... do funky #### with that number..."
But I do know that you have significant issues with your program structure, especially within your lengthy run() method where you have numerous nested while (...) loops and do-while loops, code constructs that might seem at home within a linear processing console program but which seems out of place within an event-driven Swing GUI.
What I suggest that you do is try to use some state-dependent coding. For instance, you could give your class the boolean variables, enteringData and dataValidYet, to represent two key states: whether the user is now entering data into the JTextField, and whether that data has yet been validated yet. And then within your JButton ActionListeners, use if and if/else blocks to decide what to do on button push depending on the state of these boolean fields, and likely other key fields of the class.
For a code "skeleton" example, one that doesn't yet do anything, but hopefully will show you the structure I'm talking about:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class StateMachine extends JPanel {
private static final String INITIAL_TITLE = "Please enter your next 8 bits. "
+ "Do not enter more than 8 bits.\n"
+ "Press Enter when done";
private static final String ARE_YOU_FINISHED = "Are you finished entering streams?";
private static final String YES = "Yes";
private static final String ENTER = "Enter";
private static final String NO = "No";
private static int GAP = 8;
private static final int COLUMNS = 30;
// this is a JTextArea built to look like a JLabel
private JTextArea topTextArea = new JTextArea(2, COLUMNS);
private JTextField dataEntryField = new JTextField(COLUMNS);
private JButton yesEnterButton = new JButton(ENTER);
private JButton noButton = new JButton(NO);
private boolean enteringData = true;
private boolean dataValidYet = false;
public StateMachine() {
yesEnterButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yesEnterButtonActionPerfromed(e);
}
});
noButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
noButtonActionPerfromed(e);
}
});
topTextArea.setWrapStyleWord(true);
topTextArea.setLineWrap(true);
topTextArea.setFocusable(false);
topTextArea.setEditable(false);
topTextArea.setOpaque(false);
topTextArea.setText(INITIAL_TITLE);
JPanel innerButtonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
innerButtonPanel.add(yesEnterButton);
innerButtonPanel.add(noButton);
JPanel outerButtonPanel = new JPanel();
outerButtonPanel.add(innerButtonPanel);
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(topTextArea, BorderLayout.PAGE_START);
add(dataEntryField, BorderLayout.CENTER);
add(outerButtonPanel, BorderLayout.PAGE_END);
}
protected void noButtonActionPerfromed(ActionEvent e) {
// TODO depending on state of enteringData and dataValidYet booleans
// change text in buttons, do things with JTextField data
// set state of enteringData and dataValidYet booleans
if (enteringData) {
// a no press is meaningless if entering data
return;
}
// .... more
}
private void yesEnterButtonActionPerfromed(ActionEvent e) {
// TODO depending on state of enteringData and dataValidYet booleans
// change text in buttons, do things with JTextField data
// set state of enteringData and dataValidYet booleans
if (enteringData) {
topTextArea.setText(ARE_YOU_FINISHED);
yesEnterButton.setText(YES);
yesEnterButton.setActionCommand(YES);
enteringData = false;
return;
}
// .... more
}
private static void createAndShowGui() {
StateMachine mainPanel = new StateMachine();
JFrame frame = new JFrame("State Machine");
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();
}
});
}
}
Also, as a "side" recommendation, one unrelated to your main problem, understand that null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Note that if this were my program, I would use more indirection including creating separate classes to separate out the GUI portion of the program from the logic portion.

Categories