Java JFrame removeall hangs an application - java

I have the following code:
ActionListener listenerComboVehicle = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
comboVehicle.removeActionListener(listenerComboVehicle);
frameCrewSelection.removeAll();
frameCrewSelection.add(formCrewSelectionForm(SpaceObjectArray.findMannedByName(comboVehicle.getSelectedItem().toString()))); //Create some controls (Jcombobox comboVehicle included) and assign listeners to them.
formComboCrews(); //Modify JCombobox controls content
}
};
And my application hangs on the following code in EventDispatchThread.java:
void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
addEventFilter(filter);
while (doDispatch && cond.evaluate()) {
if (isInterrupted() || !pumpOneEventForFilters(id)) {
doDispatch = false;
}
}
removeEventFilter(filter);
}
The while loop is infinite and it hangs my application. When .removeAll() is absent, the application doesn't hang but I get new controls over old controls. I've found a workaround by disposing a frame and creating it again but it looks nasty. Additional code will be provided if needed. Please help.

Moved from comments for better view:
frameCrewSelection.getContentPane().removeAll(); frameCrewSelection.setContentPane(formCrewSelectionForm(SpaceObjectArray.findMan‌​nedByName(comboVehicle.getSelectedItem().toString())));
made it work.

Related

Java: How to wait for the listener to execute the next line?

I have a problem because I have the next code in my main class:
SelectCalculatorWindow selectCalculatorWindow = new SelectCalculatorWindow();
CalcWindow calcWindow;
if (selectCalculatorWindow.getOption() == SelectCalculatorWindow.BASIC_OPTION) {
calcWindow = new CalcWindow(0);
} else if (selectCalculatorWindow.getOption() == SelectCalculatorWindow.PSEUDOSCIENTIFIC_OPTION) {
calcWindow = new CalcWindow(1);
}
And, in other class (SelectCalculatorWindow), I have this:
public SelectCalculatorWindow() {
initComponents();
instantiateListener();
}
private void instantiateListener() {
acceptBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(basicCalculatorRbtn.isSelected()) {
setOption(BASIC_OPTION);
} else if (pseudoscientificCalculatorRbtn.isSelected()) {
setOption(PSEUDOSCIENTIFIC_OPTION);
}
setVisible(false);
}
});
}
So, I want that condition sentences that I wrote in the main class execute only if user click the button, and I don't know how to do it
You haven't posted a valid minimal reproducible example program yet, and so I can only guess, but having said that, my guess is that SelectCalculatorWindow creates and displays a JFrame which is a non-modal application window, which is not what you want. Instead you will want to display a modal child-window, or dialog, such as a modal JDialog. When you use this, it pauses application code flow in the calling code until the dialog has been dealt with, and so allows your program to pause waiting for the user to make their selection, and then resume the code once the selection has been made.
A JOptionPane is an example of a type of modal dialog, but using a JDialog, you can create windows as varied and flexible as a JFrame, but with the advantages noted above.

Impossible Java Memory Consistency Error

