Scala swing panel disappears when trying to change contents (only when running a Thread) - multithreading

So I'm writing a boid simulation program as a project for school. My program supports multiple different groups of these boids that don't flock with other groups, they all have different settings which I do by adding a BoxPanel to the main GUI of the program when a new tribe is made, and those BoxPanels have a settings button that opens a new frame with the groups settings.
This works perfectly when I start the program up and add all the pre defined tribes that are in the code. Now I made a new part of the GUI that let's you make new groups of these boids and adds them while the simulation is running, and here is when the problems start for me.
For some weird reason it adds the group just fine, with the right settings in to the simulation but it wont add the BoxPanels to the main GUI. It makes the whole settings bar that I have in the side of my simulation disappear completely. I tested this out and if I add the tribes in the beginning of my calculation thread it does the same thing, so this seems to be a problem with multiple threads and swing. Any ideas what is causing this or how to fix this? I am completely perplexed by this.
tl;dr: The code below for adding tribes works fine when I haven't started the thread but if I try to use it after starting the thread the optionPanel appears empty.
Here's the code that adds the BoxPanels to the main gui:
def addTribe(tribe: Tribe) = {
tribeFrames += new TribeSettingFrame(tribe)
tribeBoxPanels += new TribeBoxPanel(tribe)
this.refcontents
}
private def refcontents = {
top.optionPanel.contents.clear()
top.optionPanel.contents += new BoxPanel(Orientation.Vertical) {
tribeBoxPanels.foreach(contents += _.tribeBoxPanel)
}
top.optionPanel.contents += new BoxPanel(Orientation.Horizontal) {
contents += top.addTribeButton
}
top.optionPanel.contents += new BoxPanel(Orientation.Horizontal) {
contents += top.vectorDebugButton
}
}
new Thread(BoidSimulation).start()
Oh and I tested if it really adds the contents that it should by printing out the sizes of the contents, and everything matches fine, it just won't draw them.
EDIT: After some digging around it really seems to be a thing with updating swing from a Thread. A lot of places suggest to use SwingWorker but from the info I gathered about it I don't think it would fit in my program since it is a continuous simulation and and I would have to keep making new SwingWorkers every frame.
EDIT2: Tried calling the method from the thread like this:
SwingUtilities.invokeLater(new Runnable() {
override def run() {
GUI2D.addTribe(tribe)
}
});
Didn't make any difference. I am starting to think that this is a problem with how I use TribeBoxPanel and TribeSettingFrame. These are objects that both contain only one method that returns the wanted BoxPanel or Frame. Is this implementation bad? If so what is the better way of creating dynamic BoxPanels and Frames?

Swing is not thread-safe.
Repeat after me.
Swing is not thread-safe.
Hear the chorus? Swing is not thread safe There is official documentation.
There is a very simple workaround given as well.
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
// your stuff
}
});
In Scala, this is supported as:
Swing.invokeLater(/* your stuff */)

First you should let the UI thread handle all UI manipulation.
The simple way should be following Scala-Code:
Swing.onEDT { GUI2D.addTribe(tribe) }
But as you already noted, this won't solve your problem. I had a very similar problem where I only changed the text content of a Swing.Label and it sometimes simply disappeared.
It turned out that it only disappeared, when the text was too long to display it inside the Area which the Label initially reserved for itself. So one way around your Problem could be to give the optionPanel a bigger initial size when you create it.
Swing.onEDT { top.optionPanel.preferredSize = new Dimension(width,height) }
I'm not quite sure whether this has to be set before the component is first drawn (before Frame.open() is called).

Related

javafx thread to update a listview

I'm trying to do a simple chat application on javafx
my actual problem is the thread to insert updates into a observablelist and set it on a listview
the code im using :
String message_reçu;
try {
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
message_reçu = in.readLine();
if (message_reçu != null) {
messagesReçus.add(message_reçu);
}
if (message_reçu.equals("QUIT")) {
break;
}
}
in.close();
out.close();
socket.close();
I did this inside of a runnable class and once the server fire a msg the thread insert the msg on the list and shows on the listview but the thread dies instead of keep the work
I did a search on it and every one says to use a runlater but I’m completely lost there I did declare a runlater but I’m not sure how to execute it so any help is welcome
Thanks
Other Answers
This question is largely a duplicate of the following questions, so also refer to the answers to those:
Usage of JavaFX Platform.runLater and access to UI from a different thread
Platform.runLater and Task in JavaFX
Solution
Your question is little more specific than those though, so I'll provide some extra info.
For your particular code you want to wrap the add call in Platform.runLater:
Platform.runLater(new Runnable() {
public void run() {
messagesReçus.add(message_reçu);
}
});
Everything else in your example stays as it is.
Background Information
JavaFX UI updates must be made on the JavaFX application thread or there is a high likelihood that your program will malfunction in unexpected ways.
The ListView control listens for changes to the ObservableList backing the ListView cell values. When that list changes, a UI update is immediately triggered on the thread the originally updated the list.
Once you wrap the list modifications in Platform.runLater, you ensure that the subsequently triggered UI update is performed on the JavaFX application thread rather than your user thread.

