我目前正在开发一个需要使用gtk.StatusIcon()
的小脚本。出于某种原因,我得到了一些奇怪的行为。如果我进入python交互式shell并输入:
>> 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()
被调用时,我会看到这一点:
我让我在与交互式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")
答案 0 :(得分:4)
你需要像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")
答案 1 :(得分: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()
但现在似乎已被弃用了。可能他们已经做出了更好的解决方案。