Undo and redo methods for awt `Graphics` objects - java

I' making this simple paintbrush-type paint toolbox (some interesting ideas in my previous question)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MainClass2{
static JLabel colorlabel = new JLabel(" Color ");
public static JLabel xlab = new JLabel("0");
public static JLabel ylab = new JLabel("0");
static JFrame frame1 = new JFrame();
static JButton quitbutton = new JButton("Quit");
static JButton infobutton = new JButton("Info");
static JButton clearbutton = new JButton("Clear");
static JButton savebutton = new JButton("Save");
private static int stroke1 = 4;
static SpinnerNumberModel spinnervals = new SpinnerNumberModel(stroke1,1,15,1);
static JSpinner spinnerbrush = new JSpinner(spinnervals);
static JButton selectcolor = new JButton("Select Color");
static JButton selectbg = new JButton("Select Background");
public static Color col1 = Color.WHITE;
private static Color col2 = Color.WHITE;
static AuxClass4 panel1 = new AuxClass4(col1, col2, stroke1);
static JPanel panel2 = new JPanel();
static JPanel panel3 = new JPanel();
static JPanel panel4 = new JPanel();
private static void addPanel1(){
panel1.setPreferredSize(new Dimension(800,500));
}
private static void addPanel2(){
ButtonAction inst1 = new ButtonAction();
xlab.setMinimumSize(new Dimension(30,30));
ylab.setMinimumSize(new Dimension(30,30));
xlab.setBorder(BorderFactory.createLineBorder(Color.BLACK));
ylab.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel2.add(new JLabel(" X: "));
panel2.add(xlab);
panel2.add(new JLabel(" Y: "));
panel2.add(ylab);
panel2.add(savebutton);
panel2.add(clearbutton);
panel2.add(quitbutton);
panel2.add(infobutton);
panel2.setLayout(new FlowLayout());
quitbutton.addActionListener(inst1);
infobutton.addActionListener(inst1);
clearbutton.addActionListener(inst1);
savebutton.addActionListener(inst1);
selectcolor.addActionListener(inst1);
selectbg.addActionListener(inst1);
}
//add to panel3
private static void addPanel3(){
StrokeAction inst2 = new StrokeAction();
spinnerbrush.addChangeListener(inst2);
panel3.add(new JLabel("Stroke size"));
panel3.add(spinnerbrush);
panel3.add(selectcolor);
panel3.add(new JLabel("Current color:"));
colorlabel.setSize(20, 20);
colorlabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
colorlabel.setOpaque(true);
colorlabel.setBackground(Color.WHITE);
colorlabel.setForeground(Color.WHITE);
panel3.add(colorlabel);
panel3.add(selectbg);
}
private static class ButtonAction implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource()==quitbutton){
System.exit(0);
}
else if(arg0.getSource()==infobutton){
JOptionPane.showMessageDialog(frame1, "Paint Toolbox designed in Java");
}
else if(arg0.getSource()==selectcolor){
panel1.changeColor();
}
else if(arg0.getSource()==selectbg){
panel1.changeBg();
}
else if(arg0.getSource()==clearbutton){
panel1.colfg = panel1.colbg;
colorlabel.setBackground(panel1.colfg);
colorlabel.setForeground(panel1.colfg);
panel1.setForeground(null);
}
else if(arg0.getSource()==savebutton){
panel1.saveImage();
}
}
}
private static class StrokeAction implements ChangeListener{
#Override
public void stateChanged(ChangeEvent arg0) {
if (arg0.getSource()==spinnerbrush){
Object o1 = spinnervals.getValue();
Integer int1 = (Integer) o1;
stroke1 = int1.intValue();
panel1.changeStroke(stroke1);
}
// TODO Auto-generated method stub
}
}
public static void main(String args[]){
addPanel1();
addPanel2();
addPanel3();
frame1.add(panel1, BorderLayout.NORTH);
frame1.add(panel2, BorderLayout.SOUTH);
frame1.add(panel3, BorderLayout.CENTER);
frame1.setTitle("PaintBox v2.2");
frame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame1.setSize(800,600);
frame1.setResizable(false);
frame1.setLocationRelativeTo(null);
frame1.setVisible(true);
}
}
class AuxClass4 extends JPanel implements MouseMotionListener{
/**
*
*/
private static final long serialVersionUID = 1L;
private int xval;
private int yval;
public Color colfg;
public Color colbg;
public int strokesize;
public int fileorder;
public AuxClass4(Color input1, Color input2, int input3){
colfg=input1;
colbg=input2;
strokesize = input3;
this.setBorder(BorderFactory.createLineBorder(Color.CYAN, 10));
this.setBackground(colbg);
//this.setMaximumSize(new Dimension(500,380));
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g1){
super.paintComponent(g1);
g1.setColor(colfg);
g1.fillRect(xval, yval, strokesize, strokesize);
}
#Override
public void mouseDragged(MouseEvent arg0) {
xval = arg0.getX();
yval = arg0.getY();
repaint(xval, yval, strokesize,strokesize);
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent arg0) {
xval = arg0.getX();
yval = arg0.getY();
String xvalret = Integer.toString(xval);
String yvalret = Integer.toString(yval);
MainClass2.xlab.setText(" " + xvalret + " ");
MainClass2.ylab.setText(" " + yvalret + " ");
}
public void changeColor(){
colfg = JColorChooser.showDialog(this, "Select color", colfg);
MainClass2.colorlabel.setBackground(colfg);
MainClass2.colorlabel.setForeground(colfg);
}
public void changeBg(){
colbg=JColorChooser.showDialog(this, "Select color", Color.WHITE);
colfg=colbg;
this.setBackground(colbg);
MainClass1.colorlabel.setBackground(colfg);
MainClass1.colorlabel.setForeground(colfg);
}
public void changeStroke(int inputstroke){
strokesize=inputstroke;
}
public void saveImage(){
final String dir = System.getProperty("user.dir");
JOptionPane.showMessageDialog(this, "File saved under " + dir + "/saveimage" + fileorder +".png");
fileorder+=1;
}
}
It works fine for now, but I started wondering if it is possible to implement undo and redo methods for Graphics objects. Intuitively, there should be some way to add the created objects to some table in a 'historical' order. User then should be able to navigate in this table.
Unfortunately, I have no experience with this approach, especially with graphics, so any suggestion would be massively welcome.

