How do I connect a custom function to the clicked action of a GTK Button? - gtk

I am working my way through the Vala GTK+3 tutorial provided by Elementary OS. I understand that this code:
var button_hello = new Gtk.Button.with_label ("Click me!");
button_hello.clicked.connect (() => {
button_hello.label = "Hello World!";
button_hello.set_sensitive (false);
});
uses a Lambda function to change the button's label when it's clicked. What I want to do is call this function instead:
void clicked_button(Gtk.Button sender) {
sender.label = "Clicked. Yippee!";
sender.set_sensitive(false);
}
I've tried this:
button.clicked.connect(clicked_button(button));
But I get this error from the Vala compile when I try to compile:
hello-packaging.vala:16.25-16.46: error: invocation of void method not allowed as expression
button.clicked.connect(clicked_button(button));
^^^^^^^^^^^^^^^^^^^^^^
Compilation failed: 1 error(s), 0 warning(s)
I'm new to both Vala and Linux so please be gentle but can someone point me in the right direction?

You need to pass a reference to the function, rather than the result of the function. So it should be:
button.clicked.connect (clicked_button);
When the button is clicked GTK+ will invoke the clicked_button function with the button as an argument.
The error message invocation of void method not allowed as expression is telling you you are calling (invoking) the method and it has no result (void). Adding parentheses, (), to the end of a function name invokes that function.

Managed to get it working. Here's the code in case others need it:
int main(string[] args) {
// Initialise GTK
Gtk.init(ref args);
// Configure our window
var window = new Gtk.Window();
window.set_default_size(350, 70);
window.title = "Hello Packaging App";
window.set_position(Gtk.WindowPosition.CENTER);
window.set_border_width(12);
window.destroy.connect(Gtk.main_quit);
// Create our button
var button = new Gtk.Button.with_label("Click Me!");
button.clicked.connect(clicked_button);
// Add the button to the window
window.add(button);
window.show_all();
// Start the main application loop
Gtk.main();
return 0;
}
// Handled the clicking of the button
void clicked_button(Gtk.Button sender) {
sender.label = "Clicked. Yippee!";
sender.set_sensitive(false);
}

Related

Demo Code on main page showing click not found

I am trying to compile demonstration code on the main page of Vala programming language
int main (string[] args) {
var app = new Gtk.Application(
"com.example.App",
ApplicationFlags.FLAGS_NONE
);
app.activate.connect(() => {
var win = new Gtk.ApplicationWindow(app);
var btn = new Gtk.Button.with_label("Hello World");
btn.click.connect(win.close);
win.child = btn;
win.present();
});
return app.run(args);
}
I am using following command:
$ valac --pkg gtk+-3.0 valademo.vala
However, it is giving following error:
valademo.vala:13.5-13.13: error: The name `click' does not exist in the context of `Gtk.Button'
btn.click.connect(win.close);
^^^^^^^^^
Compilation failed: 1 error(s), 0 warning(s)
Where is the problem and how can it be solved?
That's probably a typo, it should be clicked not click. You may want to raise an issue with the website or submit a pull request.
There are a couple of other problems. Firstly GTK+3 needs win.show_all(), but that has been removed in GTK 4.
Secondly the documentation for win.present() is advising that function shouldn't be used.
Here's a working example for GTK+3:
int main (string[] args) {
var app = new Gtk.Application(
"com.example.App",
ApplicationFlags.FLAGS_NONE
);
app.activate.connect(() => {
var win = new Gtk.ApplicationWindow(app);
var btn = new Gtk.Button.with_label("Hello World");
btn.clicked.connect(win.close);
win.child = btn;
win.show_all();
});
return app.run(args);
}

How to add an event trigger listener(callback)

