Results 1 to 7 of 7
- 04-03-2010, 08:22 AM #1
Member
- Join Date
- Mar 2010
- Location
- Belgrade, Serbia
- Posts
- 27
- Rep Power
- 0
JComboBox ActionListener and Swing Thread safety
I am developing an application that among other things has two JComboBoxes. It is convenient that both combo boxes has the same action listener. Basically at the most upper level I want to create a JFrame class which will contain all the GUI elements, data storage class which will contain internal data needed for application to run, data access class which will work with files and control class which will control the work of all classes. I want control class to be the action listener for the two combo boxes.
Question one: Is there a smarter way to determine which combo box trigered the event than
Java Code:public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == comboBox1) { comboBox1ControlMethod(); } else if(source == comboBox2) { comboBox2ControlMethod(); } else { JOptionPane.showMessageDialog(null, errorString); } }
Mister Cay S. Horstmann says in his book Core Java 8 Edition that this is possible way to solve the problem but he doesn't recommend it.
Second question: Imagine that my action listener is written in the above fashion. And imagine that comboBox1ControlMethod and comboBox2ControlMethod launch a separate thread which will gather appropriate data do there work and then terminate.
Let say user make a selection in the comboBox2. comboBox2ControlMethod launches the thread which in turn determine which item from the combo box user selected, then read appropriate files, update the internal data class, and that repaint the frame. By repainting the frame I mean only changing the text in several JTextField classes and changing which item is selected in several JComboBoxes. All this components whose data I change like this don't have ActionListener associated with them. I care about these components contest only when the user decided to save his work.
I read in the API that Swing is not thread save.
Can I launch a separate thread to do this work or do I have to do this work in the same thread that controls the GUI.
If I was unclear tell me and I will try to explain better.
Thanks in advance.
-
Regarding your second question: Yes, it's best to use a background thread such as a SwingWorker or a plain vanilla background thread when calling time or CPU-intense processes as long as you take care to call most Swing code from the EDT.
- 04-04-2010, 09:52 AM #3
Member
- Join Date
- Mar 2010
- Location
- Belgrade, Serbia
- Posts
- 27
- Rep Power
- 0
But what it means "as long as you take care to call most Swing code from the EDT". What is most but enough and what is too much. Let say that I have a JPanel which contains JComboBox comboBox and JTextField textField. And let say that inside comboBox ActionListerer I start a thread.
Then inside thread t I callJava Code:public void actionPerformed(ActionEvent e) { t.start(); }
Have I violated thread safety?Java Code://some code textField.setText(someString); //some code
Thanks in advance.
- 04-04-2010, 12:44 PM #4
Member
- Join Date
- Jul 2008
- Posts
- 62
- Rep Power
- 0
> Have I violated thread safety?
any time you access a swing component it is far safer to do it via a
SwingUtilities.invokeLater(..)
which will add it to the end of the Swing thread (EDT)
according to the api, some actions are thread safe, but I wouldn't trust that.
in your first post, when there are only 2 sources, I hate this (in a single listener):
Object source = event.getSource();
I would prefer to add a specific listener to a component.
a calculator with 10 numeric buttons and numerous operands would be different
- 04-04-2010, 10:45 PM #5
Member
- Join Date
- Mar 2010
- Location
- Belgrade, Serbia
- Posts
- 27
- Rep Power
- 0
SwingUtilities.invokeLater seems to be the answer to second problem.
Regarding the first I found the better way to do it. It is convenient for me to have only one class that controls the application. Because both action listeners needs to call the same methods. I will make two inner classes which will be actionListeners and both of them will be able to call the methods of the enclosing class.
If I understood ActionListener correctly I need a class that implement ActionListener interface. That class call it listenClass need to have actionPerformed method. I then add listenClass using addActionListener method to some other class which in this example we will call talkClass.
If I understood event handling only one method of the class can be called when event occurs actionPerformed method.Java Code:talkClass.addActionListener(listenClass);
That means that I either need to have separate class for each event I want to handle or to somehow distinguish the source of the event in actionPerformed method. That is the reason I tried the first solution. It is convinient to have a single event handling class because most methods for handling both events are identical. It is more complicated to have two classes with identical methods or two classes derived from same class that has methods needed for both handler classes.
Now. My brother who is Java programmer but one that had very little need for GUI and event handling, he write mostly server side banking software, tells me that I can have more than one method in a single class that can be called when event occurs.
To try to explain. Let say that I have one listenClass. listenClass has methods called action1 and action2. And let say I have two talk classes talkClass1 and talkClass2. He is convinced that I can set listenClass to be ActionListener for both talkClass1 and talkClass2 but than I can set that when talkClass1 emits the event action1 method is called and when talkClass2 emits the event action2 method is called.
He has very little experience in GUI programming and all that he has are with graphic designer from NetBeans. He does server side software most of the time so he might be mistakening. In case he is not. Can what he is suggesting to me be done? If it can be done how can it be done?
Thanks in advance.
-
This is ugly code, sorry, but it does show one control class delivering more than one action listener...
Java Code:import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class MultListeners { private static void createAndShowUI() { View view = new View(); Control control = new Control(); control.setView(view); view.addActionListener1(control.getListener1()); view.addActionListener2(control.getlistener2()); JFrame frame = new JFrame("Multiple Listeners"); frame.getContentPane().add(view.getMainPanel()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } class View { private JPanel mainPanel = new JPanel(); private JButton button1 = new JButton("Button 1"); private JButton button2 = new JButton("Button 2"); private JTextArea displayArea = new JTextArea(15, 25); View() { mainPanel.add(button1); mainPanel.add(button2); mainPanel.add(new JScrollPane(displayArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER)); displayArea.setEditable(false); displayArea.setFocusable(false); } public void addActionListener1(ActionListener al) { button1.addActionListener(al); } public void addActionListener2(ActionListener al) { button2.addActionListener(al); } public void displayAppendText(String text) { displayArea.append(text); } public JPanel getMainPanel() { return mainPanel; } } class Control { private ActionListener listener1; private ActionListener listener2; private View view; public void setView(View view) { this.view = view; } public ActionListener getListener1() { if (listener1 == null) { listener1 = new ActionListener() { public void actionPerformed(ActionEvent e) { sendText(1); } }; } return listener1; } public ActionListener getlistener2() { if (listener2 == null) { listener2 = new ActionListener() { public void actionPerformed(ActionEvent e) { sendText(2); } }; } return listener2; } private void sendText(int i) { view.displayAppendText("This is being sent by listener number " + i + "\n"); } }
- 04-05-2010, 10:02 AM #7
Member
- Join Date
- Mar 2010
- Location
- Belgrade, Serbia
- Posts
- 27
- Rep Power
- 0
First of all thank you. Writing that amount of code to help me learn. I appreciate it. I don't want to be ungrateful but this is one control class that contains two classes both of which implement ActionListener interface. It is very elegant work around the problem but it is important to me that I understood event handling correctly. I need class that implement ActionListener interface. That class need to implement actionPerformed method which we be called when associated method occur.
Thank you all for your help.
Similar Threads
-
ActionListener NOT working
By zed420 in forum New To JavaReplies: 3Last Post: 12-20-2009, 03:40 PM -
Activate JComboBox 1 when object is selected in JComboBox 2...
By bahumbaba in forum AWT / SwingReplies: 2Last Post: 12-10-2009, 01:58 PM -
ActionListener new user
By AmyHill in forum Java AppletsReplies: 1Last Post: 11-16-2009, 07:15 PM -
How to access the ActionListener
By jboy in forum New To JavaReplies: 3Last Post: 10-15-2009, 06:04 PM -
Inside a Timer thread loop,how to refresh a JTable in swing
By neha_negi in forum Threads and SynchronizationReplies: 3Last Post: 09-04-2009, 01:45 AM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks