Eventhandlers between different forms (parent/child) - forms

Im quite new with c++ and so far im having a little trouble understanding the basics. i got 2 forms right now.
parent.h
#include "child.h"
public ref class parent : public System::Windows::Forms::Form {
child^ v_child = gcnew child;
void InitializeComponent(void){
v_child->Load += gcnew System::EventHandler(v_child, &child::child_Load);
}
private: System::Void child_Load(System::Object^ sender, System::EventArgs^ e) {
MessageBox::Show("Howdy");
}
}
i basically want the parent to do something when the child has an event, in this case, just a Load. it compiles and gives no warning/error, child execute the event, but it never triggers on the parent.
wanted to do this to be able to interact between parent and child, which so far, im having so much trouble doing so.

To be clear, do you want parent to react to a "Load" event on the child?
If so, then you're linking the event incorrectly. Your code:
v_child->Load += gcnew System::EventHandler(v_child, &child::child_Load);
Links the Load event handler to the v_child not to parent. Try this instead:
v_child->Load += gcnew System::EventHandler(this, &parent::child_Load);

Related

Unity3D: Custom UnityEvent AddListener not firing

I have my own custom UnityEvent and am trying to add a listener.
I have used AddListener on numerous other UI objects, such as buttons, dropdowns, toggles, etc. so I understand the process. However, when I Invoke my UnityEvent, it simply doesn't fire.
I'm receiving no error messages, and after doing reading and research, everything looks correct. So, not sure what to do further.
This is an object that emits when it's rotated.
This is the basics of my code:
using UnityEngine.Events;
public class Rotator: MonoBehaviour
{
public UnityEvent OnRotate;
int angle = 0;
int newAngle = 0;
void Start()
{
OnRotate = new UnityEvent();
}
void Update()
{
newAngle = (int)transform.rotation.eulersAngles.z;
if (newAngle != angle)
{
print ("Actual Instance ID: " + GetInstanceID());
print ("Invoking!");
OnRotate.Invoke();
angle = newAngle;
}
}
}
and
public class Owner: MonoBehaviour
{
public Rotator rotator;
void Start()
{
print ("Rotator Instance ID: " + rotator.GetInstanceID());
rotator.OnRotate.AddListener(
() => UpdateRotation()
);
}
void UpdateRotation()
{
print ("Invoked!");
}
}
When the Rotator has it's angle changed, I get this in the console:
Actual Instance ID: 11234
Rotator Instance ID: 11234
Invoking!
The instance ID is to make sure I'm working with the same objects and not going in circles for nothing. They match, so I'm listening to the object that's firing.
However, the listener isn't firing. I've tried different combinations with delegates, etc. but it's all the same. No errors. It just doesn't invoke.
Obviously, I'm doing something wrong, but what is it?
Thanks for any help.
Somehow your answered your new edited version of the question with exactly the code you previously provided in the First Version of your Question!
As I tried to tell you ... if you anywhere in your code do OnRotate = new UnityEvent() of course you thereby erase any persistent callbacks and any runtime callbacks added before that moment!
In short
Simply leave it as
public UnityEvent OnRotate;
and you don't even have to think about it anymore.
For understanding why it also works if you put it in Awake please simply have a look at the Order of Execution for Event Functions
→ First Awake and OnEnabled is called for every GameObject/Component. Then all Start methods are called as soon as the GameObject/Component is active.
Within each of these blocks (Awake + OnEnable) and (Start) the order of execution between different component types is not guaranteed unless you explicitly configure it via the Script Execution Order Settings where you could define that Owner is simply run before Rotator .. then having both in Start would also work again.
Why does it also work if you do it on the public field?
→ Because this field is serialized. That means it is initialized automatically in the Inspector and then stored together with the Scene or prefab asset including any persistent callbacks.
And then Later Unity re-uses the serialized Version of the field so actually you can completely remove the new UnityEvent(); since it doesn't have any effect on a serialized field! It will always be initialized automatically anyway!
Ok, I found out what the issue was.
My question now is "why?".
I changed my code from:
public UnityEvent OnRotate;
void Start() {
OnRotate = new UnityEvent();
}
to
public UnityEvent OnRotate = new UnityEvent();
void Start() {
}
And now it works.
Although, now that I think about it, Awake() is the method where they all fire before initialization, whereas Start() is when the object is created. So the Start() of the Rotator is probably getting called after the Owner is adding a listener.

StartCoroutine get error NullReferenceException