I would recommend UndoManager
http://docs.oracle.com/javase/6/docs/api/javax/swing/undo/UndoManager.html
See also the example
http://www.java2s.com/Code/Java/Swing-JFC/Undomanager.htm

Take a look at the command pattern. I think this javaworld article explains it quite nicely.
In a nutshell you will have to have an interface containing undo and redo. Objects that implement this will be added to a list. As you undo and redo you can navigate through the list calling undo and redo. It means that you may have to write more code becuase for every event you actually draw you will have to write the equivelent to undo it.

Related

Accessing changes made inside JButton ActionListener outside the ActionListener

I ll explain my code in a bit:
I have a JComboBox with a list of items
And when the JButton "Select" is pressed, it registers the last index of the last selected item from JComboBox.
Now I need to access this index inside the main.
Here is my code :
public static final JComboBox c = new JComboBox();
private static final JButton btnNewButton = new JButton("Select");
And the JButton ActionListener is:
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
ind = c.getSelectedIndex();
frame.setVisible(false);
}
});
So after the button is pressed, the frame closes
But now when I try to access this ind inside main simply by
public static void main(String[] args) {
System.out.println(ind);}
I get a return value of ind = 0
I understand that this is because it has been initialized to 0 as
static ind = 0
But then how do I access this index outside the JButton ActionListener?
I need to use this index further in my code.
EDIT
Here's my MCVE
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SpringLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.UIManager;
public class MinimalExProgram
{
private static String[] description = { "One", "Two", "Three"};
static int ind;
public static final JComboBox c = new JComboBox(description);
private static final JButton btnNewButton = new JButton("Select");
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().setForeground(UIManager.getColor("ComboBox.disabledBackground"));
frame.getContentPane().setBackground(UIManager.getColor("EditorPane.disabledBackground"));
SpringLayout springLayout = new SpringLayout();
springLayout.putConstraint(SpringLayout.NORTH, btnNewButton, 5, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, c, -6, SpringLayout.WEST, btnNewButton);
springLayout.putConstraint(SpringLayout.EAST, btnNewButton, -10, SpringLayout.EAST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, c, 6, SpringLayout.WEST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.NORTH, c, 6, SpringLayout.NORTH, frame.getContentPane());
frame.getContentPane().setLayout(springLayout);
frame.setSize(500, 150);
frame.setLocation(400, 200);
frame.setResizable(false);
c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
System.out.print("What I want:");
ind = c.getSelectedIndex();
System.out.println(ind);
frame.setVisible(false);
}
});
frame.getContentPane().add(c);
btnNewButton.setForeground(UIManager.getColor("ComboBox.buttonDarkShadow"));
btnNewButton.setBackground(UIManager.getColor("EditorPane.disabledBackground "));
frame.getContentPane().add(btnNewButton);
frame.setVisible(true);
System.out.print("What I get: ");
System.out.println(ind);
}
}
I need to access the ind inside the main as mentioned before
Here when I print out the ind I get zero despite whatever choice I make inside the combobox.
OK, I'm going to guess since you've yet to show us enough information to do more than this, but I assume that:
You're showing a 2nd window as a dialog off of a main window
That this 2nd window is a JFrame and holds your JComboBox and the button
That you're making it invisible on button push,
That you try to get the information from the combobox, but it's always 0
And this may be because you're getting the information before the user has had a chance to interact with the 2nd window.
If so, the solution is to make the 2nd window a modal dialog window such as a modal JDialog and not a JFrame. This way, the calling code will know exactly when the 2nd window is no longer visible since the calling code's code flow will be blocked until the 2nd window is no longer visible.
Edit
Proof of concept: Change your code from:
final JFrame frame = new JFrame();
to:
// rename frame variable to dialog for clarity
final JDialog dialog = new JDialog();
dialog.setModalityType(ModalityType.APPLICATION_MODAL);
and it works.
But again, I'd get rid of unnecessary statics and get rid of doing too much code in the main method. For instance,...
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
#SuppressWarnings("serial")
public class MinimalExProgram3 extends JPanel {
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JFrame frame = new JFrame("MinimalExProgram3");
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();
}
});
}
}
#SuppressWarnings("serial")
class MainPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JTextField field = new JTextField(8);
private ComboPanel comboPanel = new ComboPanel();
JDialog dialog = null;
public MainPanel() {
field.setFocusable(false);
add(field);
add(new JButton(new ShowComboAction("Show Combo")));
}
#Override // make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class ShowComboAction extends AbstractAction {
public ShowComboAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Window mainWin = SwingUtilities.getWindowAncestor(MainPanel.this);
if (dialog == null) {
dialog = new JDialog(mainWin, "Dialog", ModalityType.APPLICATION_MODAL);
dialog.add(comboPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
// code called here after dialog no longer visible
String text = comboPanel.getText();
field.setText(text);
}
}
}
#SuppressWarnings("serial")
class ComboPanel extends JPanel {
private static final String[] DESCRIPTION = { "One", "Two", "Three" };
private int ind;
private JComboBox<String> combo = new JComboBox<>(DESCRIPTION);
private String text;
private SelectionAction selectionAction = new SelectionAction("Select");
private JButton selectionButton = new JButton(selectionAction);
public ComboPanel() {
add(combo);
add(selectionButton);
combo.setAction(selectionAction);
}
public int getInd() {
return ind;
}
public String getText() {
return text;
}
private class SelectionAction extends AbstractAction {
public SelectionAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
ind = combo.getSelectedIndex();
if (ind >= 0) {
text = combo.getSelectedItem().toString();
}
Window win = SwingUtilities.getWindowAncestor(ComboPanel.this);
win.dispose();
}
}
}

