Cast Component[] -> JButton - java

I'm programming Java with NetBeans. I have a strange problem. In a class Mouse Listener, I do getComponents of a panel, and it returns a array of components that I put(?) in one array JButton (whit cast) so..
JButton[] b= (JButton[])Main.p1.getComponents();
IDE doesn't show an error.
I do, for example:
b[0].setBackground(Color.yellow);
and in output I see an error.
But if I do
JButton b= (JButton) Main.p1.getComponents()[0];
b.setBackground(...);
And all works but I don't understand why. Can somebody explain please?
2015-01-18
Thank to all for the answer.
I want take Components of a Panel, not only for change background's color, but also for the Ordinates; I need all Buttons in a array to compare all at the same time .. Why I cant convert 'Components' in 'Buttons'? Panel has a pointer to Buttons in Ram Memory..
Patryk Dobrowolski thank's you, i try this: (i use class Button extends JButton)
Button[] button = new Button[Main.p1.getComponents().length];
for (int i = 0; i < Main.p1.getComponents().length; i++) {
button[i] = (Button) Main.p1.getComponents()[i];
}
but in output I see this error:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JLabel cannot be cast to Button
why JLabel?
Hovercraft Full Of Eels, thank's you for your answer, I could create an array and insert the pointer of all Button into it. But I said: JPannel has a Array where insert pointer.. I can use it. Why not?
Thank's you very much!
Alessandro Amedei

In the first case, you are lying to the compiler. By stating
JButton[] b= (JButton[])Main.p1.getComponents();
you are telling the compiler that you know that this is an array of JButtons, when in fact it really is an array of Components. Therefore you get no compile-time errors, but you do get one at runtime.
In the other case it works, since then you are telling the compiler that the Component you want to work with is a JButton, which is true.

It's because array of JComponent is not the same as array of JButton. You need to cast one by one in the loop if you want to finally get array of buttons:
JButton[] buttons = new JButton[components.length];
for (int i = 0; i < components.length; i++) {
buttons[i] = (JButton) components[i];
}

I am concerned that you are trying to extract your selected JButton by iterating through an array of components and thereby basing your program logic on the GUI component structure, which is a very fragile way to do things. If you change components around, or later decide to nest a container that holds your JButtons into another container (i.e., into another JPanel), you would have to take care to update this listener and all similar listeners, again making your code quite fragile.
Rather than do this, a better solution might be to add a listener to the individual components that need them. For instance, if you want to change the background of a JButton to yellow if a mouse is hovering over it, consider adding a ChangeListener to each JButton, extracting the involved button via the ChangeEvent's getSource() method and then testing the button's model to see if it is in a roll-over state. For example:
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class SetButtonBackground extends JPanel {
public static final Color ROLLOVER_COLOR = Color.yellow;
public SetButtonBackground() {
int rows = 5;
int cols = rows;
setLayout(new GridLayout(rows, cols, 5, 5));
ButtonChangeListener btnChngListener = new ButtonChangeListener();
for (int i = 0; i < rows * cols; i++) {
String text = "Button " + (i + 1);
JButton button = new JButton(text);
button.addChangeListener(btnChngListener);
add(button);
}
}
private class ButtonChangeListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
JButton btn = (JButton) e.getSource();
ButtonModel model = btn.getModel();
if (model.isRollover()) {
if (!btn.getBackground().equals(ROLLOVER_COLOR)) {
btn.setBackground(ROLLOVER_COLOR);
}
} else if (btn.getBackground().equals(ROLLOVER_COLOR)) {
btn.setBackground(null); // change back to default state
}
}
}
private static void createAndShowGui() {
SetButtonBackground mainPanel = new SetButtonBackground();
JFrame frame = new JFrame("Set Button Background");
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();
}
});
}
}

Related

Reordering labels