Basically how you would create a public void MethodToDoStuff(), attach a monobehaviour script and link the method on a button, so that when its clicked, said method "MethodToDoStuff" is called.
Now I want to do that via an editor script.
Add an event trigger component
On the event trigger component, add a PointerDown and PointerUp event
On the PointerUp and PointerDown, link a public method on another script to be run (doesHandler.HidePanel()) "see code below"
I could do this manually but having an editor script is super effiecient.
Here is what I have so far:
All help is appreciated, Thanks!
EDITOR SCRIPT:
void OnWizardCreate()
{
doesHandler = GameObject.FindWithTag("WhatItDoes").GetComponent<WhatThisDoes>();
GameObject selection = Selection.activeGameObject;
EventTrigger trig=(EventTrigger)selection.AddComponent(typeof(EventTrigger));
EventTrigger.Entry onPointerDown = new EventTrigger.Entry();
onPointerDown.eventID = EventTriggerType.PointerDown;
EventTrigger.Entry onPointerUp = new EventTrigger.Entry();
onPointerUp.eventID = EventTriggerType.PointerUp;
trig.triggers.Add(onPointerDown);
trig.triggers.Add(onPointerUp);
}
OTHER SCRIPT:
public void HidePanel()
{
whatItDoesPanel.SetActive(false);
}
On runtime you would usually call e.g.
onPointerDown.AddListener(doesHandler.HidePanel);
however this would only add the listener temporarily.
Adding a persistent listener is a bit more complex but luckily there now is a tool for this: UnityEventTools.AddPersistentListener so afaik you would only have to add
UnityEventTools.AddPersistentListener(onPointerDown, doesHandler.HidePanel);
UnityEventTools.AddPersistentListener(onPointerUp, doesHandler.HidePanel);
Additional afaik you should before use Undo.RecordObject in order to mark the changed object and the scene as dirty and add a Undo/Redo entry like
Undo.RecordObject(selection, "Added event triggers");
So probably something like
void OnWizardCreate()
{
doesHandler = Object.FindObjectOfType<WhatThisDoes>();
if(!doesHandler)
{
Debug.LogWarning("No WhatThisDoes found in the scene -> Ignored");
return;
}
var selection = Selection.activeGameObject;
if(!selection)
{
Debug.LogWarning("Nothing selected -> Ignored")
return;
}
if(selection.GetComponent<EventTrigger>())
{
Debug.LogWarning($"The selected object {selection} already has an EventTrigger attached! -> Ignored");
return;
}
// log the undo before making changes
Undo.RecordObject(selection, "Added event triggers");
var onPointerDown = new EventTrigger.Entry();
onPointerDown.eventID = EventTriggerType.PointerDown;
UnityEventTools.AddPersistentListener(onPointerDown, doesHandler.HidePanel);
var onPointerUp = new EventTrigger.Entry();
onPointerUp.eventID = EventTriggerType.PointerUp;
UnityEventTools.AddPersistentListener(onPointerUp, doesHandler.HidePanel);
var trig = selection.AddComponent<EventTrigger>();
trig.triggers.Add(onPointerDown);
trig.triggers.Add(onPointerUp);
}

Adding an element after clicking on a button

I was trying to learn Vala by programming a very simple application and I stumbled over a problem, that I was unable to resolve on my own.
The program shows simply a button Init and on click it should add a Button X to the Grid container. Unfortunately, the contents of the Grid container remain empty and I don't know why.
Even more confusing is, that adding the Button right in the constructor works as expected.
So what I'm doing wrong here?
using Gtk;
class MyWindow: Gtk.Window {
private Gtk.Grid mGrid;
public MyWindow() {
var init=new Gtk.Button.with_label("Init");
init.clicked.connect((t)=>{
stdout.printf("Init");
mGrid.attach(new Gtk.Button.with_label("X"),0,0,1,1);
});
var box=new Gtk.Box(VERTICAL,0);
mGrid=new Gtk.Grid();
//mGrid.attach(new Gtk.Button.with_label("X"),0,0,1,1);
box.add(init);
box.add(mGrid);
this.add(box);
this.show_all();
}
}
int main(string[] args) {
Gtk.init(ref args);
new MyWindow();
Gtk.main();
return 0;
}
With the GTK+ toolkit widgets are hidden by default. Although you have this.show_all (), the button is created afterwards and is hidden. Changing the callback from:
init.clicked.connect((t)=>{
stdout.printf("Init");
mGrid.attach(new Gtk.Button.with_label("X"),0,0,1,1);
});
to something like:
init.clicked.connect((t)=>{
stdout.printf("Init");
var my_button = new Gtk.Button.with_label("X");
my_button.show_all ();
mGrid.attach(my_button,0,0,1,1);
});
now works.

How to create an mouse eventhandler in C++/CX

I am creating button control in my Windows 8 metro application made in C++/CX. I'd like to make an event which is triggered when the button is pressed. But I have no clue how to add an event to a button in C++/CX.
If you want to do this in C# it is as following:
Button btnDoSomething = new Button();
btnDoSomething.MouseClick += new MouseEventHandler(iGotClickedByTheButton);
void iGotClickedByTheButton(object sender, MouseEventArgs e)
{
MessageBox.Show("Hello I got clicked!");
}
So my approach was doing something like this:
Button^ btnDoSomething = ref new Button();
btnDoSomething->Tapped += ref new TappedEventHandler(sender, iGotClickedByTheButton);
void iGotClickedByTheButton(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
MessageDialog^ msgDlg = ref new MessageDialog("Hello I got clicked!");
msgDlg->ShowAsync();
}
This however resulted in an error at this place:
btnDoSomething->Tapped += ref new TappedEventHandler(sender, iGotClickedByTheButton);
It displayed the following error:
Error: invalid delegate initializer -- function does not match the
delegate type.
Solved it by doing the following:
Button^ btnDoSomething = ref new Button();
btnDoSomething->Click += ref new Windows::UI::Xaml::RoutedEventHandler(this, &MyProjectName::MainPage::iGotClickedByTheButton);

Can't hit breakpoints for user generated actions when debugging jython code with PyDev in Eclipse

I'm implementing a GUI application in Jython, using Eclipse and PyDev plugin.
The problem is that I have a hard time using the builtin debugger. When I start a debug session it just stops. Of course this should be expected as the program just creates a JFrame and then it's finished.
So any breakpoints I put for different events .e.g. pressing a button, will never happen as the debug session is already terminated.
What should I do ? I'm growing tired of using prints for all my debugging.
For instance, when I tried debugging this small Java example. I have no problem to hit
the breakpoint I had set in the windowClosing-method
import java.awt.event.*;
import javax.swing.*;
public class Test1 {
public static void main(String s[]) {
JFrame frame = new JFrame("JFrame Source Demo");
// Add a window listner for close button
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
And then I tried this somewhat more or less similiar example in jython
from javax.swing import JFrame;
import java.awt.event.WindowListener as WindowListener
class Test1 (JFrame, WindowListener):
def __init__(self):
super(JFrame, self).__init__('Some name goes here', defaultCloseOperation = JFrame.EXIT_ON_CLOSE, size = (800, 800))
self.addWindowListener(self)
self.setVisible(True)
def windowClosing(self, windowEvent):
print 'window closing'
pass # want to hit this breakpoint
someFrame = Test1()
pass #breakpoint here maybe
If I tried to run the jython example in the debugger and it just terminates. Ok then I added a breakpoint after I created someFrame and a breakpoint in the windowClosing method. Still no luck, It doesn't get hit when I close the window but I see it executed as I see the printout.
Can anyone tell me what I'm doing wrong ? I'm sure I forgot something very simple.
Put a breakpoint in the first line of your main method that initiates the application.
If you want to debug certain actions like pressing a button add an action listener to a button and inside the handling method add the breakpoint. For example:
JButton button = new JButton("OK");
button.addActionListener(new ActionListener()
{
#Override
public void action(ActionEvent e)
{
System.out.println("button OK has been pressed"; // add breakpoint here
// call to some code that handles the event
}
});
I had the same problem
btnCompilar = new JButton("Compilar");
btnCompilar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
compile(); //can't hit breakpoint here
}
});
I couldn't hit breakpoints inside actionPerformed, so I just made a method and used breakpoints in it.
void compile(){
//can hit breakpoint here
}