Java Multidemensional Array Loop that inputs data with Button Action

Questions I am pulling my hair out over.
How do I get the array to add data to current index, then increment to the next index to add changed JTextField data for the next button press. currently I'm overwriting the same index.
I have tried to figure out actionlisteners for the button "Submit" that uses a counter with nesting of the loop. played with ideas from question 23331198 and 3010840 and 17829577 many others as a reference but didn't really get it to far. Most searches pull up info on managing buttons with arrays and creating button arrays so I assume I'm not using the correct wording to search with. I have read a few places that an MD array is not the best option to use.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class GUIandLogicTest extends JFrame
{
// Variable Decloration
private static JFrame mainFrame;
private static JPanel mainPanel;
private static JTextField fieldOne;
private static JTextField fieldTwo;
private static JTextArea textArea;
private static JLabel textFieldOneLabel;
private static JLabel textFieldTwoLabel;
double[][] tutArray = new double[10][2];
// int i =0 ;
// Set GUI method
private void gui()
{
// constructs GUI
mainFrame = new JFrame();
mainFrame.setSize(800, 800);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
textFieldOneLabel = new JLabel("number 1");
mainPanel.add(textFieldOneLabel);
fieldOne = new JTextField(10);
mainPanel.add(fieldOne);
textFieldTwoLabel = new JLabel("number 2");
mainPanel.add(textFieldTwoLabel);
fieldTwo = new JTextField(10);
mainPanel.add(fieldTwo);
textArea = new JTextArea(50, 50);
mainPanel.add(textArea);
JButton Exit = new JButton("Quit");// Quits program
mainPanel.add(Exit);
Exit.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
JButton submit = new JButton("Enter");
// Reads jfields and set varibles to be submitted to array
mainPanel.add(submit);
submit.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent arg0)
{
double txtField1 = Double
.parseDouble(fieldOne.getText().trim());
double txtField2 = Double
.parseDouble(fieldTwo.getText().trim());
if (txtField1 < 0)
{
}
if (txtField2 < 0)
{
}
int arrayIndex = 0;
tutArray[arrayIndex][0] = txtField1;
tutArray[arrayIndex][1] = txtField2;
arrayIndex++;
for (int i = 0; i < tutArray.length; i++)
{
textArea.append("Number1: " + tutArray[i][0] + " Number2: "
+ tutArray[i][1]);
textArea.append("\n");
textArea.append(String.valueOf(arrayIndex++));
textArea.append("\n");
// textArea.append(String.valueOf(arrayIndex++));
}
}
});
JButton report = new JButton();
// will be used to pull data out of array with formatting and math
mainFrame.setVisible(true);
mainFrame.add(mainPanel);
}
public static void main(String[] arg)
{
GUIandLogicTest GUIandLogic = new GUIandLogicTest();
GUIandLogic.start();
}
public void start()
{
gui();
}
}
This is what I was looking for thanks for the help!
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class GUIandLogicTest extends JFrame
{
// Variable Decloration
private static JFrame mainFrame;
private static JPanel mainPanel;
private static JTextField fieldOne;
private static JTextField fieldTwo;
private static JTextArea textArea;
private static JLabel textFieldOneLabel;
private static JLabel textFieldTwoLabel;
double[][] tutArray = new double[10][2];
int arrayIndex = 0;
// int i =0 ;
// Set GUI method
private void gui()
{
// constructs GUI
mainFrame = new JFrame();
mainFrame.setSize(800, 800);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
textFieldOneLabel = new JLabel("number 1");
mainPanel.add(textFieldOneLabel);
fieldOne = new JTextField(10);
mainPanel.add(fieldOne);
textFieldTwoLabel = new JLabel("number 2");
mainPanel.add(textFieldTwoLabel);
fieldTwo = new JTextField(10);
mainPanel.add(fieldTwo);
textArea = new JTextArea(50, 50);
mainPanel.add(textArea);
JButton Exit = new JButton("Quit");// Quits program
mainPanel.add(Exit);
Exit.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
JButton submit = new JButton("Enter");
// Reads jfields and set varibles to be submitted to array
mainPanel.add(submit);
submit.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent arg0)
{
double txtField1 = Double
.parseDouble(fieldOne.getText().trim());
double txtField2 = Double
.parseDouble(fieldTwo.getText().trim());
textArea.setText("");
if (txtField1 < 0)
{
}
if (txtField2 < 0)
{
}
tutArray[arrayIndex][0] = txtField1;
tutArray[arrayIndex][1] = txtField2;
arrayIndex++;
for (int i = 0; i < arrayIndex; i++)
{
textArea.append("Number1: " + tutArray[i][0] + " Number2: "
+ tutArray[i][1]);
// textArea.append("\n");
//textArea.append(String.valueOf(arrayIndex++));
textArea.append("\n");
// textArea.append(String.valueOf(arrayIndex++));
}
}
});
JButton report = new JButton();
// will be used to pull data out of array with formatting and math
mainFrame.setVisible(true);
mainFrame.add(mainPanel);
}
public static void main(String[] arg)
{
GUIandLogicTest GUIandLogic = new GUIandLogicTest();
GUIandLogic.start();
}
public void start()
{
gui();
}
}
You can add the index as a field in your main object:
protected int index;
in your actionPerformed you increase index:
index++;
NOTE:
But why do you extend from JFrame AND use the field mainFrame?
you can use
this.setSize(800,800);
this.add(mainPanel);
Please declare (because of extends JFrame):
private static final long serialVersionUID = 1L;
Please start the name of an object with a lower case letter:
JButton exit = new JButton("Quit");

