|
I have a graph created in a zedGraph control on my form.
A separate thread handles the data collecting and preparing for graph purposes.
When I hit start I can see the zedGraph control resizing alright but i cant see the curves.
If I leave the focus of the form and then return to it(say with alt_tab or the mouse)
I can see the curves.
It operates in a manner that led me to think of a refreshing problem.
can you please advise me what to do?
thank you.
|
|
|
|
|
That implies that your graph is only redrawn when invalidated, so call Invalidate() either on the whole form or the graph control when you know the graph is ready to be displayed.
|
|
|
|
|
I tried Invalidat() and I tried refresh(), none of which does the trick.
It seems like the axis are changing correctly and only the curves themselves don't show.
Any other ideas?
|
|
|
|
|
Have you tried zedGraph1.Update()?
|
|
|
|
|
Also, if I call hide() and then show(), this also doesn't help,
only if i point to the main form(for instance) and back to my graph, I can see the change in the
curves.
|
|
|
|
|
|
yes I also did that, it didn't help.
after the graph is ready for display I called this.invalidate() on the form, it didn't help.
I called invalidate on the control, it also didn't help,
I called this.refresh(), also didn't help.
now I tried doing a showDialog() on this(my form), and in the dialog form I can see the curves.
it is not a solution acceptable, but it might imply on the reason for my problem,
and on how to fix it.
Does it help? can you think of something else I can try to do?
|
|
|
|
|
Hello,
If you are pathing the values from a different thread to the ZedGraph Control, you have to use "Invoke".
After this is done you should call:
yourzedGraphcontrol.AxisChange();
yourzedGraphcontrol.Invalidate();
All the best,
Martin
|
|
|
|
|
Hey Martin,
on what do I use Invoke()?
|
|
|
|
|
Hello,
gizmokaka wrote: on what do I use Invoke()?
The parent object of the ZedGraphControl (Form or UserControl).
Example code for Form on which the ZedGraphControl is placed:
private delegate void UpdateZedGraphDelegate(object values);
public void UpdateZedGraph(object values)
{
if(this.InvokeRequired)
{
this.Invoke(new UpdateZedGraphDelegate(UpdateZedGraph), new object[] {values});
return;
}
}
All the best,
Martin
|
|
|
|
|
Sorry for the newbe questions but I am quite novice in this type of high level programming.
I don't really understand how the code you sent me works,
can you please explain it a bit, and tell me where my new thread comes in to action?
I have my class which collects all the data for the graph into a member control,
I want that member control to be updated from another thread, how do I use the code you
presented to do so?
thank you .
|
|
|
|
|
Hello,
The thread where you collect the data for the Graph has a referenz of the "memberControl"?!
The "memberControl" holds the ZeGraph Control?!
If you now add a/the method like I gave you before, to the memberControls code,
the thread should be able to call this method.
The thread can now path the value for the graph to this method.
The "InvokeRequired" property of the Control class does a check if it's neccesary to Invoke the method.
Reason is, that you also could call the method from inside the thread, and there the invoke is not needed.
In case of "InvokeRequired" is "true" the method will be called again by the "Invoke" call, and next time "InvokeRequired" will be "false". (debug it, for easier understanding).
At the first call ("InvokeRequired" is "true") the code after the if statement is not going to be executed.
After Invoke you can use the pathed datas to set the ZedGraph properties.
Hope it helps!
All the best,
Martin
|
|
|
|
|
thank you very much.
I am reading it now and hope I will understand and utilize successfully what you have written.
thanks a lot.
|
|
|
|
|
Hello again dear Mr Martin,
First of all I want to thank you a lot for your help it was very, informative, and it helped me with
a different problem I encountered.
Still it did not solve my refresh problem. and y?
it's not happening to me because a different thread is calling the function, it happens even if everything is done in the same thread.
You see, I have me a function that creates data for the zedGraph control to show.
everything is working fine, and the underlying graph is probably OK.
the problem is that I need to move attention form the form and return, when I return
I can see the changes.
I will patch the snippet here, maybe this will help:
#region ZedGraph_Log Analysis
private void lgAnalysisZedGraphControl_Load(object sender, EventArgs e)
{
CreateGraph(lgAnalysisZedGraphControl);
SetSize();
}
private void SetSize()
{
lgAnalysisZedGraphControl.Location = new Point(10, 10);
lgAnalysisZedGraphControl.Size = new Size(lgAnalysisPanelShowGraph.Width - 10, lgAnalysisPanelShowGraph.Height - 10);
}
delegate void createCurvesHandler(ZedGraphControl zgc);
private void CreateGraph(ZedGraphControl zgc)
{
zgc.GraphPane.CurveList.Clear();
zgc.GraphPane.XAxis.Type = AxisType.Date;
Thread startCreateCureves = new Thread(delegate() { createCurves(zgc); });
startCreateCureves.Start();
}
private void createCurves(ZedGraphControl zgc)
{
if (zgc.InvokeRequired)
{
createCurvesHandler d = new createCurvesHandler(createCurves);
zgc.Invoke(d, new object[] { zgc});
}
else
{
ColorSymbolRotator rotator = new ColorSymbolRotator();
#region create curves as needed
for (int i = 0; i < lgControlsPanel.Controls.Count; i++)
{
if (lgControlsPanel.Controls[i] == angleCheckBox)
if (angleCheckBox.Checked)
{
foreach (string key in valveCheckedListBox.Items)
{
if (valveCheckedListBox.CheckedItems.Contains(key))
{
zgc.GraphPane.AddCurve(key + ": Angle", anglePointArr[HexToLong(key)], rotator.NextColor, rotator.NextSymbol);
}
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
#endregion
zgc.AxisChange();
}
}
|
|
|
|
|
Hello,
I have to tell you that this doesn't make any sence!
From my understanding of your first questions, I asumed you want to make a thread for collecting the datas for your Graph.
But hat I see here is that you have the datas and start a thread to fill the datas to your Graph.
And the first thing which is done in the thread is to invoke it back to the GUI thread.
For your problem with the Zed Graph (without using threads), you should conntact the ZedGraph forum I guess!
Sorry, for not really helping you out!
All the best,
Martin
|
|
|
|
|
Is there a way of calling a method but not calling the first line of the method?
I have a generic List called PlayHand. I add to this list in the method PlayGame(). When the button is clicked I want to add a Card type to this list. But after the method PlayGame() has been called and the method has completed, the generic list PlayHand clears.
Can anyone help? Im really stuck on this!
Lucy
|
|
|
|
|
Lucy_H85 wrote: Is there a way of calling a method but not calling the first line of the method?
I don't think so. What you can do is add boolean parameter to that method, and have condition on first line, something like
void MyMethod(bool shouldExecuteFirstLine)
{
if(shouldExecuteFirstLine)
{
...
}
}
Lucy_H85 wrote: I have a generic List called PlayHand. I add to this list in the method PlayGame(). When the button is clicked I want to add a Card type to this list. But after the method PlayGame() has been called and the method has completed, the generic list PlayHand clears.
Uh, I don't follow Can you show your code?
[ My Blog] "Visual studio desperately needs some performance improvements. It is sometimes almost as slow as eclipse." - Rüdiger Klaehn "Real men use mspaint for writing code and notepad for designing graphics." - Anna-Jayne Metcalfe
|
|
|
|
|
Sorry I am very new to C# and I am trying alter a console application example from a book to a windows form to test my skills and how much I have learnt. I think I haven't learnt to much and I have taken on a huge task.
I have this method PlayGame()
public void PlayGame()<br />
{<br />
Player[] players = new Player[1];<br />
<br />
for (int p = 0; p < players.Length; p++)<br />
{<br />
string playerName = listBox1.SelectedItem.ToString();<br />
players[p] = new Player(playerName);<br />
}<br />
<br />
if (players == null)<br />
return;<br />
<br />
for (int p = 0; p < players.Length; p++)<br />
{<br />
for (int c = 0; c < 7; c++)<br />
{<br />
players[p].PlayHand.Add(playDeck.GetCard(currentCard++));<br />
}<br />
}<br />
<br />
Card playCard = playDeck.GetCard(currentCard++);<br />
discardedCards.Add(playCard);<br />
<br />
for (currentPlayer = 0; currentPlayer < players.Length; currentPlayer++)<br />
{<br />
label1.Text = players[currentPlayer].Name + "'s turn.";<br />
labelHiden.Text = Convert.ToString(currentPlayer);<br />
label2hiden.Text = Convert.ToString(players[currentPlayer]);<br />
foreach (Card card in players[currentPlayer].PlayHand)<br />
{<br />
listBox2.Items.Add(Convert.ToString(card));<br />
}<br />
label3.Text = "Card in play: " + playCard;<br />
<br />
if (discardedCards.Contains(playCard))<br />
{<br />
discardedCards.Remove(playCard);<br />
}<br />
players[currentPlayer].PlayHand.Add(playCard);<br />
label1.Text = "Drawn: " + playCard;<br />
<br />
label1.Text = "New Hand:";<br />
<br />
for (int i = 0; i < players[currentPlayer].PlayHand.Count; i++)<br />
{<br />
listBox2.Items.Add(i + 1 + ": " + players[currentPlayer].PlayHand[i]);<br />
}<br />
label3.Text = "Choose card to discard:";<br />
}<br />
current = playCard;<br />
<br />
}
I only want this section of code to execute if a button is clicked:
<br />
if (discardedCards.Contains(playCard))<br />
{<br />
discardedCards.Remove(playCard);<br />
}<br />
players[currentPlayer].PlayHand.Add(playCard);<br />
label1.Text = "Drawn: " + playCard;<br />
I was wondering if there was a way of breaking this loop to wait if the button is clicked.
Lucy
|
|
|
|
|
Lucy_H85 wrote: Player[] players = new Player[1];
As I thought, this creates a new local variable. Turn it into a member if you want to reuse it.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
Thank you! I will try that now.
Lucy
|
|
|
|
|
Sounds like your problem is tha the list is created inside the method and so has no state. Is it a member ? If it is, then it's Clear method is being called somewhere.
What is this first line you're trying to avoid ( it can't be done without the approach someone else offered ) ?
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
Hi All,
Can I covert the SqlDataReader into a user defined class? I will explain my doubt.
I have a user defined class named 'Member' which contains the fields same as in the 'Member' table in database.
Now I want to select the Members from database and converted to the array of class 'Member'.
Is it possible? Is it will causes to overkill?
Regards,
Hogan
|
|
|
|
|
You can create a method that received as a parameter an SqlDataReader object, and returns a Member array. There for each row in the database you create a new Member object, read the values and at the end return the array.
Hope it helps.
There are 10 kinds of people: those who understand binary and those who don't
|
|
|
|
|
Thank you for reply
It require a loop. isn't it? I am worried about the performance. This member class in my business layer. Actually SqlDataReader is enough for the purpose. But I want to make it more slandered form
Regards,
Hogan
|
|
|
|
|
Yes, you need a loop. I gave you a solution to a problem, though i would rather work with SqlDataReader
There are 10 kinds of people: those who understand binary and those who don't
|
|
|
|