first of all I'm not an English native speaker so I apologize for any eventual “weird” writing.
I'm developing a Swing Java application on Eclipse that updates a Jpanel. This panel contains several sub-panels, and I'm constantly switching the panels “modes”, what happens to be a MouseListener changing so they respond in a slightly different manner to the user mouse inputs.
Regardless of what the application do, it's happening an error that seems to have no logical explanation to me. At some point in my code I try to update the panels to what I called neutralMode. This happens on the following method:
//Guarded block (see http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)
private synchronized boolean waitsForUserSatisfactionAnswer()
{
while(!userIndicatedSatisfaction)
{
try {
wait();
} catch (InterruptedException e) {}
}
userIndicatedSatisfaction = false; //reset for future new query
getObjectSetVisualizationPanel().neutralMode();
//getObjectSetVisualizationPanel().queryPatternMode();
return userSatisfied;
}
This updating doesn't work (the call to neutralMode() dont do what is expected). However the call to queryPatternMode() (commented on the line right below) works perfectly. So I decided to COPY queryPatternMode()'s body and PASTE it on neutralMode()'s body ECXATLY THE SAME! AND IT STILL DOESNT WORK!
The methods code is like this:
public void queryPatternMode()
{
System.out.println("Inside queryPatternMode!!!");
System.out.println("panels.size(): " + panels.size());
for (DigitalObjectPanel panel : panels)
{
System.out.println("Inside the loop!!!");
panel.resetBehavior();
panel.setQuerySelectionBehavior(gui);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.validate();
}
});
}
}
public void neutralMode()
{
System.out.println("Inside neutralMode!!!");
System.out.println("panels.size(): " + panels.size());
for (DigitalObjectPanel panel : panels)
{
System.out.println("Inside the loop!!!");
panel.resetBehavior();
panel.setQuerySelectionBehavior(gui);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.validate();
}
});
}
}
What happens is that, when I call neutralMode(), the “panels” collection happens to be empty (panels.size() equals zero). However when I call queryPatternMode() instead, the collection happens to have it's expected size (20 panels). But both methods are equals, and both are called from the same place!!!
What it could be??? Is there any possible explanation for that??
It definitely looks like a synchronisation issue. You should check how many threads are accessing the collection 'panels'.
It is just a stroke of luck that it works for you with queryPatternMode() all the time, and not with neutralMode(). On another fine day, it might be other way around.

Can't get ItemListener to work for JCheckBox

I am using this code to create a JCheckBox
private final JCheckBox cbDisplayMessage = new JCheckBox("Display");
cbDisplayMessage.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getItemSelectable() == cbDisplayMessage) {
if(cbDisplayMessage.isSelected()) {
cbDisplayMessage.setSelected(false);
} else {
cbDisplayMessage.setSelected(true);
}
}
}
});
When I run this it causes an StackOverflow error on setSelected(true). Can't figure out what I am doing wrong. Any ideas appreciated....
You can try with ActionListener instead of ItemListener as shown below without causing StackOverflow error.
cbDisplayMessage.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (cbDisplayMessage.isSelected()) {
cbDisplayMessage.setSelected(false);
} else {
cbDisplayMessage.setSelected(true);
}
}
});
There is no need to check the source of the event again because you are sure that you have added this listener on the same object. This is required only if same listener is added for more components.
-- EDIT--
Now Your requirement is clear to me. If you want to toggle the state of the check box then there is no need to do it using listener because that's the default behavior of the check box.
Your listener is called every time the state changes, but you trigger a new state change from within that listener, so each state change results in that listener being called over and over again until your stack is full. Your setup has to be a bit more complicated to do something like that - if you want to change the state of the component you're listening to, you'll want to remove its listener(s), fire your programmatic state change, then re-add them.

Multiple JFrame application, how do I bring them all to front together?