Basic Multiply and Divide Java GUI

I am trying to have the number the user inputs into the frame either multiply by 2 or divide by 3 depending on which button they decide to click. I am having an hard time with working out the logic to do this. I know this needs to take place in the actionperformed method.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Quiz4 extends JFrame ActionListener
{
// Global Variable Declarations
// Our list input fields
private JLabel valueLabel = new JLabel("Enter a value between 1 and 20: ");
private JTextField valueField = new JTextField(25);
// create action buttons
private JButton multiButton = new JButton("x2");
private JButton divideButton = new JButton("/3");
private JScrollPane displayScrollPane;
private JTextArea display = new JTextArea(10,5);
// input number
private BufferedReader infirst;
// output number
private NumberWriter outNum;
public Quiz4()
{
//super("List Difference Tool");
getContentPane().setLayout( new BorderLayout() );
// create our input panel
JPanel inputPanel = new JPanel(new GridLayout(1,1));
inputPanel.add(valueLabel);
inputPanel.add(valueField);
getContentPane().add(inputPanel,"Center");
// create and populate our diffPanel
JPanel diffPanel = new JPanel(new GridLayout(1,2,1,1));
diffPanel.add(multiButton);
diffPanel.add(divideButton);
getContentPane().add(diffPanel, "South");
//diffButton.addActionListener(this);
} // Quiz4()
public void actionPerformed(ActionEvent ae)
{
} // actionPerformed()
public static void main(String args[])
{
Quiz4 f = new Quiz4();
f.setSize(1200, 200);
f.setVisible(true);
f.addWindowListener(new WindowAdapter()
{ // Quit the application
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
} // main()
} // end of class
Here's something simpler, but it essentially does what you want out of your program. I added an ActionListener to each of the buttons to handle what I want, which was to respond to what was typed into the textbox. I just attach the ActionListener to the button, and then in the actionPerformed method, I define what I want to happen.
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Quizx extends JFrame {
private JPanel panel;
private JTextField textfield;
private JLabel ansLabel;
public Quizx() {
panel = new JPanel(new FlowLayout());
this.getContentPane().add(panel);
addLabel();
addTextField();
addButtons();
addAnswerLabel();
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setTitle("Quiz 4");
this.setSize(220, 150);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setVisible(true);
}
private void addTextField() {
textfield = new JTextField();
textfield.setColumns(9);
panel.add(textfield);
}
private void addButtons() {
JButton multButton = new JButton("x2");
JButton divButton = new JButton("/3");
panel.add(multButton);
panel.add(divButton);
addMultListener(multButton);
addDivListener(divButton);
}
private void addLabel() {
JLabel valueLabel = new JLabel("Enter a value between 1 and 20: ");
panel.add(valueLabel);
}
private void addAnswerLabel() {
ansLabel = new JLabel();
panel.add(ansLabel);
}
private void addMultListener(JButton button) {
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
ansLabel.setText(String.valueOf(Integer.parseInt(textfield.getText().trim()) * 2));
}
});
}
private void addDivListener(JButton button) {
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
ansLabel.setText(String.valueOf(Double.parseDouble(textfield.getText().trim()) /3));
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Quizx();
}
});
}
}
Hope that helps.