After adding multi threading to my app, VS2010 will not remove file handle after stopping debugging

today I've added multi threading to a windows forms application. On my UI thread I'm starting a thread via new Thread() {...}).Start(); Which itself will call a Method which uses ThreadPool.QueueUserWorkItem(). After the Method is called the thread will wait on a queue until a specific item is returned and the thread exits:
new Thread(o =>
{
s.SimulateChanges();
Boolean run = true;
while (run)
{
SimulationResult sr = queue.WaitDequeue();
//EOF is a static property which will be returned
//if the queue is at its end so I can break the while loop
if (SimulationResult.EOF.Equals(sr))
{
run = false;
continue;
}
this.simulationProgressBar.BeginInvoke((Action)delegate()
{
if (sr.IsDummy && this.simulationProgressBar.Value < this.simulationProgressBar.Maximum)
{
/*...*/
}
else
{
this.resultListView.AddObject(sr);
}
});
}
this.simulationProgressBar.BeginInvoke((Action)delegate()
{
this.ToggleSimulationControls(true);
});
}).Start();
And that is the code of the method called:
public void SimulateChanges()
{
ThreadPool.QueueUserWorkItem(o =>
{
foreach (IColElem elem in collection.AsEnumerable())
{
/*lot of code*/
queue.Enqueue(new SimulationResult() { IsDummy = true });
}
log.Debug("Finished!");
queue.Enqueue(SimulationResult.EOF);
});
}
My Queue is a self written class allowing a thread to wait on dequeue until an object ins enqueued.
Everything is working fine, except that if I stop debugging (using stop debugging or simply closing the application) I can't rebuild my application as VS2010 doesn't remove the file handle. I believe it has something to do with my threads not exiting correctly. Is their any way I can assure this?
Thanks for any advice :-)
Hard to explain all aspects of the question. But you are making a pretty common mistake, often made by programmers when they first start using threads. You are not making sure that the thread stops running when the user closes the main window. It is an easy mistake to make, the UI thread takes care of a lot of grunt work. Including automatically terminating when the main window of your app is closed by the user. So at least part of your problem is that you did manage to close the main window. But didn't actually terminate the process. Building cannot work, your program's EXE is still in use.
Properly shutting down a thread can be very difficult, given that the user will close the window regardless of what that thread is doing. It could be catatonic, buried deep inside an operating system call and waiting for it to complete. Tough to ask it to quit when it isn't executing code.
There is a very simple solution, at least good enough to keep going with your project or solve half the problem you have. You can mark the thread as "kill automatically at program termination" and the CLR will take care of it. Use the IsBackground property, like this:
var t = new Thread(o =>
{
// Lotsa code
});
t.IsBackground = true;
t.Start();
But do keep in mind that there's nothing graceful about that kind of kill. If you are writing a file or talking to a server then that's going to cause a partially written file or a very confused server. Otherwise not different from killing the program with task manager.

How to make an assert window in QT

