To stop my application from flickering, I tried to activate DoubleBuffering for all of my controls and subcontrols.
To achieve this, I added the follwoing codesnippet in my mainform:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; //WS_EX_COMPOS
return cp;
}
}
The problem is, that with WindowsXP the cpu-load becomes almost 100% and keeps up. No problem on Windows7.
It looks for me, as it is the very same problem as in this question. Is there a "easy" solution in C#? Or asked in a different way -> What usually causes this behaviour? So I can find out the problem in my application.
UPDATE: Maybe some more information to help you folks help me. What I am trying to do is showing a semi-transparent form ontop of the mainform with an progressbar. This "progressBarForm" is in a second thread to have this progressbar running. On Win7 everything works fine, as mentioned above with WinXP (.net4, activated desktoptheme) there is 100% cpu-load after the progressbar was shown once - also the acutal payload-function needs much longer to complete - maybe because of the high-cpu-load done by the progressbar. Where and what should I check again? Some ideas?
Btw.: I don't think the thread is a problem, as when I show the form in the mainthread and don't refresh anything, the result (high cpu-load) is the same...
Related
I am working on a project than involves making an image appear and then disappear after a fixed time. I thought that the correct function for that purpose would be Thread::Sleep() but it doesn't seem to work.
this->pictureTConf->Visible = true;
Thread::Sleep(5000);
this->pictureTConf->Visible = false;
With this code, the picture doesn't appear at any moment. Any thoughts? Thanks.
PD: Using Visual Studio, Windows forms and VC++.
Setting a member variable to true isn't enough because your call to Sleep() prevents the code from running the message loop. Try this instead: (This is just for sample purposes, you shouldn't do this in a "real" application.)
this->pictureTConf->Visible = true;
this->pictureTConf->Refresh();
Thread::Sleep(5000);
this->pictureTConf->Visible = false;
this->pictureTConf->Refresh();
Also, as Chuck pointed out, if you use a timer, you shouldn't need the calls to Refresh(). Everything will just work.
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).
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.
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;
});
I've got a Qt application that has two main windows. On Linux, when one main window brings up a modal dialog, it comes up behind the other main window. What can I do to cause the dialog to always come up on top of ALL main windows?
NOTE: This only happens on Linux. We build this app on MacOSX as well, and the problem does not occur there.
Here's the code that brings up the dialog. The stuff in the #if is all the things I've tried to bring the window forward. I've tried various combinations and orders of these things.
QMessageBox dialog;
dialog.setIcon( QMessageBox::Information );
dialog.setWindowTitle( _documentName );
dialog.setText( tr("This document has unsaved changes. Do you want to save before closing?") );
dialog.setInformativeText( tr("Your changes will be lost if you don't save them.") );
dialog.setStandardButtons( QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel );
dialog.setDefaultButton( QMessageBox::Save );
dialog.setFixedSize( dialog.size() ); // non-resizable window
#if STUFF_I_TRIED
dialog.show();
dialog.setVisible(true);
dialog.open();
dialog.activateWindow();
dialog.raise();
#endif
int result = dialog.exec();
I realize that exec() should be all I need to show the window. My idea in calling show() or open() was just to allow activateWindow() or raise() to take affect. Just foolin' around trying to get that damn dialog to come forward.
TIA for any help!
All the sequcence between #if 1_ and #endif looks pretty weird to me.
Normally, to show modal dialog, only exec() is needed:
QMessageBox msgBox;
msgBox.setText("They killed Kenny, again.");
int ret = msgBox.exec();
Reference.
You are doing quite a bit of things between your #if 1, that is likely confusing X11.
You need only ONE of those. Since you are working with Mac and X11, I suspect you want to use open() and get a sheet.
IIRC, show() vs. open() causes different window flags to be set, so
calling them right after each other may get the window into a strange
state. Also calling show() or open() should always activate or raise the window if it is a dialog, which QMessageBox is.
Try only using one of these and seeing what happens.