How Do I use KeyListener to Display Different Strings Depending on Which Key is Pressed?

Take it easy on me, I'm pretty new to Java programming in general, especially swing, and I'm trying to learn the basics of GUI programming.
I want to be able to prompt the user to enter a certain key into a text box and then click a button to display a string of text based on what key they enter. This is what I have so far:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class LeeSinAbilities extends JFrame
{
private JLabel leeSin;
private JTextField ability;
private JButton c;
private JLabel aName;
private static final long serialVersionUID = 1L;
public LeeSinAbilities()
{
super("Lee Sin's Abilities");
setLayout(new FlowLayout());
setResizable(true);
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel leeSin = new JLabel("Enter an ability key to see Lee Sin's ability names! (q, w, e, r)");
add(leeSin);
JTextField ability = new JTextField("Enter abilities here: ", 1);
add(ability);
JButton go = new JButton("Get Ability Name");
add(go);
JLabel aName = new JLabel("");
add(aName);
event e = new event();
go.addActionListener(e);
}
public static void main(String [] args){
new LeeSinAbilities().setVisible(true);
}
public class event implements ActionListener{
public void actionPerformed(ActionEvent e){
String abilityName = ability.getText();
if(abilityName.equalsIgnoreCase("q")){
aName.setText("Sonic Wave / Resonating Strike");
}
else if(abilityName.equalsIgnoreCase("w")){
aName.setText("Safeguard / Iron Will");
}
else if(abilityName.equalsIgnoreCase("e")){
aName.setText("Tempest / Cripple");
}
else if(abilityName.equalsIgnoreCase("r")){
aName.setText("Dragon's Rage");
}
else
aName.setText("Brutha please -_-...q, w, e, or r!");
}
}
}
I realise ActionListener is not the correct event to use, I'm just not sure what to put there yet (I'm guessing KeyListener.) All comments / suggestions are highly appreciated.
The first issue (which I assume is NullPointerException) is due to the fact that you are shadowing your variables...
public class LeeSinAbilities extends JFrame
{
//...
// This is a instance variable named ability
private JTextField ability;
//...
public LeeSinAbilities()
{
//...
// This is a local variable named ability , which
// is now shadowing the instance variable...
JTextField ability = new JTextField("Enter abilities here: ", 1);
//...
}
public class event implements ActionListener{
public void actionPerformed(ActionEvent e){
// This will be `null` as it's referencing the
// instance variable...
String abilityName = ability.getText();
//...
}
}
}
So instead of using...
JTextField ability = new JTextField("Enter abilities here: ", 1);
You should be using...
ability = new JTextField("Enter abilities here: ", 1);
This will prevent the NullPointerException from occurring in you actionPerformed method
Updated
Now, if you want to respond to key events, the best approach is to use the Key Bindings API, for example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class KeyPrompt {
public static void main(String[] args) {
new KeyPrompt();
}
public KeyPrompt() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.setSize(400, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel aName;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JLabel("Enter an ability key to see Lee Sin's ability names! (q, w, e, r)"), gbc);
aName = new JLabel("");
add(aName, gbc);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "QAbility");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "WAbility");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0), "EAbility");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0), "RAbility");
am.put("QAbility", new MessageAction(aName, "Sonic Wave / Resonating Strike"));
am.put("WAbility", new MessageAction(aName, "Safeguard / Iron Will"));
am.put("EAbility", new MessageAction(aName, "Tempest / Cripple"));
am.put("RAbility", new MessageAction(aName, "Dragon's Rage"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
public class MessageAction extends AbstractAction {
private final String msg;
private final JLabel msgLabel;
public MessageAction(JLabel msgLabel, String msg) {
this.msgLabel = msgLabel;
this.msg = msg;
}
#Override
public void actionPerformed(ActionEvent e) {
msgLabel.setText(msg);
}
}
}
}
It has better control over the focus requirements depending on your needs...

