0

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

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

Pygtk 完全按照它应该做的,并在系统托盘中显示一个图标 (lin_idle.png):

这工作正常

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

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

gtkInit()被调用时,我看到的是:

你为什么不工作 GSFKLJFSGDJKHSFDGHJKL

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

更新:出于某种原因,gtk.status_icon_new_from_file()在脚本中调用了几次之后,它最终确实创建了图标,但不幸的是,这个问题仍然存在。有没有人对可能出现的问题有任何想法?

根据要求:这是完整的脚本。这实际上是一个我处于早期制作阶段的应用程序,但如果你正确设置它,它现在确实可以工作,所以如果你愿意,可以随意使用它(也帮助我!),您只需要获取一个 imgur 开发者密钥并将其放入linup_control.py

Linup.py

#
# Linup - Linux 的 Dropbox 替代品!
# 由 Nakedsteve 撰写
# 在 MIT 许可下发布
#

导入操作系统
进口时间
导入配置解析器
从 linup_control 导入 Linup

cfg = ConfigParser.RawConfigParser()
# 看看我们是否有一个 .linuprc 文件
home = os.path.expanduser("~")

如果不是 os.path.exists(home+"/.linuprc"):
    # 不,所以让我们做一个
    cfg.add_section("路径")
    cfg.set("paths","watch_path", home+"/Desktop/screenshot1.png")

    # 现在将其写入文件
    使用 open(home+"/.linuprc","wb") 作为配置文件:
        cfg.write(配置文件)
别的:
    cfg.read(home+"/.linuprc")

linup = Linup()

# 创建 GUI(状态图标、菜单等)
linup.gtkInit()

# 进入主循环,我们检查是否有要上传的镜头
# 每 1 秒
path = cfg.get("paths","watch_path")
而1:
    如果(os.path.exists(路径)):
        linup.uploadImage(路径)
        url = linup.getURL()
        linup.toClipboard(url)
        linup.json = ""

        print "截图上传!"
        os.remove(路径)
    别的:
        # 如果你想知道我为什么使用 time.sleep()
        # 因为我发现没有它,我的 CPU 还在
        # 在运行 linup 时始终保持 50%。如果你有更好的
        # 方法,请联系我(我对python比较陌生)
        时间.sleep(1)

linup_control.py

导入gtk
导入json
进口时间
导入 pycurl
导入操作系统

班级阵容:
    def __init__(self):
        自我.json = ""

    def 上传图像(自我,路径):
        # 设置状态图标为忙
        self.statusIcon.set_from_file("img/lin_busy.png")

        # 创建新的 pycurl 实例
        cu = pycurl.Curl()

        # 将 POST 变量设置为 image 和 dev 键
        值 = [
            (“钥匙”,”*************”),
            (“图像”,(cu.FORM_FILE,路径))
        ]

        # 设置发送地址
        cu.setopt(cu.URL, "http://imgur.com/api/upload.json")
        # 这让我们得到 imgur 返回的 json
        cu.setopt(cu.WRITEFUNCTION,self.resp_callback)
        cu.setopt(cu.HTTPPOST, vals)

        # 做吧!
        cu.perform()
        cu.close()

        # 将状态图标设置为完成...
        self.statusIcon.set_from_file("img/lin_done.png")
        # 等待 3 秒
        时间.sleep(3)
        # 设置图标为空闲
        self.statusIcon.set_from_file("img/lin_idle.png")

    # 用于从 imgur 获取响应 json
    def resp_callback(self, buff):
        self.json += buff

    # 从json数据中提取图片URL
    def getURL(自我):
        js = json.loads(self.json)
        返回 js['rsp']['image']['original_image']

    # 将文本变量插入剪贴板
    def toClipboard(self, text):
        cb = gtk.Clipboard()
        cb.set_text(文本)
        cb.store()

    # 启动 Linup 的 GUI 元素
    def gtkInit(自我):
        self.statusIcon = gtk.StatusIcon()
        self.statusIcon.set_from_file("img/lin_idle.png")
4

2 回答 2

4

您需要gtk.main像 qba 所说的那样调用该函数,但是每 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")
于 2009-11-04T23:28:10.240 回答
1

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

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

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

您的解决方案是创建两个线程 - 一个用于 gui,第二个用于您的应用程序。在第一个中,您只需调用 gtk.main()。第二,你把你的主程序循环。当然,当您调用 python 程序时,您已经启动了一个线程:P

如果您不熟悉 whit 线程,还有其他解决方案。Gtk 具有调用您指定的函数的函数,但有一些延迟:

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

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

但它现在似乎已被弃用。可能他们已经提出了更好的解决方案。

于 2009-11-04T22:56:04.280 回答