I'm creating labels dynamically from an array in a FlowLayout JPanel, storing them in a JLabel array for future reference. They are displayed from left to right as intended.
I want to move one of the labels to the beginning (leftmost) of the panel.
I don't mind if the whole array shifts or just two labels swap places:
apple orange pear cherry melon
|
cherry apple orange pear melon
or
cherry orange pear apple melon
I've swapped array entries, then revalidate() and repaint(), but nothing happens.
Is there an easy way to move swing components around without removing all and then re-adding them to the panel or copying all the properties from one label to the other (I have others defined, not just the text)?
Here is a stripped down version of my code:
import javax.swing.*;
public class Test extends JPanel {
public Test () {
String entries[] = { "apple", "orange", "pear", "cherry", "melon" };
JLabel[] lbls = new JLabel[entries.length];
for (int i = 0; i < entries.length; ++i) {
lbls[i] = new JLabel();
lbls[i].setText(entries[i]);
add(lbls[i]);
}
// swap array entries
JLabel tmplbl = new JLabel();
tmplbl = lbls[3];
lbls[3] = lbls[0];
lbls[0] = tmplbl;
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setContentPane(new Test());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
});
}
}
I've swapped array entries
Swapping entries in an array does nothing. The Array has nothing to do with the panel.
So you need to adjust the components on the panel.
I want to move one of the labels to the beginning (leftmost) of the panel.
Well that is a different requirement than "swapping". It is also easier.
You can add a component to a panel and specify its position in the panel, so adding a component to the beginning is easy because its position will always be zero.
So to move the 3rd component to the beginning the code would be something like:
Component component = panel.getComponent(2);
panel.add(component, 0);
panel.revalidate();
panel.repaint();
If you really want a swap, then the code would be similar. You would get the component at both locations and then add the one component back to the lower location first and the add the other component back to the higher location.
There are a couple of things to fix before fixing your error:
Here are 2 errors in this line: public class Test extends JPanel {
Class name, do you know how many people call their classes Test? A LOT! Make it more descriptive, like SwapLabelsTest.
extends JPanel, you're not changing the behavior of the JPanel so there's no need to extend it in this case, just create a new instance of JPanel.
Don't put everything in the constructor, it's better to have an initialize() method or something like that (createAndShowGUI() in the code below) to handle GUI construction. It may seem like the easiest way, but separating that part will come handy later on when the project becomes bigger.
Move your variables to a bigger scope, for easier handling, unless those variables are local to the method, this will improve performance and readability.
Include a component that detects events, such as a JButton so that your swapping execution will happen when that event is triggered (a button click).
Your swapping logic seems a little bit odd, you have created new JLabels there and are trying to swap them, but it's better to have a MVC kind of pattern here, so that you swap the values in the array and then just update the UI after with those changes.
You may be asking, but how do I do that? Well like this:
String tmpString = entries[3];
entries[3] = entries[1];
entries[1] = tmpString;
The above code swaps the values in the entries array, all we have to do now is update each label with lbl[i].setText(entries[i]) inside of a for-loop.
So, you end up with something like this in the end:
import java.awt.BorderLayout;
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.SwingUtilities;
public class Test {
private JFrame frame;
private JPanel panel;
private String entries[] = { "apple", "orange", "pear", "cherry", "melon" };
private JLabel[] lbls = new JLabel[entries.length];
JButton button;
private void createAndShowGUI() {
panel = new JPanel();
for (int i = 0; i < entries.length; ++i) {
lbls[i] = new JLabel();
lbls[i].setText(entries[i]);
panel.add(lbls[i]);
}
button = new JButton("Swap 1 and 3");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String tmpString = entries[3];
entries[3] = entries[1];
entries[1] = tmpString;
reloadLabels();
}
});
frame = new JFrame("Test");
frame.add(panel);
frame.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
private void reloadLabels() {
for (int i = 0; i < entries.length; ++i) {
lbls[i].setText(entries[i]);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().createAndShowGUI();
}
});
}
}
Everytime you click the button, the items 1 & 3 (indexes) will be swapped and the UI will be updated (as .setText triggers an UI update).

How to call methods on objects that I didn't assign a reference name to?

