1

I am a beginner when it gomes to GUI programming with Python so I am guessing my problem has a simple solution even if I have not found a solution searching with google, wikis, documentation, examples ...

What I am trying to achive is that a value in an entry widget should constantly increase up to a max value as long as a button is pressed. I have tried using callback for the event "button-press-event" but get the same response as with callback for the signal "clicked". When connecting to "clicked" the application works as expected, e.g. the value is incremented each click but when I use a connection to the event "button-press-event" I still only get increment for each click (press and release)

I am using this with Python3.2 (on a Raspberry Pi 2)

Below is the working code that acts on each click:

#!/usr/bin/python
from gi.repository import Gtk, Gdk
from time import sleep

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="ST")

        MAX_SPD = 3000

        self.set_default_size(100,100)
        self.set_size_request(100,100)
        self.set_resizable(False)

        spdEntry = Gtk.Entry()
        spdEntry.set_has_frame(True)
        spdEntry.set_text("0")
        spdEntry.connect("activate", self.inputSpd, MAX_SPD)

        start  = Gtk.Button("Start")
        start.connect("clicked", self.clicked_start)
        stop   = Gtk.Button("Stop")
        stop.connect("clicked", self.clicked_stop)
        inc = Gtk.Button("inc")
        inc.connect("clicked", self.pressed_inc, spdEntry, MAX_SPD)

        fixed  = Gtk.Fixed()

        fixed.put(start,    0, 0)
        fixed.put(spdEntry, 0, 40)
        fixed.put(stop,     0, 70)
        fixed.put(inc, 120, 0)

        self.add(fixed)

    def clicked_start(self, widget):
        self.set_title("GO")

    def clicked_stop(self, widget):
        self.set_title("ST")

    def pressed_inc(self, widget, entry, maxSpd):
        speed = int(entry.get_text())
        speed = speed+1
        if speed > maxSpd:
            speed = maxSpd
        entry.set_text(str(speed))

    def inputSpd(self, entry, maxSpd):
        speed = int(entry.get_text())
        if speed > maxSpd:
            speed = maxSpd
        entry.set_text(str(speed))

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

This is the non working code that should increment as long button is pressed:

#!/usr/bin/python
from gi.repository import Gtk, Gdk
from time import sleep

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="ST")

        MAX_SPD = 3000

        self.set_default_size(100,100)
        self.set_size_request(100,100)
        self.set_resizable(False)

        spdEntry = Gtk.Entry()
        spdEntry.set_has_frame(True)
        spdEntry.set_text("0")
        spdEntry.connect("activate", self.inputSpd, MAX_SPD)

        start  = Gtk.Button("Start")
        start.connect("clicked", self.clicked_start)
        stop   = Gtk.Button("Stop")
        stop.connect("clicked", self.clicked_stop)
        inc = Gtk.Button("inc")
        inc.connect("button-press-event", self.pressed_inc, spdEntry, MAX_SPD)
        inc.connect("button-release-event", self.left_inc)

        fixed  = Gtk.Fixed()

        fixed.put(start,    0, 0)
        fixed.put(spdEntry, 0, 40)
        fixed.put(stop,     0, 70)
        fixed.put(inc, 120, 0)

        self.add(fixed)

    def clicked_start(self, widget):
        self.set_title("GO")

    def clicked_stop(self, widget):
        self.set_title("ST")

    def pressed_inc(self, widget, event, entry, maxSpd):
        if event.type == Gdk.EventType.BUTTON_PRESS:
            speed = int(entry.get_text())
            speed = speed+1
            if speed > maxSpd:
                speed = maxSpd
            entry.set_text(str(speed))
            return True

    def left_inc(self, widget, event):
        if event.type == Gdk.EventType.BUTTON_RELEASE:
            return True


    def inputSpd(self, entry, maxSpd):
        speed = int(entry.get_text())
        if speed > maxSpd:
            speed = maxSpd
        entry.set_text(str(speed))

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
3
  • if I understood correctly you want to use a SpinButton (lazka.github.io/pgi-docs/#Gtk-3.0/classes/…) which will provide all the desired functions, including max value, step, and so on. Commented May 10, 2015 at 19:29
  • I will have a look at the spin button but I am not sure it fits my need. What I need is that the value is constantly updating as long the button is pressed (no clicks) Commented May 11, 2015 at 9:09
  • Hi @gianmt I have now checked the SpinButton documentation and it would have worked if I only wanted one button. My actual application will have several buttons with different speeds all updating same entry widget. It is probably doable to modify the SpinButton Class so it also has several buttons but that is definately out of my scope. Commented May 11, 2015 at 15:45

1 Answer 1

1

You can do this by using GLib.timeout_add(). However, I agree to gianmt that it is better to just use a Gtk.SpinButton

#!/usr/bin/python
from gi.repository import Gtk, Gdk, GLib

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="ST")

        self.MAXSPEED = 3000

        self.set_default_size(100,100)
        self.set_resizable(False)

        self.entry = Gtk.Entry()
        self.entry.set_text("0")

        start = Gtk.Button(label="Start")
        start.connect("clicked", self.clicked_start)
        stop = Gtk.Button(label="Stop")
        stop.connect("clicked", self.clicked_stop)
        inc = Gtk.Button(label="inc")
        inc.connect("button-press-event", self.pressed_inc)
        inc.connect("button-release-event", self.left_inc)

        fixed  = Gtk.Fixed()

        fixed.put(start,      0,   0)
        fixed.put(self.entry, 0,   40)
        fixed.put(stop,       0,   70)
        fixed.put(inc,        120, 0)

        self.add(fixed)

    def clicked_start(self, widget):
        self.set_title("GO")

    def clicked_stop(self, widget):
        self.set_title("ST")

    def pressed_inc(self, widget, event):
        self.inc_id = GLib.timeout_add(100, self.increase)

    def left_inc(self, widget, event,):
        GLib.source_remove(self.inc_id)

    def increase(self):
        speed = int(self.entry.get_text()) + 1
        if speed > self.MAXSPEED:
            self.entry.set_text(str(self.MAXSPEED))
        else:
            self.entry.set_text(str(speed))
        return True


win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

There was also a from time import sleep as an import on top of your code. It was not used and I do not know about the rest of your application but using time.sleep(), while you are not in a thread, will block the Gtk.main() loop and make your application unresponsive.

Sign up to request clarification or add additional context in comments.

2 Comments

The sleep has been removed and I forgot to remove the import
I have tried this successfully for the simple example provided here and if it works for the full application I will mark this as solved.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.