0

我有一个脚本,它有一个记录和停止按钮,记录按钮执行一个无限循环,但它也阻止了另一个按钮(停止按钮)。我想要构建的只是一个从单击记录按钮开始并停止是单击停止按钮的过程。这是脚本:

# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
### BEGIN LICENSE
# This file is in the public domain
### END LICENSE

from locale import gettext as _

from gi.repository import Gtk # pylint: disable=E0611
import logging
logger = logging.getLogger('recordme')

from recordme_lib import Window
from recordme.AboutRecordmeDialog import AboutRecordmeDialog
from recordme.PreferencesRecordmeDialog import PreferencesRecordmeDialog

class RecordmeWindow(Window):
    __gtype_name__ = "RecordmeWindow"
    record = False

    def finish_initializing(self, builder): # pylint: disable=E1002
        """Set up the main window"""
        super(RecordmeWindow, self).finish_initializing(builder)

       self.AboutDialog = AboutRecordmeDialog
       self.PreferencesDialog = PreferencesRecordmeDialog

       # Code for other initialization actions should be added here.
       self.button1 = self.builder.get_object('button1')
       self.button2 = self.builder.get_object('button2')

    def on_button1_clicked(self, widget):
        while(not self.record):
             print 'button1 clicked'
             while gtk.events_pending():
                gtk.main_iteration(False)

关于这个问题的任何想法?

4

3 回答 3

2

我在 WX 中遇到过类似的程序,它也是基于事件的。我发现解决该问题的最佳(可能也是唯一)方法是创建一个在主循环期间在计时器上运行的函数。我的会定期运行,但您也可以将其设置为在运行函数时等待并关闭循环。在 GTK 中,您必须使用另一个模块“gobject”来执行此操作。下面是一个在 GTK 中定期运行的方法示例。

import gobject

class gtk_object(object):
    def __init__(self):
        gobject.timeout_add(100, self.my_function)
    def my_function(self):
        #do something here, like stopping the loop or having a timer to stop the loop
        return True
于 2013-11-19T04:44:32.147 回答
1

GTK+(与大多数 UI 工具包一样)是基于事件的。这意味着它运行内部“事件循环”——一个收集和处理事件的循环,例如处理用户输入和重绘窗口。所有事件处理程序都是从主循环分派的。为了处理事件,循环必须“旋转”。

在您的示例中,您正在阻止主循环:

def on_button1_clicked(self, widget):
    while(not self.record):
         print 'button1 clicked'

只要这个函数没有完成,控制就不会返回到主循环,所以它不能处理其他事件,或者重绘窗口。

您可以在PyGTK FAQ中添加此代码段,以允许主循环同时处理事件:

while gtk.events_pending():
  gtk.main_iteration(False)
于 2013-11-11T20:01:53.660 回答
1

假设您的记录功能是 CPU 密集型和/或可能阻塞和/或需要软实时保证,我建议将其移至单独的“工作”线程。

然后,创建一个窗口和您的按钮。

在这里,当点击“记录”时,我向工人发出信号开始记录;当点击“停止”时,通知工人停止;或者,当单击停止时,如果您希望您的应用程序退出,则终止主循环。

在窗口关闭时终止应用程序并正确终止工作线程的附加控制逻辑位于最底部。

#!/usr/bin/env python
import time
import logging
import threading
from gi.repository import Gtk


class Worker(threading.Thread):
    should_record = False
    quit = False

    def run(self):
        while not self.quit:
            if self.should_record:
                logging.warn("recording...")
                # cpu-intensive code here
            else:
                time.sleep(0.1)


class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.worker = Worker()
        self.worker.start()
        hb = Gtk.Box()
        self.add(hb)
        record = Gtk.Button("Record")
        stop = Gtk.Button("Stop")
        hb.add(record)
        hb.add(stop)

        def command(arg):
            self.worker.should_record = arg

        record.connect("clicked", lambda _b: command(True))
        stop.connect("clicked", lambda _b: command(False))
        # optional, if you want to quit the app on stop as well
        stop.connect("clicked", lambda _b: Gtk.main_quit())

if __name__ == "__main__":
    main = MainWindow()
    try:
        # optional, if you want to support close window to quit app
        main.connect("delete-event", Gtk.main_quit)
        main.show_all()
        Gtk.main()
    finally:
        main.worker.quit = True
        main.worker.join()

老东西

理想情况下,您希望使用Gtk.main()而不是Gtk.main_iteration()在 Gtk+ 3 中使用。

在 Gtk+ 2 中,模块名称是gtk而不是gi.repository.Gtk.

然后你可以退出机智:

gtk.main_quit

def main_quit()

Gtk.main_quit() 函数终止由最近一次调用 Gtk.main() 函数启动的当前主循环级别。调用此函数可降低主循环的嵌套级别。

您可以有多个嵌套的主循环,在这种情况下,您必须退出其中的每一个。

或者,您也可以使用gtk_dialog.run()按钮的默认操作是退出循环。

于 2013-11-18T14:09:22.643 回答