For example, I am trying to call the setEnable method on a JButton that I constructed within the parameter parenthesis of an add method:
add(new JButton());
I know I could just do something like:
JButton button = new JButton();
button.setEnable(false);
but is there I way I can call setEnable on a JButton that I didn't assign a reference name to?
The reason why I am not assigning the JButton a reference name is because I am supposed to add an unknown number of JButtons to a JPanel. How I am doing this, is by using this for loop.
for (int i = 0; i < numberOfButtonsToAdd; i++)
{
JPanelName.add(new JButton());
}
and I want all the JButtons to be disabled.
You state in comment:
The reason why I am not assigning the JButton a reference name is because I am supposed to add an unknown number of JButtons to a JPanel. How I am doing this, is by using a for loop: for (int i = 0; i < numberOfButtonsToAdd; i++) { JPanelName.add(new JButton()); }
Then just use either an array or ArrayList of JButton.
// in your field declarations
List<JButton> buttonList = new ArrayList<JButton>();
// elsewhere in your program
for (int i = 0; i < numberOfButtonsToAdd; i++) {
JButton button = new JButton();
buttonList.add(button);
somePanel.add(button);
}
Now you have a reference to any button in the list via buttonList.get(someIndex)
Note also, that most buttons are given ActionListeners that are activated whenever the button is pressed. Without such listeners, the buttons are pretty much useless. You can also get a reference to the pressed JButton from the ActionListener via the ActionEvent object passed into its actionPerformed method:
public void actionPerformed(ActionEvent e) {
AbstractButton myButton = (AbstractButton) e.getSource();
// now you can use myButton
}
Note that this is key information that you should have shared with us up front in your original question.
Edit
You state now:
and I want all the JButtons to be disabled.
Then just make them disabled from the get-go:
for (int i = 0; i < numberOfButtonsToAdd; i++) {
JButton button = new JButton();
button.setEnabled(false);
buttonList.add(button);
somePanel.add(button);
}
Although I am curious -- why all disabled? Why no ActionListener? No text?
Edit 2
You state:
Would I still be able to access those individual buttons later on, since they are all assigned "button"?
Please understand that the variable name is of little importance, and in fact, in my example above, the variable named button does not exist outside of the for loop within which it was declared. Instead what matters is the reference to the JButton object. As has been much discussed in the other answers and as you are aware, this can be obtained by using a variable, but it doesn't have to be a variable directly to the JButton, it could, as is in this case, be the variable to the ArrayList<JButton>. That's why I suggest that you create this entity.
Edit 3
for example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class ButtonLists extends JPanel {
private static final int ROWS = 6;
private static final int COLS = 6;
private List<JButton> allButtons = new ArrayList<JButton>();
private List<JButton> evenButtons = new ArrayList<JButton>();
public ButtonLists() {
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
int buttonInt = i * COLS + j;
String buttonString = String.valueOf(buttonInt);
JButton button = new JButton(buttonString);
button.setEnabled(false);
gridPanel.add(button);
allButtons.add(button);
if (buttonInt % 2 == 0) {
evenButtons.add(button);
}
}
}
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Activate All") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(true);
}
}
}));
bottomPanel.add(new JButton(new AbstractAction("Activate Even") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(false);
}
for (JButton btn : evenButtons) {
btn.setEnabled(true);
}
}
}));
bottomPanel.add(new JButton(new AbstractAction("Activate Odd") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(true);
}
for (JButton btn : evenButtons) {
btn.setEnabled(false);
}
}
}));
setLayout(new BorderLayout());
add(gridPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ButtonLists");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonLists());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
If you added it to a panel you can get the components of that panel and looping through those components if one is a button you could call setEnabled(), but if there were more than one button you would have to determine if it was the correct one.
Edit:
Since you added that you want all the buttons disabled then this method should work nicely. Examples:
All:
for(Component c : panel.getComponents()){
c.setEnabled(false);
}
Just JButtons:
for(Component c : panel.getComponents()){
if(c instanceof JButton){
((JButton)c).setEnabled(false);
}
}
No, you can't. If setEnabled() returned the object it's enabling, you could enable-and-add the object in a single line. But as it is, setEnabled() returns void, so you have no choice but to use a local variable.
However, a JButton is enabled by default, so there's no need to explicitly call setEnabled() on it, it's already enabled!
You can call a method in a new instance like
new JButton().setEnabled(true);
But this won't allow you to access the JButton instance you create here anymore and thus you cannot call add().
This can only be possible if the method call returns the instance object on which it was called. So if for example setEnabled would return the same instance on which it was called (that is, this in setEnabled context) , you could do add(new JButton().setEnabled(true)).
Anyway in your case don't be afraid of using references:
final JButton button = new JButton();
button.setEnabled(true);
add(button);
Note that in this case 2 last methods can be called in any order, the result will be the same.
The only way this can work is if what ever you are adding it to has a get method. other than that you don't have any other options. Best way is what you showed.
JButton button = new JButton();
button.setEnable(true);

Somehow my GUI got stuck when I click on a button to perform a method call

I want to update the board configuration by clicking on a JButton. However, sometimes the image is displayed on the frame. sometimes is not. Everytime there is a significant delay after I click on the button. I tried debugging and found there might be a endless loop in :EventDispatchThread.class
(this is the class from java library)
void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
addEventFilter(filter);
doDispatch = true;
while (doDispatch && cond.evaluate()) {
if (isInterrupted() || !pumpOneEventForFilters(id)) {
doDispatch = false;
}
}
removeEventFilter(filter);
}
The endless loop is the while loop above.
Below is my listener class:
public class PlaceListener implements ActionListener{
private JTextField _text1;
private Board board;
private JTextField _text2;
private ArrayList<NewGUI> _guiList;
private int _numOfPlayer;
public PlaceListener(JTextField text1, JTextField text2, Board b,ArrayList<NewGUI> guiList, int numOfPlayer,NewGUI gui)
{
_text1 = text1;
_text2 = text2;
board = b;
_guiList = guiList;
_numOfPlayer = numOfPlayer;
}
#Override
public void actionPerformed(ActionEvent e) {
int x = Integer.parseInt(_text1.getText());
int y = Integer.parseInt(_text2.getText());
board.Place(y, x);
for(int j = 0;j<_numOfPlayer;j++)
{
NewGUI gui = _guiList.get(j);
gui.updateBoard();
gui.updateCurrTile();
gui.updateScore();
gui.updateTurn();
}
}
}
The basic idea is: I have an array of GUI. after each click, the listener will call all the GUIs within the array to update their configuration.
I also tried to update the board configuration within the GUI class directly, and it turns out to work well. I'm extremely confused! Can anyone help me out? Thanks!!
This is the main GUI class:
public class NewGUI {
private JFrame _frame;
private Board _board;
private JLabel _turnLabel;
private JTextArea _textArea;
private JLabel _currTileLabel;
private JPanel _boardPanel;
public NewGUI(Board board,int whos,ArrayList<NewGUI> guiList,int numOfPlayer)
{
_board = board;
_frame = new JFrame("Metro");
//turnLabel
_turnLabel = new JLabel();
_turnLabel.setText("Current player is: "+_board.getCurrPlayer());
_turnLabel.setSize(110, 40);
_turnLabel.setLocation(0, 0);
_frame.add(_turnLabel);
//mainPlayerLabel
JLabel mainPlayerLabel = new JLabel("Player"+whos+" 's window");
mainPlayerLabel.setSize(120, 20);
mainPlayerLabel.setLocation(400,0);
_frame.add(mainPlayerLabel);
//JTextArea to hold scores
_textArea = new JTextArea();
_textArea.setText(_board.displayScore());
_textArea.setSize(160,140);
_textArea.setLocation(730, 170);
_frame.add(_textArea);
_boardPanel = new JPanel();
_boardPanel.setSize(560, 560);
_boardPanel.setLocation(170, 80);
_boardPanel.setLayout(null);
// _boardPanel.setBackground(java.awt.Color.BLACK);
_frame.add(_boardPanel);
//Button Panel
JPanel buttonPanel = new JPanel();
buttonPanel.setSize(300, 150);
buttonPanel.setLocation(280, 650);
buttonPanel.setBackground(java.awt.Color.blue);
_frame.add(buttonPanel);
//Current Tile Label
_currTileLabel = new JLabel("Current Tile is: ");
_currTileLabel.setIcon(new ImageIcon(NewGUI.class.getResource(_board.getCurrTile().tileType()+".png")));
_currTileLabel.setSize(170, 60);
_currTileLabel.setLocation(20, 620);
_frame.add(_currTileLabel);
//2 input JTextField
JTextField text1 = new JTextField(3);
JTextField text2 = new JTextField(3);
text1.setSize(20, 20);
text2.setSize(20, 20);
text1.setLocation(620, 680);
text2.setLocation(640, 680);
_frame.add(text1);
_frame.add(text2);
//Buttons
JButton buttonPlace = new JButton("Place");
JButton buttonCommit = new JButton("Commit");
JButton buttonRemove = new JButton("Remove");
JButton buttonResign = new JButton("Resign");
buttonPlace.addActionListener(new PlaceListener(text1,text2,_board,guiList,numOfPlayer,this));
buttonCommit.addActionListener(new CommitListener(_board,guiList,numOfPlayer));
buttonRemove.addActionListener(new RemoveListener(_board,guiList,numOfPlayer,this));
buttonResign.addActionListener(new ResignListener(_board));
//Add buttons onto buttonPanel
buttonPanel.add(buttonCommit);
buttonPanel.add(buttonResign);
buttonPanel.add(buttonRemove);
buttonPanel.add(buttonPlace);
buttonPanel.setLayout(new FlowLayout());
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
_frame.setSize(900, 900);
_frame.setLayout(null);
_frame.setVisible(true);
}
public void updateBoard()
{
_boardPanel.removeAll();
//scan and refresh the board configuration.
for(int i = 1; i<13;i++)
{
for(int j = 1; j<13;j++)
{
if(_board.getBoard()[i][j]!=null)
{
for(int e = 65; e<89;e++){
char temp = (char)e;
if(_board.getBoard()[i][j].tileType()==temp)
{
JLabel label = new JLabel(new ImageIcon(NewGUI.class.getResource(temp+".png")));
label.setSize(40,40);
label.setLocation(40+(i-1)*40, 40+(j-1)*40);
_boardPanel.add(label);
break;
}
}
}
}
}
}
public void updateTurn()
{
_turnLabel.setText("Current player is: "+_board.getCurrPlayer());
}
public void updateScore()
{
_textArea.setText(_board.displayScore());
}
public void updateCurrTile()
{
_currTileLabel.setIcon(new ImageIcon(NewGUI.class.getResource(_board.getCurrTile().tileType()+".png")));
}
public static void main(String[] args)
{
Board b = new Board(3,true);
NewGUI gui = new NewGUI(b,1);
b.Place(4, 4);
b.Commit();
b.Place(12, 12);
b.Commit();
b.Place(3, 3);
gui.updateBoard();
}
}
See the last static main class? when I test it , all the update methods work well! But when I use listener to perform the method all. The updateBoard refuses to work.
So it looks like your code might be the problem here. Again EventDispatchThread uses an endless loop to work to pump events so that is obvious, and can be disregarded as the actual problem. You're problem comes from using removeAll(), and instantiating a few thousand labels every time they click the button (What's 13 x 13 x 89-65? 4056!). That's going to cause a lot of redrawing and relayout unnecessarily. So the pause you see is the performance of your code because it's not efficient. Don't believe try this:
public void updateBoard() {
long start = System.currentTimeInMillis();
// existing code goes here
long duration = System.currentTimeMillis() - start;
System.out.printf("UpdateBoard timing: %,d ms%n", duration );
}
If your code is anywhere over 10-100ms it will feel glitchy. In fact 100ms is on the slow side and a human can detect a delay of 100ms.
You probably need to re-evaluate your design, and either reuse the existing labels and simply call setImage() to change them. After all that's the whole point of using a persistent UI component model over using raw paint calls. Instantiate them once and reuse.
You are also creating thousands of images with new ImageIcon() calls too. You probably only need one icon and just have all labels point to the same image that will dramatically reduce your memory usage as well. In fact if you follow my advice I think you'll see dramatic speed and memory improvements.
If you can't find a suitable way to reuse JLabel then consider writing your own component by subclassing JComponent or JPanel (if you plan on using a container) and override paintComponent(). I see you're NOT using a LayoutManager and instead choosing to do everything using absolute positioning. If you are going to do absolute positioning you might want to just paint it yourself. Painting is more lower level interface, but you have full control. You'll have to handle positioning, word wrapping, all yourself. But, it will be very efficient, and you can redraw from a data model.
Since all your doing is draw images in a grid pattern I think drawing those with the Java2D api would be a better idea than instantiating that many JLabels and ImageIcons. If you subclass JPanel you can add JComponents to the panel for things like score, etc. But, draw the grid in the paintComponent() method.

Controlling another class from a different class

I am having a bit of problem regarding Swing. I have a JFrame called FrameMain. Inside it is a JPanel called panelChoices.
When FrameMain is called/created, it fills up the panelChoices object with a number of PanelEntries objects, which is a JPanel with a number of JButtons in it (it is a different class that I wrote).
What I want to do is when I click one of the buttons inside the PanelEntries object, I want to destroy/remove FrameMain, along with the rest of it components (including the PanelEntries object that contains the JButton).
I've tried using super but it returns the JPanel (the PanelEntries object) that holds the JButton and not FrameMain that holds them all together. How can I achieve this?
EDIT: It seems that I am not clear enough, so here's a bit more information from my work. I don't have the actual code right now because I am on a different machine but I hope this will help elaborate my question.
public class FrameMain() {
private JFrame frameMain;
private JPanel panelChoices;
public FrameMain(args) {
createGUI();
loadData();
}
private void createGUI() {
JFrame frameMain = new JFrame();
JPanel panelChoices = new JPanel(new GridLayout(1,1));
frameMain.add(panel);
// removed formatting and other design codes since they are not important.
pack();
}
private void loadData() {
boolean available;
for (int i = 1; i <= 10; i++) {
// do some if/else and give value to boolean available
PanelEntries panel = new PanelEntries(i, available);
frameMain.add(panel);
// more code here to handle data.
}
}
}
public class PanelEntries() extends JPanel {
public PanelEntries(int num, boolean avb) {
JButton button = new JButton("Button Number " + num);
button.setEnabled(avb);
add(button);
// add action listener to created button so that it calls 'nextScreen()' when clicked.
// more code
pack();
}
private void nextScreen() {
// destroy/dispose MainFrame here.
// See Notes.
AnotherFrame anotherFrame = new AnotherFrame();
}
}
Notes:
All classes are inside their own .java file.
I need to know how to dispose FrameMain from the button inside the PanelEntries object, not just disposing a JFrame.
As per the given information,
If you want to exit the application, its not a big deal use System.exit(0); :)
If you mean to dispose the frame, jframe.dispose();
If you want to remove a componet / all components you can use .remove(Component) / .removeAll() etc
If this did not help, please re-write your question with more information.