need assistance with GUIs and java swing

This is my program below and I am trying to figure out where my main method should be. I have seen a few examples of it being implemented at the very end of the program but there main is different from mine.
Main method (to be implemented):
public class JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Components File");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
My Program
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Lab_10 extends JFrame
{
private final double EARTHQUAKE_RATE= 8.0;
private final int FRAME_WIDTH= 300;
private final int FRAME_HEIGHT= 200;
private JLabel rLabel;
private JTextField eField;
private JButton button;
private JLabel earthLabel;
public Lab_10()
{
JLabel earthLabel = new JLabel("Most structures fall");
makeTextField();
makeButton();
makePanel();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void makeTextField()
{
JLabel rLabel = new JLabel("Richter");
final int FIELD_WIDTH = 10;
eField = new JTextField(FIELD_WIDTH);
eField.setText("" + EARTHQUAKE_RATE);
}
class AddLabelListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
earthLabel.setText("Most structures fall");
}
}
private void makeButton()
{
JButton button = new JButton("Enter");
ActionListener listener = new AddLabelListener();
button.addActionListener(listener);
}
private void makePanel()
{
JPanel panel = new JPanel();
panel.add(rLabel);
panel.add(eField);
panel.add(button);
panel.add(earthLabel);
add(panel);
}
}
Updated Code (which is compiling but and running but with logic errors because it implements an empty frame [guess as much from the main method I have]):
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Lab_10 extends JFrame
{
private final double EARTHQUAKE_RATE= 8.0;
private final int FRAME_WIDTH= 300;
private final int FRAME_HEIGHT= 200;
private JLabel rLabel;
private JTextField eField;
private JButton button;
private JLabel earthLabel;
public Lab_10()
{
JLabel earthLabel = new JLabel("Most structures fall");
makeTextField();
makeButton();
makePanel();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void makeTextField()
{
JLabel rLabel = new JLabel("Richter");
final int FIELD_WIDTH = 10;
eField = new JTextField(FIELD_WIDTH);
eField.setText("" + EARTHQUAKE_RATE);
}
class AddLabelListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
earthLabel.setText("Most structures fall");
}
}
private void makeButton()
{
JButton button = new JButton("Enter");
ActionListener listener = new AddLabelListener();
button.addActionListener(listener);
}
private void makePanel()
{
JPanel panel = new JPanel();
panel.add(rLabel);
panel.add(eField);
panel.add(button);
panel.add(earthLabel);
add(panel);
}
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
#Override
public void run()
{ JFrame frame = new JFrame();
frame.setTitle("Components File");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
Your 'main' probably looks different because you are not using SwingUtilities.invokeLater(Runnable doRun) ?
Well, to put it simply, you must use it always. So, modify your code and use this:
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
// copy-paste your main() code
}
});
Also, why is your class named JFrame ? Refrain from using names that are already used by Java classes already.

Categories

Resources