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

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

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()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

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)
Benutzeravatar
uwekel
User
Beiträge: 1
Registriert: Dienstag 1. Januar 2013, 09:33
Wohnort: Oldenburg

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.
Antworten