Java KeyEvents for a KeyPad component

I'm writing a Java application that will have an on-screen number pad available for touch-input. Normal key input will also be available, but I'd like the keypad there for tablets and such. I've made a class that extends JPanel. It has 10 buttons laid out in the normal keypad configuration. Now I'm trying to figure out how to make it act like a regular keypad.
I just don't know how to issue KeyEvents. Here's what I've tried so far:
I tried adding a new KeyListener. In the JPanel, when a button was pressed, the action listener called a method that created a new KeyEvent and sent it to all the KeyListeners that were added to the JPanel. However, no matter how many times I added KeyListeners, the didn't seem to be any associated with the panel.
Another thing I tried was passing the target JTextField to the JPanel and setting a member object to the JTextField. But every time I try to append text to it, the member object is null. It's really perplexing to me.
I'm hoping someone could point me in the correct direction with how to implement this keypad to make it as modular is possible so it can be used inside several different screens.
Thanks in advance!
Brent
You dont need the KeyListener you can associate yourself the outcome effect of pressing a button (its not a key) on the JTextField.
Maybe something like:
New JButton button = new JButton(new KeyPressedAction(mTextField,"0"));
Where
public class KeyPressedAction extends Action{
JTextField tf;
String num;
public KeyPressedAction(JTextField textField,String num){
this.tf = textField;
this.num = num;
}
public void actionPerformed(ActionEvent e){
textField.setText(textField.getText+num);
}
}
I'm writing a Java application that
will have an on-screen number pad
available for touch-input.
So I assume that when the button is "touched" an ActionEvent will be generated. Then I assume you will want to add the character related to the button to a text field. If so, then the following examples should get you started. You don't need to generated KeyEvents, you just respond to the ActionEvents:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonCalculator extends JFrame implements ActionListener
{
private JButton[] buttons;
private JTextField display;
public ButtonCalculator()
{
display = new JTextField();
display.setEditable( false );
display.setHorizontalAlignment(JTextField.RIGHT);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
buttons = new JButton[10];
for (int i = 0; i < buttons.length; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( this );
button.setMnemonic( text.charAt(0) );
buttons[i] = button;
buttonPanel.add( button );
}
getContentPane().add(display, BorderLayout.NORTH);
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
setResizable( false );
}
public void actionPerformed(ActionEvent e)
{
JButton source = (JButton)e.getSource();
display.replaceSelection( source.getActionCommand() );
}
public static void main(String[] args)
{
ButtonCalculator frame = new ButtonCalculator();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
If that doesn't solve your problem, then you should be looking into Key Bindings instead of using KeyEvents.

Categories

Resources