I have two cs files, Main.cs and Menu.cs. On OnGUI event which is in Main.cs file I call method from Menu.cs.
private void OnGUI()
{
Menu menu=new Menu();
menu.Create_Menu();
}
And in Menu.cs.
public void Create_Menu ()
{
StartCoroutine(LoadCar());
}
private IEnumerator LoadCar()
{
//Load Object
Download download;
download=new Download();
GameObject go = null;
yield return StartCoroutine(LoadAsset("http://aleko-pc/3dobjects?key=1017&objecttype=1","car13",(x)=>{go = x;}));
}
I get error NullReferenceException
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine)
If I copy private IEnumerator LoadCar() method in Main.cs class, and call from OnGUI it works.
Maybe I do not understant working area of Coroutines, Can any body help me?
First of all the OnGUI method is called every frame and I don't think you want to download the assets every frame.
Second, you need to make sure Menu is derived from MonoBehviour and added to the view hierarchy.
A better approach would be to add Menu as a component to a GameObject (maybe the same that has the Main script attached) and call Create_Menu on the Start method of Menu.

backgroundworker in infinite loop

Except doevent() is another way that, in this infinite loop run another control in form.
I wanted to do it with backgroundworker, but I failed.
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
Application.DoEvents(); //how i can use the backgrondworker in this place
}
}
The question and sample are confusing to me but what I think you are asking is how to use the BackgroundWorker class.
The Documentation for this class is pretty helpful and has sample code towards the bottom.

Do I have to manually attach a gtk signal handler when I specified the function name in glade?

I'm writing my first gtk program, using gtkmm, and glade.
I made a filechooserbutton and it has a signal called file-set
So I set that to what I assume is the function name I want it to call when the file is chosen.
But then I see here:
http://library.gnome.org/devel/gtkmm-tutorial/unstable/sec-builder-accessing-widgets.html.en
That they're manually getting the dialog widget and setting a button signal handler in the code.
Which is the right way to do it?
And while I'm here any links to good examples would be handy, they seem to be few and far between. Thanks.
This is how I did it:
// create the UI
refUI = Gtk::Builder::create();
refUI->add_from_file(grq::GLADE_FILE);
// grab your widget
refUI->get_widget("but_new", but_new); // Gtk::ToolButton *but_new;
but_new->signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_new_game));
// your signal handler looks something like this :)
void MainWindow::on_new_game() {}
edit:
Basically the *this is the object on which you will be calling the function your signal handler.
This is what my main looks like:
int main(int argc, char **argv) {
Gtk::Main kit(argc, argv);
MainWindow main_window;
kit.run(*main_window.window);
return 0;
}
MainWindow is basically a class that wraps GtkWindow and defines the widgets, a. la.:
class MainWindow
{
private:
Glib::RefPtr<Gtk::Builder> refUI;
//
// Widgets
//
Gtk::ToolButton *but_about;
public:
// The window. This is public so we can hook into events and
// call kit.run(window) against it, if needed.
Gtk::Window *window;
MainWindow()
{
// Load the data for this window and it's widgets.
refUI = Gtk::Builder::create();
refUI->add_from_file(grq::GLADE_FILE);
// The window
refUI->get_widget("main_window", window);
// Widgets
refUI->get_widget("but_about", but_about);
but_about->signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_about));
...
}
virtual ~MainWindow()
{
if (window != NULL)
{
delete window; // Frees all the children for the window, too.
}
}
virtual void on_about()
{
// stuff
}
};
Hope this helps!
I found the answer to my question as an afterthought in another stackoverflow question.
But I don't remember which one it was.
The answer seems to be that you have to programmatically add the signal handler to the widget in your code, the gtkbuilder won't do it for you.

Catching the scrolling event in gtk#

Which event from which widget should I catch when I need to run some code when ScrolledWindow is scrolled?
Ths widgets tree I am using is:
(my widget : Gtk.Container) > Viewport > ScrolledWindow
I tried many combinations of ScrollEvent, ScrollChild, etc. event handlers connected to all of them, but the only one that runs anything is an event from Viewport that about SetScrollAdjutstments being changed to (x=0,y=0) when the application starts.
You should attach to the GtkAdjustment living in the relevant scrollbar, and react to its "changed" event. Since Scrollbars are Ranges, you use the gtk_range_get_adjustment() call to do this.
unwind's answer was correct.
Just posting my code in case someone needs a full solution:
// in the xxx : Gtk.Container class:
protected override void OnParentSet(Widget previous_parent) {
Parent.ParentSet += HandleParentParentSet;
}
void HandleParentParentSet(object o, ParentSetArgs args) {
ScrolledWindow swn = (o as Widget).Parent as ScrolledWindow;
swn.Vadjustment.ValueChanged += HandleScrollChanged;
}
void HandleScrollChanged(object sender, EventArgs e) {
// vertical value changed
}
If you need to change the parent of any of those widgets, or may need to change the types and change the hardcoded types and handle disconnecting from the previous parent.