I currently have a very long running GUI-Application in QT. Later that application is going to be tested and run on an embedded device without a keyboard in full screen.
For easier debugging I have a custom assert macro, which allows me to ignore certain asserts (may include known buggy parts I have to work around for now) etc. For the time being I just print something on the console such as "Assertion: XXXX failed; abort/ignore". This is fine when I start the application within a console, but ultimately fails when I run it on the final device. In that case the assert will just block the main thread waiting for input and make the GUI hang badly without hope for recovery.
Now I am thinking about how to remedy this situation. One Idea is to just have the assert crash, as the standard assert does. But I do not really like that Idea, since there are a lot of know problems, and I've always found ignorable asserts very helpful when testing applications. Also I would have to put the messages into a separate file, so I can later see what happened while testing. Reading these files afterwards is possible, but I would prefer a simpler way to find out what went wrong.
The other idea was to make a window instead. However the asserts may be triggered in any thread and I can only create new windows in the GUI thread. Also the main event loop may be blocked by the assert, so I cannot be sure that it will handle the events correctly. I would somehow need a fully responsive stand-alone window in a separate thread, which only handles a few buttons.
Is this somehow possible in QT4?
You may post events to main thread to display dialog and wait for an answer from non-gui threads, or just display dialog if current thread is app thread
int result = -1;
if ( QTrhead::currentThread() == QCoreApplication::instance()->thread() )
{
result = AssertHandler->ShowDialog(where, what, condition);
}
else
{
QMetaObject::invokeMethod(AssertHandler, "ShowDialog", Qt::QueuedBlockingConnection, Q_RETURN_ARG(int, result), Q_ARG(QString, where), Q_ARG(QString, what), Q_ARG(QString, condition);
}
if (result != 0)
{
// handle assert
}
The AssertHandler is QObject based class with slot int ShowDialog(const QString &where, const QString what, const QString &condition). It should display dialog with assert data and buttons assert/ignore. Returns 0 when user pressed ignore, otherwise returns non zero value.

Java Thread Safety v Displaying a Dialog from separate Thread

Hi noticed some code in our application when I first started Java programming. I had noticed it created a dialog from a separate thread, but never batted an eye lid as it 'seemed to work'. I then wrapped this method up through my code to display dialogs.
This is as follows:
public class DialogModalVisibleThread
extends Thread {
private JDialog jDialog;
public DialogModalVisibleThread(JDialog dialog, String dialogName) {
this.setName("Set " + dialogName + " Visable");
jDialog = dialog;
}
#Override
public void run() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
}
Usage:
WarnUserDifferenceDialog dialog = new WarnUserDifferenceDialog( _tableDifferenceCache.size() );
DialogModalVisibleThread dmvt = new DialogModalVisibleThread( dialog, "Warn User About Report Diffs");
dmvt.start();
Now, as far as I am now aware, you should never create or modify swing components from a separate thread. All updates must be carried out on the Event Dispatch Thread. Surely this applies to the above code?
EDT on WikiPedia
However, the above code has worked.
But lately, there have been countless repaint issues. For example, click on a JButton which then calls DialogModalVisibleThread to display a dialog. It caused buttons alongside the clicked button not to redraw properly.
The repaint problem is more frequent on my machine and not the other developers machine. The other developer has a laptop with his desktop extended onto a 21" monitor - the monitor being his main display. He is running Windows 7 with Java version 1.6.0_27.
I am running on a laptop with Windows 7 and Java version 1.6.0_24. I have 2 additional monitors with my desktop extended onto both.
In the meantime I am going to upgrade to Java 1.6 update 27.
I wondered if the above code could cause repaint problems or are there any other people out there with related paint issues?
Are there any easy ways to diagnose these problems?
Thanks
So, you're breaking a rule, having problems, and wondering if these problems could be cause by the fact that you broke the rule. The answer is Yes. Respect the rules!
To detect the violations, you might be interested by the following page: http://weblogs.java.net/blog/2006/02/16/debugging-swing-final-summary
The easiest way to check if your problems are being caused by breaking the rules is to fix them (You should fix them anyway :-)
Just use SwingWorker.invokeLater() from the thread you want to update to UI from to easily adhere to Swing's contract. Something like this should do the trick:
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
});
}
EDIT: You should make the 'jDialog' variable final for this to work.

Silverlight 5: print outside the UI thread?

Is it possible to print in Silverlight without blocking the UI thread?
I have to print a lot of pages, and consequently my UI freezes for a while. I would like to print on a background thread instead (and update a progress bar if possible), but can't figure out how.
I tried calling the Print() method of my PrintDocument inside the DoWork() method of a BackgroundWorker, but that gives me an UnauthorizedAccessException "Invalid cross-thread access".
It seems that even initiating a PrintDocument is not possible outside the UI thread:
PrintDocument pd = new PrintDocument(); in BackgroundWorker.DoWork() throws the same exception.
I found a lot of posts where people say that printing has to happen on the UI thread, but no documentation of this. I'm new to multithreading, so any pointers in the right direction would be appreciated.
I had this problem and came across this question which unfortunately didn't have the answer i was hoping for. But I thought that for anyone else who comes across this problem, this may at least shed some light.
I was following this article on printing in Silverlight, It works like a charm for regular printing on the UI Thread, but for actually trying to print on a separate thread I don't think it's possible. I switched out the last line of code in the example
printDocument.Print("SLPrintDemo document");
with an alternate one to see if it would work
new Thread(() => printDocument.Print("SLPrintDemo document")).Start();
To see if the print job itself would spawn in a separate thread. However though the code compiles and runs fine, the document does not print. The reason seems to be that once the Print command is fired, it then fires up the printing options dialog for choosing printer and other options etc. At this point it is no longer on the UI thread so nothing happens ( No exceptions, so i'm assuming they're swallowed somewhere)
So as far as I can tell at the moment, there is no way to print in Silverlight that is not in the UI thread.
Use Dispatcher for updating your UI. For example:
Dispatcher.BeginInvoke(() =>
{
ProgressBar.Value = 100;
});

Resources