I noticed I can use getName() as part of the trick.
What is java.awt.Component.getName() and setName() used for?
But I don't really have a clue where to start. What type of listener should I use (assuming the textfield / or box is currently blinking / selected)
This is my previous question, and thank you for the help guys.
How do I use requestFocus in a Java JFrame GUI?
I realize that for each component (Textfield) that I am creating, I have to insert a statement like requestFocus (or using transferFocus).
Is it possible to apply this policy to all the fields???
I have several textfields and ComboBox. The problem I hit is that I don't want to write methods for every single field / box.
For example, I write a method like this
private JTextField getFirstNameEntry() {
.... do something
}
because my instructor writes his program like this
private JPanel getJContentPane() {
jContentPane = new JPanel();
jContentPane.setLayout(new java.awt.FlowLayout(FlowLayout.LEADING));
jContentPane.add(makeLabel(" First Name *", 100, 20));
jContentPane.add(getFirstNameEntry(), null);
jContentPane.add(makeLabel(" Middle Initial", 100, 20));
jContentPane.add(getMiddleInitialEntry(), null);
// etc
return jContentPane;
However, to save redundancy (that was my motive at first), say I have a box, I can simply add the following code inside the method above: getJContentPane()
titleBox = new JComboBox(new String[]{"Mr.","Mrs.","Ms.","Dr.","Prof.","Rev."});
jContentPane.add(titleBox);
But doing this, I still need to create a method to do addItemListener
private void setComboBoxFocus() {
titleBox.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = titleBox.getSelectedItem().toString();
System.out.println(titleSelected);
titleBox.transferFocus();
}
}
});
}
However, this doesn't really save redundancy at all. If I have more than one ComboBox to be added, I would have to write another similar method. In fact, even in the case with one ComboBox (titleBox), I would still end up with writing a method for titleBox.
So my question is: is there a way to write a general method that can call focus to all (maybe one for ComboBox type)?
Thank you and sorry for the long post.
Why not take a JComboBox argument to your setComboBoxFocus() method, which allows you to set that listener to any JComboBox you may have? Like so:
private void setComboBoxFocus(JComboBox box) {
box.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = box.getSelectedItem().toString();
System.out.println(titleSelected);
box.transferFocus();
}
}
});
}
Related
I am writing a Java program in which I have an array of buttons (not a calculator!) and I'm looking for an efficient way to know which JButton was clicked. From what I know of Java so far, the only way to do it is to have them all in the same ActionListener and then loop through looking for a match.
Another solution I just thought of would be to extend JButton to include a unique ID number variable in the constructor. It seems that should work when the event object is cast to JButton after an instanceof check. Kind of like using VB's Tag property which is assigned to the index number.
Is there a better/more elegant way?
Is there a better/more elegant way?
yes to use (for almost JComponents) the put/getClientProperty, there you can to set endless number of properties, can be multiplied in contrast with setName / setActionCommand / etc
getClientProperty can be used as unique identificator for Swing Action or EventHandler (rather than to use ActionListener)
Links to the Javadocs: putClientProperty(), getClientProperty()
Here is an example from programm I writing last few months.
I have an enum called Position
public enum Position {
BB, SB, BU, CO, MP3, MP2, MP1, EP3, EP2, EP1;
}
and have some JToggleButtons each of them holding ist own Position.
public class PositionButton extends JToggleButton {
private final Position p;
public PositionButton(Position p) {
this.p = p;
setText(p.toString());
setActionCommand(p.toString());
}
public Position getPosition() {
return p;
}
}
This allows you to create Buttons in a Loop and get value direct from button without comparing:
ActionListener positionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
PositionButton b = (PositionButton )e.getSource();
Position p = b.getPosition();
//do something with Position
}
}
for (Position p : Position.values()) {
PositionButton b = new PositionButton (p);
b.addActionListener(positionListener);
}
The way I've done it before was using actionPerformed for different buttons. I like it more compared to some other ways I've seen.
public void actionPerformed(ActionEvent clicking)
{
if (clicking.getSource() == button[0])
// Do this
if (clicking.getSource() == button[1])
// Do something different
}
Since you built an array, you can throw the ID right where that 0 is and that's your unique ID.
Add a separate action listener for each button.
I have a JPanel on which I've dynamically added quite a few JButtons. All of this is working perfectly. Later on in my program execution, I need to refer back to these buttons and pull out the button text. I'm having trouble figuring out how to refer back to them.
When I created each button, I gave it a unique name. Let's say this is the code where I created the button:
public void createButton(Container parent, String btnName) {
JButton btn = new JButton("xyz");
btn.setName(btnName);
btn.addActionListner(new ActionListner() {
//code
}
parent.add(btn);
}
In another method, I'm trying to retrieve the label on the button since it may have changed at run time. Do I need to keep an array of these buttons as they are created? Or is there a way that I can refer back to them directly?
This is what I was working on, but it's stupid. Can anyone suggest a correct approach?
public String getBtnLabel(String btnName) {
JButton btn = (JButton) btnName;
return btn.getText();
}
If the answer is that I just need to create the array and then iterate over it, that's fine. Just looking for other options.
You need to use a Map<String, JButton> so when you create your dynamic buttons you give them some sort of unqiue name:
//somewhere at the top of your class
private final Map<String, JButton> myButtonMap = new HashMap<>();
public void createButton(Container parent, String btnName) {
JButton btn = new JButton("xyz");
btn.setName(btnName);
btn.addActionListner(new ActionListner() {
//code
}
parent.add(btn);
myButtonMap.put(btnName, btn);
}
And then simply get from the map
public String getBtnLabel(String btnName) {
return myButtonMap.get(btnName).getText();
}
This will obviously throw an NPE if the button isn't defined...
Also you will need to delete from your map when you're done with it otherwise you're asking for a memory leak...
I suggest you to use a Map< String, JButton >.
At creation time you put new button into it with buttons.put( name, btn )
In event handler you use JButton btn = buttons.get( name )
Yes you need to keep references to the buttons. An array would be an option, but since arrays are awkward to use, you should prefer a List.
If you have a a reference to the JPanel containing the buttons, you could get them from it. but that is likely to be rather bothersome.
I would recommend keeping a list of your buttons or a reference to them in a map, however you could do this:
for (Component i : parent.getComponents()) {
if (i.getName().equals(btnName)) {
JButton b = (JButton) i;
// do stuff..
}
}
Using the parent component and iterating over the added components.
I have a JFrame with a menubar, in which i'd like some dynamic menus, as in, depending on the size of the ArrayList with HashLists. The problem here is that i then got a dynamic amount of JMenuItems, so i need a way to get as much variables as HashLists. In this case i made the name of the variable static, but obviously that's not working on the ActionListener, since all MenuItems will have the same ActionListener.
I'm wondering how to solve this, and how to get a menu with a dynamic amount of menuitems which all have unique actionlisteners.
private ArrayList<HashMap> menuLijst;
.
for (HashMap h : menuLijst) {
String vraag = (String) h.get("vraag");
JMenuItem qMenu = new JMenuItem(vraag);
informatie.add(qMenu);
qMenu.addActionListener(this);
}
Thanks in advance.
Depending on what you want to do in your ActionListener, you can either use this, as you do right now and in the actionPerformed you can then use ((JMenutItem)event.getSource()) to see which menu item has been clicked. Alternatively, you could register as many ActionListeners as there are menus, like this:
for (final HashMap h : menuLijst) {
final String vraag = (String) h.get("vraag");
final JMenuItem qMenu = new JMenuItem(vraag);
informatie.add(qMenu);
qMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// here event.getSource() is the same as qMenu
System.out.println("Menu "+qMenu+" with label "+vraag+" has been pressed");
System.out.println("HashMap is "+h);
}
});
}
But to me (and also seeing your previous questions), it seems that you are abusing the usage of HashMap instead of using appropriate new objects. I don't know what else is in your HashMap, let's say that you have 3 keys: "vraag", "answer", "grade", you could create the following class:
public class MyClass {
private String vraag;
private String answer;
private int grade;
// And getters and setters here.
}
And have a List<MyClass> instead of List<HashMap>.
I don't see why you want to use a HashMap for your Strings. If you save an ArrayList of Strings, and loop over them to add them all to the menu, you can add actionListeners to all of them, just as you are doing now.
In your ActionListener, check which button is clicked by looping through the ArrayList, and comparing to the name of the clicked button.
I have a JTable in my program. I want to update it after clicking JButton.
I wrote this:
DefaultTableModel myTable = new DefaultTableModel(celDatas,celNames);
JTable source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {
return false;}};
JScrollPane pane = new JScrollPane(source);
(...)
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
query = "Select sal FROM EMP";
myTable =(DefaultTableModel)source.getModel();
myTable.fireTableDataChanged();
}
The problem is that id doesn't update my data on JTable.
How to resolve this problem?
EDIT:
JTable is displayed in my guy through JScrollPane.
I make now this:
source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {return false;}};
pane = new JScrollPane(source);
I made also a new void, where is getting datas from database + there I define myTable:
void queryConnection() {
(...)
myTable = new DefaultTableModel(celDatas,celNames);
}
I added a JButton, which update my JTable (when we change the query.
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
query = "Select sal FROM EMP";
queryConnection();
}
}
================================================================================
public class Application2 implements Runnable {
private JTable source;
private JScrollPane pane;
private DefaultTableModel myTable;
private JPanel panel;
private String[][] celDatas = null;
private String[] celNames = null;
public void run() {
(...)
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
if(...) {
query = "Select sal FROM EMP";
queryConnection();
}
}
if(query == null) {
query = "Select * from EMP";
queryConnection();
}
source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {return false;}};
pane = new JScrollPane(source);
pane.setSize(f.getSize().width-60,300);
pane.setLocation(30,20);
panel.add(pane);
f.add(panel);
f.pack();
}
void queryConnection() {
//here is connection and downloading datas
myTable = new DefaultTableModel(celDatas,celNames);
}
I hope that it is right now more convenient? ;)
You don't need to call any fireXXX() methods if you're creating a new TableModel, but rather you mainly need to call these if you're writing your TableModel based on AbstractTableModel (you're not).
Your problem lies elsewhere I think. You seem to be creating a new JTable and adding it to a new JScrollPane. Are you adding these components to your GUI (you don't show)? If so, is the container that you're adding to able to accept new components smoothly? Do you revalidate and repaint the container? Is your newly created JTable being displayed in the GUI?
Or, is there a JTable already displayed in your GUI? If so, perhaps all you want to do is set its model rather create a new JTable. I favor this solution as the easiest.
Edit 1
I would do something like so:
Access Database in a background thread and get information from it.
Create a new DefaultTableModel object filling it with data extracted from the database.
I would not create a new JTable if one already exists. Instead I'd simply call setTableModel(...) on the currently displayed JTable and pass in my newly created DefaultTableModel object.
Then I'd sit back and enjoy the big bucks and other fruits of my success.
Edit 2
Ganjira, for us to be able to best help you, we need to understand the problem better, which is why I've requested either full clarification of your problem or an sscce, of which I've seen neither. My problems with understanding your issues include:
Again, do you have a JTable already displayed in your GUI, and now you're trying to change the data that is displayed in the JTable based on data extracted from a database?
If so, why not simply change the model of the existing JTable rather than create a whole new JTable?
If you don't already have a JTable in the application and now you want to display one, you state that your data is not being displayed but don't show code to help us understand why.
If you can answer the first two questions, we may not need an sscce, but if not, please understand that your current post is no where close to being an sscce, in that we cannot run it, we cannot compile it, it doesn't reproduce your problem for us,... I have to wonder if you've even read the link yet as it explains why all of these conditions are important (that and brevity so as not to drown us in a large amount of unrelated code).
No, it is not required that you post an SSCCE, but if we can't help you based on the text in your question and your code snippets, it does offer a better chance of allowing us to understand the problem and find a solution for you.
Edit 3
You state:
JTable's been already in GUI, because it shows the 'beginning of the program'. After clicking JButton I want to change values in JTable. It doesn't change the model of the existing JTable - it doesn't change nothing.
And this confuses me as the best solution is one I've been suggesting all along -- Don't make a new JTable, but instead create a new DefaultTableModel and change the model for the existing JTable. You've yet to mention why you're not trying this, or if you have tried it, how it's not working for you.
I have a program in which I am using 3 things, a checkbox, a combobox and a textfield. The logic works like this if checkbox is enable then combobox and textfield are enable unless not.
Then set some value in the textfield by mulitplying it with the item in combobox.
From the frame - The value of Final Price is Price * Quantity.
Now the issue when I click purchase everything went fine. But when I change the value from Jcombobox it doesn't automatically change the value in final price and remains to be 1200 as in first case. For the value to be changed I have uncheck and then check the Checkbox.
What could be the problem. I have used ItemListner for both checkbox and combobox.
#Override
public void itemStateChanged(ItemEvent e){
Object get = e.getSource();
int multiplier;
int ftotal;
if (e.getStateChange()==ItemEvent.SELECTED){
if(get==chkbox1){
qntbox1.setEnabled(true);
size1.setEnabled(true);
multiplier = Integer.parseInt(String.valueOf(qntbox1.getSelectedItem()));
ftotal = Integer.parseInt(price1.getText()) * multiplier;
fprice1.setText(String.valueOf(ftotal));}
You have to implement ActionListener for your JComboBox:
private static final String command_cbo1 = "ComboBox1";
// ...
public class YourClass implements ItemListener, ActionListener
{
// ...
public YourClass()
{
// ...
qntbox1.addActionListener(this);
qntbox1.setActionCommand(command_cbo1);
// ...
}
// ...
public void itemStateChanged(ItemEvent e)
{
// ...
}
// ...
public void actionPerformed(ActionEvent e)
{
JComboBox cb = (JComboBox) e.getSource();
String s = (String) cb.getSelectedItem();
if(e.getActionCommand().equals(command_cbo1))
{
fprice1.setText("" + (Integer.parseInt(price1.getText()) * Integer.parseInt(s)));
}
// ...
}
// ...
}
not directly to your question
1/ JCheckBox is totally useless, that will be really needed for final calculation(s)
2/ consider that JComponents for Price and Final Price would be only JFormattedTextField, then you can pretty to forgot for Parse#Whatever
3/ consider that JComponents for Quantity would be only JSpinner, but workaround for Number Instance would be litte bit complicated as for JFormattedTextField example here
4/ for nice output put everything to the JTable
5/ for JComboBox I preferred ItemListener not ActionListener, because your problems isn't with proper Listener but with parsing Numbers correct way
Ok got it working. The ActionListner made it work (JComboBox). I guess using ItemListner for too many components made parsing a little confusing, add to that I used too many clauses in the ItemListner scope. Thanks a lot everyone for helping.
#mKorbel : I'll be using your suggestion asap :) and will check JTable and said components. have to go through them since I haven't used it.
#Eng.Fouad : Thanks man for the help.
Just one issue. When I typecast getSelectedItem() to integer it gives NumberFormatException error (runtime). So I have to first change the object to String and then parseit into integer. Any clue why direct conversion is throwing error ?
Here is the working code for the project.
public void itemStateChanged(ItemEvent e){
Object get = e.getSource();
if (e.getStateChange()==ItemEvent.SELECTED){
if(get==chkbox1){
qntbox1.setEnabled(true);
size1.setEnabled(true);
fprice1.setText(String.valueOf(Integer.parseInt(price1.getText()) * Integer.parseInt(String.valueOf(qntbox1.getSelectedItem()))));
}
#Override
public void actionPerformed (ActionEvent ae)
{
Object toggel = ae.getSource();
String check;
if (toggel == qntbox1)
{
check = (String) qntbox1.getSelectedItem();
fprice1.setText(String.valueOf(Integer.parseInt(price1.getText()) * Integer.parseInt(check)));
}