I have been searching this issue in the web and have gone trough the documentation,however was not successful in finding a solution.
In my code I have created a MasterPane and utilize 13 GraphPanes,The problem is that if there are many graphs, the details become indistinguishable,hence I want to select(by clicking) a graph and enlarge it.Is there a specific function to realize this goal.If not,which steps are to be followed.
Thank you in advance
Even late,i hope it'll will help others.
The idea is to use the MasterPan PaneList collection.
I added a few buttons to the Window and do the control from them, another way
is to use FindPane method in the MasterPan class and do this by clicking.
I'll show both ways.
The code follows:
// graphSystem Class
MasterPane masterPane;
PaneList plist = new PaneList();
private void InitGraphs()
{
//Zedgraph control
var zgc = Apprefs.Zedgraph;
//MasterPan
masterPane = zgc.CreateMasterPan(Title, System.Drawing.Color.White);
// CreateMultiGraph is my own API to create Graph
zgc.CreateMultiGraph("Graph1", 1, "G1xtitle", "G1ytitle", false);
zgc.CreateMultiGraph("Graph2", 1, "G2xtitle", "G2ytitle", false);
zgc.CreateMultiGraph("Graph3", 1, "G3xtitle", "G3ytitle", false);
// save the Pans
foreach (GraphPane graph in masterPane.PaneList)
plist.Add(graph);
}
//---------------------------------------------------------------------------
public void Englare(RichButton button)
{
var graph = Apprefs.Zedgraph2.graph;
if (button.Name == "Show1")
{
ShowOneGraph(0);
}
else if (button.Name == "Show2")
{
ShowOneGraph(1);
}
else if (button.Name == "ShowAll")
{
ShowAllGraphs();
}
}
//---------------------------------------------------------------------------
private void ShowOneGraph(int Graphindex)
{
if (masterPane == null) return;
var graph = Apprefs.Zedgraph.graph;
if (Graphindex >= 0 && Graphindex < plist.Count)
{
masterPane.PaneList.Clear();
masterPane.PaneList.Add(plist[Graphindex]);
Layout();
}
}
//---------------------------------------------------------------------------
private void ShowAllGraphs()
{
if (masterPane == null) return;
var graph = Apprefs.Zedgraph.graph;
masterPane.PaneList.Clear();
foreach (GraphPane gr in plist)
masterPane.PaneList.Add(gr);
Layout();
}
//---------------------------------------------------------------------------
private void Layout()
{
var graph = Apprefs.Zedgraph2.graph;
using (Graphics g = graph.CreateGraphics())
{
masterPane.SetLayout(g, PaneLayout.SingleColumn);
graph.AxisChange();
graph.Refresh();
}
}
//---------------------------------------------------------------------------
way2: englare by click On Graph:
Add this method:
//---------------------------------------------------------------------------
GraphPane lastpan;
public void UCclicked(PointF mousePt)
{
GraphPane pan= masterPane.FindPane(mousePt);
if (pan != null)
{
if (pan == lastpan)
{
ShowAllGraphs();
lastpan = null;
}
else
{
ShowOneGraph(plist.IndexOf(pan));
lastpan = pan;
}
} }
Also register to the click event:
zgcGraph.MouseDoubleClick += new MouseEventHandler(zgcGraph_MouseDoubleClick);
And finally:
void zgcGrzgcGraph_MouseDoubleClick(object source, System.Windows.Forms.MouseEventArgs e)
{
if (Apprefs.graphSystem != null)
{
System.Drawing.PointF mousePt = new System.Drawing.PointF(e.X, e.Y);
Apprefs.graphSystem.UCclicked(mousePt);
}
}
thats it!
Related
I do need some help to implement a way for the user to interact with the model like for example when the edit button is pressed I want the user to select on a part on the object that can highlight in yellow on unity with c#. Is there way or any logic? Let me know if you dont understand what I want to implement. thanks for your help.
Here is some code:
public class BlowupController : MonoBehaviour {
public void Editcomponents()
{
// let user interact when edit button (script) is called.
ClearText();
RemoveStatus = !RemoveStatus;
var imgs = reticle.GetComponentsInChildren<Image>(true);
if (RemoveStatus)
{
foreach (var img in imgs)
{
img.GetComponent<Image>().color = new Color32(255, 0, 0, 255);
}
}
else
{
foreach (var img in imgs)
{
img.GetComponent<Image>().color = new Color32(255, 255, 255, 255);
}
}
}
public void ResetComponents(GameObject Remove)
{
Debug.Log("HI"); ;
Debug.Log(value);
ClearText();
foreach (Animator ani in AnimotorList)
{
ani.gameObject.SetActive(true);
ani.SetBool("Start", value);
}
if (RemoveStatus)
{
var imgs = reticle.GetComponentsInChildren<Image>(true);
foreach (var img in imgs)
{
img.GetComponent<Image>().color = new Color32(255, 255, 255, 255);
}
var on = Remove.transform.Find("Remove_On");
on.gameObject.SetActive(true);
var off = Remove.transform.Find("Remove_Off");
off.gameObject.SetActive(false);
RemoveStatus = !RemoveStatus;
}
ResetPanel.SetActive(false);
}
public void UndoRemovingComponent(GameObject Remove)
{
if (UndoList.Count > 0)
{
ClearText();
var ob = UndoList[UndoList.Count - 1];
ob.SetActive(true);
UndoList.Remove(ob);
if (UndoList.Count == 0)
{
var imgs = reticle.GetComponentsInChildren<Image>(true);
foreach (var img in imgs)
{
img.GetComponent<Image>().color = new Color32(255, 255, 255, 255);
}
var on = Remove.transform.Find("Remove_On");
on.gameObject.SetActive(true);
var off = Remove.transform.Find("Remove_Off");
off.gameObject.SetActive(false);
ResetPanel.SetActive(false);
UndoPanel.SetActive(false);
RemoveStatus = !RemoveStatus;
}
}
}
private IEnumerator Start()
{
yield return new WaitForSeconds(initialTimeDelay);
if (reticle == null)
{
reticle = FindObjectOfType<Reticle>().gameObject;
}
TransformSync();
}
}
}
I do not fully understand your question, but if you are trying to know if/when a user presses a key, you can use Input.GetKeyDown(). Example
if (Input.GetKeyDown("space"))
{
print("space key was pressed");
}
OR
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
print("space key was pressed");
}
}
Here, you replace space with the key you wish to check. Full documentation can be found on Unity docs https://docs.unity3d.com/ScriptReference/Input.GetKeyDown.html
First of all, since your object is divided into separate parts, create a script called "CheckIfSelected" or something similar, then in the update method, use raycast to check if the object is clicked. Once the object is clicked, get the material on the object, then change the color as such: (Sorry about the formatting and any possible typos, i am not using an ide)
function Update () {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit;
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, hit)) {
if (hit.transform.gameObject == gameObject ){
gameObject.renderer.material.color = new Color(1,1,1);
}
}
}
I wrote some code to draw something in a iOS App, if the server send some new coordinates to it.
I have a callback function that draw the coordinates. But when I create a new instance of a class in this function the callback exit without any error...
Does someone else have this problem before?
Here is my code if this is helping
CGPath pathtotal;
List<CGPath> path;
CGPoint initialPoint;
CGPoint latestPoint;
DrawDrawerDraw drawDrawerDraw;
public DrawGuessView(IntPtr handle) : base(handle)
{
BackgroundColor = UIColor.White;
pathtotal = new CGPath();
SocketEventHandler.Add("draw:drawer:draw", onDrawDrawerDraw);
}
public void onDrawDrawerDraw(dynamic obj)
{
drawDrawerDraw = (DrawDrawerDraw)obj;
for (int i = 0; i <= drawDrawerDraw.coords.Count; i++)
{
if (initialPoint.X != (nfloat)drawDrawerDraw.coords[i].x0 && initialPoint.Y != (nfloat)drawDrawerDraw.coords[i].y0)
{
path[i] = new CGPath();
}
initialPoint.X = (nfloat)drawDrawerDraw.coords[i].x0;
initialPoint.Y = (nfloat)drawDrawerDraw.coords[i].y0;
latestPoint.X = (nfloat)drawDrawerDraw.coords[i].x1;
latestPoint.Y = (nfloat)drawDrawerDraw.coords[i].y1;
//add lines to the touch points
if (path[i].IsEmpty)
{
path[i].AddLines(new CGPoint[] { initialPoint, latestPoint });
}
else
{
path[i].AddLineToPoint(latestPoint);
}
}
SetNeedsDisplay();
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
try
{
foreach (var item in path)
{
if (!initialPoint.IsEmpty)
{
//get graphics context
using (CGContext g = UIGraphics.GetCurrentContext())
{
//set up drawing attributes
g.SetLineWidth(2);
UIColor.Black.SetStroke();
//add geometry to graphics context and draw it
pathtotal.AddPath(item);
g.AddPath(pathtotal);
g.DrawPath(CGPathDrawingMode.Stroke);
}
}
}
}
catch (Exception e) { }
}
}
There are two points you need to modify.
Initialize path in DrawGuessView method
public DrawGuessView(IntPtr handle) : base(handle)
{
BackgroundColor = UIColor.White;
pathtotal = new CGPath();
List<CGPath> path = new List<CGPath>();
SocketEventHandler.Add("draw:drawer:draw", onDrawDrawerDraw);
}
path[i] = new CGPath() will cause the ArgumentOutOfRangeException, we can't set value to the item in List by this way.
Modify the loop
CGPath pathItem = null;
for (int i = 0; i <= drawDrawerDraw.coords.Count; i++)
{
if (initialPoint.X != (nfloat)drawDrawerDraw.coords[i].x0 && initialPoint.Y != (nfloat)drawDrawerDraw.coords[i].y0)
{
pathItem = new CGPath();
}
initialPoint.X = (nfloat)drawDrawerDraw.coords[i].x0;
initialPoint.Y = (nfloat)drawDrawerDraw.coords[i].y0;
latestPoint.X = (nfloat)drawDrawerDraw.coords[i].x1;
latestPoint.Y = (nfloat)drawDrawerDraw.coords[i].y1;
//add lines to the touch points
if (pathItem.IsEmpty)
{
pathItem.AddLines(new CGPoint[] { initialPoint, latestPoint });
}
else
{
pathItem.AddLineToPoint(latestPoint);
}
path.Add(pathItem);
}
So my program is generating a bunch of buttons like so:
foreach (var subdir in dir.GetDirectories()) {
var path = subdir.Name;
var button = new Button {
Text = getFlavor(path) + "\t(" + path + ")",
Width = Width,
Height = 35,
Top = y
};
button.Click += buttonClick;
Controls.Add(button);
if (button.Text.Contains("Kittens")
i++;
}
I want to try something like this
if (i == 1) {
[Button.ThatContains("Kitten)].Click;
}
"ThatContains" is not a real method. How do I get references to buttons I've created programmatically ?
You could use OfType<Button> to find all buttons in the container control where you've added them(f.e. a Panel). Then a liitle bit LINQ power gives you the correct button(s):
var kittenButtons = panel.Controls.OfType<Button>()
.Where(btn => btn.Text.Contains("Kittens"));
foreach(Button btn in kittenButtons)
btn.PerformClick();
If you just want to click the first:
Button kittenButton = panel.Controls.OfType<Button>()
.FirstOrDefault(btn => btn.Text.Contains("Kittens"));
if(kittenButton != null)
kittenButton.PerformClick();
For what it's worth, here is also an extension method that returns controls recursively via deferred execution which allows to use only the first found Buttton or consume all down the road:
public static IEnumerable<T> GetChildControlsRecursive<T>(this Control root) where T : Control
{
if (root == null) throw new ArgumentNullException("root");
var stack = new Stack<Control>();
stack.Push(root);
while (stack.Count > 0)
{
Control parent = stack.Pop();
foreach (Control child in parent.Controls)
{
if (child is T)
yield return (T)child;
stack.Push(child);
}
}
yield break;
}
Now you can use similar code as above to get for example the first matching button or all:
var kittenButtons = this.GetChildControlsRecursive<Button>()
.Where(b => b.Text.Contains("Kittens"));
// search just until the first button is found
Button firstKittenButton = kittenButtons.FirstOrDefault();
if(firstKittenButton != null) firstKittenButton.PerformClick;
// loop all
foreach(Button btn in kittenButtons)
btn.PerformClick();
Either create a subclass of Button to store the information you want and instantiate that instead or use the Tag property
public class MyButton : Button
{
public int ButtonID { get; set; }
}
public class MyApplication
{
public void DoSomething()
{
int i; // todo: loop stuff
var button = new MyButton
{
Text = getFlavor(path) + "\t(" + path + ")",
Width = Width,
Height = 35,
Top = y,
ButtonID = i
};
}
}
Or why not cast the sender parameter of the button click event as a Button and check the text?
public class MyApplication
{
public void DoSomething()
{
var b = new Button();
b.Click += b_Click;
}
public void b_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
switch (b.Text) {
case "Kittens":
return;
default:
return;
}
}
}
Something like this
var button = FirstOrDefault(y => y is Button && y.Text.Contains("Kittens"));
if(button != null)
button.PerformClick();
In order to get the references, you may need to what you would do with getting references of any other type - store them somewhere, which does not seem to be the case here at all. Normally, you would register your buttons for interaction from a user by attaching them to a Form. Assuming you're not doing this by the looks of your sample code, I'm going to recommend storing them into a Dictionary<string, Button>.
You could use a dictionary or you could use a simple recursive loop (in case you are sticking the buttons into different containers).
private bool ClickButton(string buttonName, Control control) {
if (control is Button && control.Text.Contains(buttonName) {
((Button)control)PerformClick();
return true;
}
if (control.HasChildren) {
foreach (Control childControl in control.Controls) {
if (ClickButton(buttonName, childControl)) {
return true;
}
}
}
return false;
}
Usage: ClickButton("Kittens", this);
Or you could use a dictionary, as some have suggested.
private Dictionary<string, Button> DynamicButtons = new Dictionary<string, Button>();
private void ClickDictionaryButton(string buttonName) {
var matches = DynamicButtons.Where(x => x.Key.Contains(buttonName));
foreach (var match in matches) {
match.Value.PerformClick();
}
}
Usage: ClickDictionaryButton("Kittens", this);
I want fill my treeview with >30000 nodes in multi level.
I use this code for fill it, but treeview get over 30 seconds time for fill it.
How can I use multi thread for increase speed to fill it ?
//in my windows form :
private void ThesaurusFrm_Load(object sender, EventArgs e)
{
TreadPopulateTree();
}
private void TreadPopulateTree()
{
System.Threading.Thread TrPopulateTree = new System.Threading.Thread(new System.Threading.ThreadStart(PopulateTree));
TrPopulateTree.Start();
}
private void PopulateTree()
{
FillTree.TvTrees = TvThesaurusNodes;
FillTree Ft = new FillTree();
var TreeItems = Db.LoadThesaurusTrees();
if (TvThesaurusNodes.InvokeRequired)
TvThesaurusNodes.BeginInvoke(new MethodInvoker(() =>
{
Ft.LoadTrees(TreeItems);
}));
}
//in my FillTree class
public static TreeView TvTrees;
List<TreesFieldSet> TreeItems = new List<TreesFieldSet>();
public void LoadTrees(List<TreesFieldSet> TreeItems)
{
this.TreeItems = TreeItems;
TvTrees.Nodes.Clear();
TvTrees.ShowPlusMinus = true;
TvTrees.FullRowSelect = true;
TvTrees.Nodes.Clear();
TvTrees.BeginUpdate();
LoadBaseNodes();
TvTrees.EndUpdate();
TvTrees.Refresh();
}
private void LoadBaseNodes()
{
if (TreeItems != null)
{
int BaseParent = 0;
TreeNode Node;
foreach (TreesFieldSet Tfs in TreeItems)
{
if (Tfs.ParentId < BaseParent)
BaseParent = Tfs.ParentId;
}
foreach (TreesFieldSet Tfs in TreeItems)
{
if (Tfs.ParentId == BaseParent)
{
Node = TvTrees.Nodes.Add(Tfs.Title);
Node.Tag = Tfs.TreeId;
GetChildren(Node);
}
}
}
}
private void GetChildren(TreeNode Node)
{
TreeNode ChNode = null;
Int32 nodeCat = (Int32)Node.Tag;
foreach (TreesFieldSet Tfs in TreeItems)
{
if (Tfs.ParentId == nodeCat)
{
ChNode = Node.Nodes.Add(Tfs.Title);
ChNode.Tag = Tfs.TreeId;
GetChildren(ChNode);
}
}
}
No never do multi-threading with UI, Reading is not a problem in some case but writing is always a problem.
You can defer the loading, i.e Load only what user can see, then load the children only when user clicks the node. I've answered a similar question here see if that helps.
Typically you load only a "Node" and its "Immediate children" no more no less.
Hope this helps.
In my application I want to ensure that a TagVisualization is only displayed if the tagged object is placed on a Ellipse. So I used this code to do that:
private void TagVisualizer_VisualizationAdded(object sender, TagVisualizerEventArgs e)
{
Console.WriteLine("Hitlist");
//Notes
if (e.TagVisualization.GetType() == typeof(NoteVisualization))
{
bool found = false;
Point pt = e.TagVisualization.Center;
hitResultsList.Clear();
VisualTreeHelper.HitTest(RootLayer, null, new HitTestResultCallback(MyHitTestResult), new PointHitTestParameters(pt));
if (hitResultsList.Count > 0)
{
foreach (DependencyObject o in hitResultsList)
{
if (o.GetType() == typeof(Ellipse))
{
Console.WriteLine("Placed on a Sourcefile");
SourceFile sf = (((o as Ellipse).Tag) as SourceFile);
GroupBox gp = e.TagVisualization.FindName("GroupHeader") as GroupBox;
gp.Header = sf.getFullName();
e.TagVisualization.Tag = sf;
SurfaceButton save = e.TagVisualization.FindName("NoteSave") as SurfaceButton;
save.Tag = sf;
found = true;
break;
}
}
}
if (!found)
{
e.TagVisualization.Visibility = System.Windows.Visibility.Collapsed;
Console.WriteLine("Placed somewhere else");
}
}
}
I'm not really sure if this is the correct way, since I don't avoid that the TagVisualization is displayed, but instead I instantly set the Visibility to collpased. I think there have to be better ways to do that?
official guidance for how to do this is shown in one of the sdk samples:
http://msdn.microsoft.com/en-us/library/ee804861(v=Surface.10).aspx
-robert (former program manager for the surface dev platform)