My users like having multiple JFrames; it allows them to resize the different components and place them wherever they want on the screen. However, I have a request to make all the child windows come to the front together... in other words, lets say they maximize another window in front of all the windows, and then use the task bar to click on just one of the JFrames. How can I set it so that they all come to the front? Note: it is also possible to close the child windows; if they are actually hidden, I do not want them to come to the front. I have a class ApplicationModel that keeps track of whether a window is hidden or not.
Things I've tried:
Using windowActivated() and focusGained() to try to bring them all to the front. This usually results in an infinite loop. The problem is that my eventing framework sends these requests off the Event Dispatch Thread, so any sort of blocking with an AtomicBoolean doesn't last long enough.
The main problem is not that I can't make them come to the front... I have made them come to the front. The problem is that they KEEP trying to come to the front, as bringing a window to the front throws the focusGained and windowActivated events, which creates an endless loop...
Making one window the master, and making the others a JDialog. Unfortunately, either the windows are modeless (and therefore don't come to front with the master window), or they are modal, (and therefore block the master window).
How can I fix either of these problems, or is there an entirely different third solution?
You can use a boolean field as a flag to prevent the infinite loop:
private boolean movingAllFramesToFront;
public void windowActivated(WindowEvent event) {
if (movingAllFramesToFront) {
return;
}
movingAllFramesToFront = true;
List<Frame> frames = getAllApplicationFrames();
for (Frame frame : frames) {
if (!applicationModel.isHidden(frame)) {
frame.toFront();
}
}
event.getWindow().toFront();
event.getWindow().requestFocus();
EventQueue.invokeLater(new Runnable() {
public void run() {
movingAllFramesToFront = false;
}
);
}
Another thing you can try is the new autoRequestFocus property introduced in Java 1.7. I have never tried using it, but here's my understanding of how it works:
public void windowActivated(WindowEvent event) {
final List<Frame> frames = getAllApplicationFrames();
for (Frame frame : frames) {
if (!applicationModel.isHidden(frame)) {
frame.setAutoRequestFocus(false);
frame.toFront();
}
}
EventQueue.invokeLater(new Runnable() {
public void run() {
for (Frame frame : frames) {
if (!applicationModel.isHidden(frame)) {
frame.setAutoRequestFocus(true);
}
}
}
);
}
I have an application with a lot of windows and had a problem similar to yours. My workaround is:
#Override
public void windowActivated(WindowEvent e) {
if (e.getOppositeWindow() == null) {
//front every window
}
}
First I created a class "SlveFrame" (Slve being the name of my app), a child of "JFrame".
public class SlveFrame extends JFrame implements WindowListener {
static ArrayList<SlveFrame> frames = new ArrayList<SlveFrame>();
public SlveFrame () {
addWindowListener(this); / /to make JFrame fire WindowListener's method
}
/ /... every method added from WindowListener
#Override
public void windowActivated(WindowEvent e) {
if (e.getOppositeWindow() == null) { // return null if window is not from my (or Your) work
for (SlveFrame frame : frames) { // if you have no idea what this is, look for "for each loop java" in google
frame.toFront();
}
}
}
/**
* The use of SlveFrame is almost the same as Jframe
*/
#Override
public void setVisible (boolean b) {
if (b)
frames.add(this);
else
frames.remove(this); // may raise an exception if you're not careful
super.setVisible(b); // or your window will simply not be visible.
}
#Override
public void dispose () {
frames.dispose(this) // may raise an exception you'll want to handle
}
}
The trick being that WindowEvent.getOppositeWIndow() returns a Jframe if the JFrame (or child class) is from your own program, meaning that if you switch to another program or app (such as eclipse, Firefox or a text editor) then back to any of your windows, then a call to getOppositeWindow() will return a 'null'. A simple if (e.getOppositeWindow()) makes it fairly easy to determine whether your window gain focus in condition that would require you to bring every window to the front, or rather to let everything be.
The overriding of setVisible (boolean b) and dispose () are optional but allow the dev to use it as a regular window.
I hope i could be of some help. Sincerly ~a lama

Problems with ActionListener and SystemUtil.invokeLater

I have look all over the web, and found no solution to my problem. For a AP Comp Sci project, I am making a Set of games, that will be run from a JFrame with JButtons. I have the games all ready, along with action listeners, but the games dont launch properly. The JFrame and JButtons are all setup correctly too.
private static class TetListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
GameCenter.quit();
GameCenter.startTetris();
}
}
GameCenter.quit() does nothing but run JFrame.dispose(), and GameCenter.startTetris(); constructs a new Tetris object, then run the play() method to start the game. All of Tetris is coded properly and works correctly when it is run in the main method (outside the actionlistener). But as soon as I put it in the ActionListener, it fails to be constructed properly. I tracked the problem down to:
public BlockDisplay(BoundedGrid<Block> board)
{
this.board = board;
grid = new JPanel[board.getNumRows()][board.getNumCols()];
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() // <<<<<<<<<<------------------- Problem Here
{
public void run()
{
createAndShowGUI(); // <<<<<<<<<<<<-------- Never Run
}
});
//Wait until display has been drawn
try
{
while (frame == null || !frame.isVisible()) // <<<<<<<-------- Never Resolved
{
Thread.sleep(1);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
So the program always hangs. I also made a Pacman game that uses this SwingUtilities.invokeLater, so it doesnt work either. I cant figure out why this is happening or how to fix it.
Any help is appreciated. Let me know if you need any more info.
If the thread that runs SwingUtilities.invokeLater is already the swing event thread and you run in this while loop, yup, your application will hang.
Get rid of the while loop.

Categories