Pygtk StatusIcon 未加载?

发布于 2024-08-09 04:08:58 字数 4033 浏览 4 评论 0原文

我目前正在编写一个需要使用 gtk.StatusIcon() 的小脚本。出于某种原因,我遇到了一些奇怪的行为。如果我进入 python 交互式 shell 并输入:

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

Pygtk 会完全执行其应该执行的操作,并在系统托盘中显示一个图标 (lin_idle.png):

This Works Fine

但是,如果我尝试在脚本中执行相同的任务:

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

当调用 gtkInit() 时,我会看到以下内容:

WHY WON'T YOU WORK GSFKLJFSGDJKHSFDGHJKL

我让我在与交互式 python shell 相同的工作目录中运行脚本,所以我很确定它找到了图像,所以我很困惑......有人有什么想法吗?提前致谢。

更新:由于某种原因,在脚本中调用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")

I'm currently working on a small script that needs to use gtk.StatusIcon(). For some reason, I'm getting some weird behavior with it. If I go into the python interactive shell and type:

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

Pygtk does exactly what it should do, and shows an icon (lin_idle.png) in the system tray:

This works fine

However, if I try to do the same task in my script:

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

When gtkInit() gets called, I see this instead:

WHY WON'T YOU WORK GSFKLJFSGDJKHSFDGHJKL

I made I ran the script in the same working directory as the interactive python shell, so I'm pretty sure it's finding the image, so I'm stumped... Any ideas anyone? Thanks in advance.

Update: For some reason or another, after calling gtk.status_icon_new_from_file() a few times in the script, it does eventually create the icon, but this issue still remains unfortunately. Does anyone at all have any ideas as to what could be going wrong?

As requested: Here's the full script. This is actually an application that I'm in the very early stages of making, but it does work at the moment if you get it setup correctly, so feel free to play around with it if you want (and also help me!), you just need to get an imgur developer key and put it in 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")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晒暮凉 2024-08-16 04:08:58

您需要像 qba 所说的那样调用 gtk.main 函数,但是每 N 毫秒调用一次函数的正确方法是使用 gobject.timeout_add 函数。在大多数情况下,您希望拥有任何可以将 gui 绑定在单独线程中的东西,但是在您只有一个图标的情况下,您不需要这样做。除非您计划使 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")

gobject.timeout_add(3000, self.statusIcon.set_from_file, "img/lin_idle.png")

You need to call the gtk.main function like qba said, however the correct way to call a function every N milliseconds is to use the gobject.timeout_add function. In most cases you would want to have anything that could tie up the gui in a separate thread, however in your case where you just have an icon you don't need to. Unless you are planning on making the StatusIcon have a menu. Here is the part of Linup.py that I changed:

# 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()

You will have to import gobject somewhere too.

I don't know for sure if this works because I can't get pycurl installed.

EDIT: In linup_control.py, I would try changing

# 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")
标点 2024-08-16 04:08:58

你犯了两个错误。一个重要,一个不重要。

首先,如果您想使用股票图标,请使用 .set_from_stock( stock_id ) 方法。如果你想使用自己的图标,那么 .set_from_file(/path/to/img.png) 就可以了。

另一个认为女巫可能是主要问题是,当你编写 gtk 应用程序时,你必须调用 gtk.main() 函数。这是主 gtk 循环,所有信号处理/窗口绘制和所有其他 gtk 内容都已完成。如果你不这样做,你的图标就不会被绘制。

您的情况的解决方案是创建两个线程 - 一个用于 gui,第二个用于您的应用程序。在第一个中,您只需调用 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()

但现在似乎已弃用。也许他们已经提出了更好的解决方案。

You made two mistakes. One is important one is not.

At first if you want to use stock icon use .set_from_stock( stock_id ) method. If you want to use your own icon then the .set_from_file(/path/to/img.png) is ok.

The other think witch is the probably the main problem is that when you write gtk application you have to call gtk.main() function. This is main gtk loop where all signal handling/window drawing and all other gtk stuff is done. If you don't do this, simply your icon is not drawing.

The solution in your case is to make two threads - one for gui, second for your app. In the first one you simply call gtk.main(). In second you put your main program loop. Of course when you call python program you have one thread already started:P

If you aren't familiar whit threads there is other solution. Gtk have function which calls function specified by you with some delay:

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

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

But it seems to be deprecated now. Probably they have made a better solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文