Seite 1 von 1

Fenster mit Headerbar - Verschieben während einer Prozesses nicht möglich

Verfasst: Montag 22. Januar 2018, 20:51
von martinjo
Hallo

Ich möchte gerne die Headerbar von Gtk3 nutzen: https://python-gtk-3-tutorial.readthedo ... #headerbar

Das Problem, sobald eine Operation ausgeführt wird, friert das komplette Fenster ein, also es ist noch nicht einmal möglich das Fenster zu minimieren oder zur Seite zu schieben.

GTK 3.18.9
Linux Mint 18.1

Freue mich sehr über Verschläge, Danke

Code: Alles auswählen

#!/usr/bin/env python3
#-*- coding: utf-8 -*-

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio
import time

class HeaderBarWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="HeaderBar Demo")
        self.set_modal(False)
        self.set_border_width(10)
        self.set_default_size(400, 200)

        hb = Gtk.HeaderBar()
        hb.set_show_close_button(True)
        hb.props.title = "HeaderBar example"
        self.set_titlebar(hb)

        button = Gtk.Button()
        icon = Gio.ThemedIcon(name="mail-send-receive-symbolic")
        image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
        button.add(image)
        hb.pack_end(button)
        
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        Gtk.StyleContext.add_class(box.get_style_context(), "linked")

        button = Gtk.Button()
        button.add(Gtk.Arrow(Gtk.ArrowType.LEFT, Gtk.ShadowType.NONE))
        box.add(button)

        button = Gtk.Button()
        button.add(Gtk.Arrow(Gtk.ArrowType.RIGHT, Gtk.ShadowType.NONE))
        box.add(button)

        hb.pack_start(box)
        
        self.add(Gtk.TextView())
        
        button = Gtk.Button("Sleep")
        button.connect("clicked", self.on_button_clicked)
        box.add(button)

    def on_button_clicked(self, widget):
        print "on_button_clicked"
        time.sleep(4)



if __name__ == "__main__":
    win = HeaderBarWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    Gtk.main()

Re: Fenster mit Headerbar - Verschieben während einer Prozesses nicht möglich

Verfasst: Montag 22. Januar 2018, 22:09
von __deets__
Willkommen in der Wunderbaren Welt der GUI Programmierung. Du darfst in der Ereignisbehandlung nur Sekundenbruchteile verbringen. Wenn du längere Aufgaben hast, brauchst du andere Mechanismen wie Timer oder Threads. Bei letzteren aber aufpassen, das du im Thread keine GUI Elemente anfasst.

Re: Fenster mit Headerbar - Verschieben während einer Prozesses nicht möglich

Verfasst: Mittwoch 24. Januar 2018, 11:46
von martinjo
Ja, daran versuche ich mich ja schon länger.

Ich habe es jetzt bei mir so umgesetzt, dass die Funktion in einem seperaten Thread starte. Dann war es nur noch tricky die Knöpfe zu deaktivieren während die Funktion läuft.

Code: Alles auswählen

    def on_button_clicked(self, widget):
        thread = Thread(target=self.do_some_work)
        thread.start()
        widget.set_sensitive(False)
        GObject.timeout_add(200, self.manage_button_sensitivity, thread,  widget)
        
    def manage_button_sensitivity(self, thread, widget):
        if thread.is_alive():
            return True
        else:
            widget.set_sensitive(True)

Auch ganz nett ist es eine Rückmeldung zu erhalten um z.B. eine Fortschrittsleiste zu füllen:

Code: Alles auswählen

   def on_button_clicked(self, widget):
        q = Queue()
        thread = Thread(target=self.do_some_work, args=(q,))
        thread.start()
        GObject.timeout_add(50, self.set_progress, thread, q)


    def set_progress(self, thread, q):
        if thread.is_alive():
            if not q.empty():
                self.progressbar.set_fraction(q.get())
            return True
        else:
            self.progressbar.set_fraction(0)


    def do_some_work(self, q):
        time.sleep(1)
        q.put(0.25)
        time.sleep(1)
        q.put(0.50)
        time.sleep(1)
        q.put(0.75)
        time.sleep(1)

Re: Fenster mit Headerbar - Verschieben während einer Prozesses nicht möglich

Verfasst: Dienstag 26. Februar 2019, 07:56
von uwekel
Schaue dir mal GObject.idle_add() an. Damit kannst du direkt aus dem Hintergrund-Thread Funktionen im Main-Thread aufrufen, ohne den Thread-Status abfragen zu müssen.