Skip to content

Instantly share code, notes, and snippets.

@gavr123456789
Last active August 15, 2023 20:50
Show Gist options
  • Save gavr123456789/04883b80cc942d2957c517231575b10e to your computer and use it in GitHub Desktop.
Save gavr123456789/04883b80cc942d2957c517231575b10e to your computer and use it in GitHub Desktop.
async GTK 3 4 gui example vala nim
using Gtk;
Button button;
void main (string[] args) {
Gtk.init (ref args);
var window = new Window ();
button = new Button.with_label ("Start counting");
button.clicked.connect (() => {
count.begin();
});
with (window){
title = "Count without blocking the UI";
border_width = 10;
window_position = WindowPosition.CENTER;
set_default_size (350, 70);
destroy.connect (Gtk.main_quit);
child = button;
show_all ();
}
Gtk.main ();
}
async void count(){
for(int i = 0; i < 10000; i++){
button.label = i.to_string();
Idle.add (count.callback);
yield;
}
}
@gavr123456789
Copy link
Author

Peek 2020-08-30 13-57

@naipotato
Copy link

Using GTK 4 will be like...

Gtk.Button button;

void main () {
  Gtk.init ();
  
  var loop = new MainLoop ();
  
  button = new Gtk.Button.with_label ("Start counting") {
    margin_top = 10,
    margin_start = 10,
    margin_bottom = 10,
    margin_end = 10
  };
  
  button.clicked.connect (() => {
    count.begin ();
  });
  
  var window = new Gtk.Window () {
    title = "Count without blocking the UI",
    default_width = 350,
    default_height = 70,
    child = button
  };
  
  window.close_request.connect (() => {
    loop.quit ();
    return true;
  });
  
  window.show ();
  
  loop.run ();
}

async void count () {
  for (var i = 0; i < 10000; i++) {
    button.label = @"$i";
    Idle.add (count.callback);
    yield;
  }
}

@gavr123456789
Copy link
Author

gavr123456789 commented Aug 23, 2021

GTK 4 nim

With real thread

# nim c --threads:on -d=release --gc:arc -r thread2.nim

import gintro/[gtk4, glib, gobject, gio]
import std/with

from  os import sleep

var 
  workThread: system.Thread[void]
  button: Button
  countdown = 0

proc idleFunc(i: int): bool =
  button.label = $i
  return SOURCE_REMOVE

proc workProc =
  while countdown < 9999:
    sleep(1)
    inc(countdown)
    idleAdd(idleFunc, countdown)

proc buttonClicked(button: Button) =
  countdown = 0
  button.label = "0001"
  createThread(workThread, workProc)

proc activate(app: gtk4.Application) =
  let
    window = newApplicationWindow(app)
  
  button = newButton("Click Me")
  button.connect("clicked",  buttonClicked)
    
  with window:
    title = "Countdown"
    defaultSize = (250, 50)
    setChild(button)
    show
  

proc main =
  let app = newApplication("org.gtk.example")
  app.connect("activate", activate)
  discard app.run()

main()

With messages

# nim c -d=release  --threads:on -r thread2.nim

import gintro/[gtk4, glib, gobject, gio]
import std/with

from  os import sleep

var channel: Channel[int]
var workThread: system.Thread[void]

var button: Button
var countdown = 0

proc updateGUI(b: Button): bool =
  let msg = channel.tryRecv()
  if msg.dataAvailable:
    b.label = $msg.msg
    if msg.msg == 0:
      workThread.joinThread
      channel.close
      return SOURCE_REMOVE
  return SOURCE_CONTINUE


proc workProc =
  while countdown < 9999:
    sleep(1)
    inc(countdown)
    channel.send(countdown)



proc buttonClicked(button: Button) =
  countdown = 0
  button.label = "0001"
  createThread(workThread, workProc)
  discard timeoutAdd(1, updateGUI, button)



proc activate(app: gtk4.Application) =
  let
    window = newApplicationWindow(app)
  
  button = newButton("Click Me")
  button.connect("clicked",  buttonClicked)
    
  with window:
    title = "Countdown"
    defaultSize = (250, 50)
    setChild(button)
    show
  channel.open
  

proc main =
  let app = newApplication("org.gtk.example")
  app.connect("activate", activate)
  discard app.run()

main()

No sleep

Peek.2021-08-23.17-08.mp4

Sleep

Peek.2021-08-23.17-10.mp4

@gavr123456789
Copy link
Author

@naipotato
Copy link

Vala GTK 4 with GThread

Without GAsyncQueue

Gtk.Button button;

void main () {
  Gtk.init ();

  var loop = new MainLoop ();

  button = new Gtk.Button.with_label ("Start counting") {
    margin_top = 10,
    margin_end = 10,
    margin_bottom = 10,
    margin_start = 10
  };

  button.clicked.connect (() => {
    new Thread<void> ("count", count);
  });

  var window = new Gtk.Window () {
    title = "Count without blocking the UI",
    default_width = 350,
    default_height = 70,
    child = button
  };

  window.close_request.connect (() => {
    loop.quit ();
    return true;
  });

  window.show ();

  loop.run ();
}

void count () {
  for (var i = 0; i < 9999; i++) {
    Idle.add (() => {
      button.label = i.to_string ();
      return Source.REMOVE;
    });

    Thread.@yield ();
  }
}
video.mp4

With GAsyncQueue

Gtk.Button button;
AsyncQueue<int?> queue;

void main () {
  Gtk.init ();

  var loop = new MainLoop ();
  queue = new AsyncQueue<int?> ();

  button = new Gtk.Button.with_label ("Start counting") {
    margin_top = 10,
    margin_end = 10,
    margin_bottom = 10,
    margin_start = 10
  };

  button.clicked.connect (() => {
    new Thread<void> ("count", count);
    Timeout.add (1, update_gui);
  });

  var window = new Gtk.Window () {
    title = "Count without blocking the UI",
    default_width = 350,
    default_height = 70,
    child = button
  };

  window.close_request.connect (() => {
    loop.quit ();
    return true;
  });

  window.show ();

  loop.run ();
}

bool update_gui () {
  var count = queue.try_pop ();

  if (count == null)
    return Source.REMOVE;

  button.label = count.to_string ();

  return Source.CONTINUE;
}

void count () {
  for (var i = 0; i < 9999; i++) {
    queue.push (i);
    Thread.@yield ();
  }
}
video.mp4

@Miqueas
Copy link

Miqueas commented Oct 12, 2021

Love this ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment