Pygtk StatusIcon не загружается?

В настоящее время я работаю над небольшим скриптом, который должен использовать gtk.StatusIcon(). По какой-то причине я веду себя с ним странно. Если я войду в интерактивную оболочку Python и наберу:

>> import gtk
>> statusIcon = gtk.status_icon_new_from_file("img/lin_idle.png")

Pygtk делает именно то, что должен, и показывает значок (lin_idle.png) на панели задач:

Отлично работает

Однако, если я попытаюсь выполнить ту же задачу в своем скрипте:

def gtkInit(self):
    self.statusIcon = gtk.status_icon_new_from_file("img/lin_idle.png")

Когда вызывается gtkInit(), я вижу следующее:

ПОЧЕМУ ВЫ НЕ РАБОТАЕТЕ GSFKLJFSGDJKHSFDGHJKL

Я запустил скрипт в том же рабочем каталоге, что и интерактивная оболочка python, так что я почти уверен, что он находит изображение, так что я в тупике ... Есть какие-нибудь идеи? Заранее спасибо.

Обновление: по той или иной причине после нескольких вызовов gtk.status_icon_new_from_file() в скрипте в конечном итоге создается значок, но, к сожалению, эта проблема все еще остается. Есть ли у кого-нибудь вообще идеи относительно того, что может пойти не так?

По запросу: вот полный сценарий. На самом деле это приложение, над которым я сейчас работаю, но оно действительно работает в настоящий момент, если вы правильно настроили его, поэтому не стесняйтесь экспериментировать с ним, если хотите ( а также помогите мне!), вам просто нужно получить ключ разработчика imgur и положить его в linup_control.py

Linup.py

#
# Linup - A dropbox alternative for Linux!
# Written by Nakedsteve
# Released under the MIT License
#

import os
import time
import ConfigParser
from linup_control import Linup

cfg = ConfigParser.RawConfigParser()
# See if we have a .linuprc file
home = os.path.expanduser("~")

if not os.path.exists(home+"/.linuprc"):
    # Nope, so let's make one
    cfg.add_section("paths")
    cfg.set("paths","watch_path", home+"/Desktop/screenshot1.png")

    # Now write it to the file
    with open(home+"/.linuprc","wb") as configfile:
        cfg.write(configfile)
else:
    cfg.read(home+"/.linuprc")

linup = Linup()

# Create the GUI (status icon, menus, etc.)
linup.gtkInit()

# Enter the main loop, where we check to see if there's a shot to upload
# every 1 second
path = cfg.get("paths","watch_path")
while 1:
    if(os.path.exists(path)):
        linup.uploadImage(path)
        url = linup.getURL()
        linup.toClipboard(url)
        linup.json = ""

        print "Screenshot uploaded!"
        os.remove(path)
    else:
        # If you're wondering why I'm using time.sleep()
        # it's because I found that without it, my CPU remained
        # at 50% at all times while running linup. If you have a better
        # method for doing this, please contact me about it (I'm relatively new at python)
        time.sleep(1)

linup_control.py

import gtk
import json
import time
import pycurl
import os

class Linup:
    def __init__(self):
        self.json = ""

    def uploadImage(self, path):
        # Set the status icon to busy
        self.statusIcon.set_from_file("img/lin_busy.png")

        # Create new pycurl instance
        cu = pycurl.Curl()

        # Set the POST variables to the image and dev key
        vals = [
            ("key","*************"),
            ("image", (cu.FORM_FILE, path))
        ]

        # Set the URL to send to
        cu.setopt(cu.URL, "http://imgur.com/api/upload.json")
        # This lets us get the json returned by imgur
        cu.setopt(cu.WRITEFUNCTION, self.resp_callback)
        cu.setopt(cu.HTTPPOST, vals)

        # Do eet!
        cu.perform()
        cu.close()

        # Set the status icon to done...
        self.statusIcon.set_from_file("img/lin_done.png")
        # Wait 3 seconds
        time.sleep(3)
        # Set the icon to idle
        self.statusIcon.set_from_file("img/lin_idle.png")

    # Used for getting the response json from imgur
    def resp_callback(self, buff):
        self.json += buff

    # Extracts the image URL from the json data
    def getURL(self):
        js = json.loads(self.json)
        return js['rsp']['image']['original_image']

    # Inserts the text variable into the clipboard
    def toClipboard(self, text):
        cb = gtk.Clipboard()
        cb.set_text(text)
        cb.store()

    # Initiates the GUI elements of Linup
    def gtkInit(self):
        self.statusIcon = gtk.StatusIcon()
        self.statusIcon.set_from_file("img/lin_idle.png")

person Steve Gattuso    schedule 02.11.2009    source источник
comment
Можете ли вы опубликовать весь скрипт Python?   -  person Isaiah    schedule 04.11.2009
comment
Прежде всего, я бы попытался использовать абсолютный путь, чтобы увидеть, связано ли это с путями поиска значков.   -  person ntd    schedule 04.11.2009


Ответы (2)


Вам нужно вызвать функцию gtk.main, как сказал qba, однако правильный способ вызова функции каждые N миллисекунд - использовать функцию gobject.timeout_add. В большинстве случаев вам может понадобиться что-нибудь, что может связать графический интерфейс в отдельном потоке, однако в вашем случае, когда у вас просто есть значок, вам это не нужно. Если вы не планируете сделать StatusIcon меню. Вот часть Linup.py, которую я изменил:

# Enter the main loop, where we check to see if there's a shot to upload
# every 1 second
path = cfg.get("paths","watch_path")
def check_for_new():

    if(os.path.exists(path)):
        linup.uploadImage(path)
        url = linup.getURL()
        linup.toClipboard(url)
        linup.json = ""

        print "Screenshot uploaded!"
        os.remove(path)
    # Return True to keep calling this function, False to stop.  
    return True

if __name__ == "__main__":

    gobject.timeout_add(1000, check_for_new)

    gtk.main()

Вам тоже придется где-то import gobject.

Я не знаю наверняка, работает ли это, потому что я не могу установить pycurl.

РЕДАКТИРОВАТЬ: в linup_control.py я бы попытался изменить

# Wait 3 seconds
time.sleep(3)
# Set the icon to idle
self.statusIcon.set_from_file("img/lin_idle.png")

to

gobject.timeout_add(3000, self.statusIcon.set_from_file, "img/lin_idle.png")
person Isaiah    schedule 04.11.2009
comment
Это решение, с которым мне удалось заставить работать, однако теперь я немного застрял в изменении значка на другое изображение, как показано на Linup.uploadImage(). Это моя собственная ошибка или мне нужно создать отдельный поток, чтобы изменить gtk.StatusIcon()? - person Steve Gattuso; 05.11.2009

Вы сделали две ошибки. Одно важно, другое - нет.

Сначала, если вы хотите использовать стоковую иконку, используйте метод .set_from_stock (stock_id). Если вы хотите использовать свой собственный значок, тогда подойдет .set_from_file (/path/to/img.png).

Другая проблема заключается в том, что, когда вы пишете приложение gtk, вы должны вызывать функцию gtk.main (). Это основной цикл gtk, в котором выполняется вся обработка сигналов / отрисовка окон и все другие вещи gtk. Если вы этого не сделаете, ваш значок просто не будет рисоваться.

Решение в вашем случае - создать два потока - один для графического интерфейса, второй для вашего приложения. В первом вы просто вызываете gtk.main (). Во второй вы помещаете основной цикл программы. Конечно, когда вы вызываете программу Python, у вас уже запущен один поток: P

Если вы не знакомы с нитками, есть другое решение. В Gtk есть функция, которая вызывает указанную вами функцию с некоторой задержкой:

def call_me:
    print "Hello World!"
    gtk.timeout_add( 1000 , call_me )

gtk.timeout_add( 1000 , call_me )
gtk.main()

Но, похоже, сейчас он устарел. Возможно, они приняли лучшее решение.

person qba    schedule 04.11.2009