Pygtk StatusIcon 未加载?
我目前正在编写一个需要使用 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")
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:
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:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要像 qba 所说的那样调用 gtk.main 函数,但是每 N 毫秒调用一次函数的正确方法是使用 gobject.timeout_add 函数。在大多数情况下,您希望拥有任何可以将 gui 绑定在单独线程中的东西,但是在您只有一个图标的情况下,您不需要这样做。除非您计划使 StatusIcon 具有菜单。这是我更改的
Linup.py
部分:您还必须在某个地方
import gobject
。我不确定这是否有效,因为我无法安装 pycurl 。
编辑:在
linup_control.py
中,我会尝试更改为
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 thegobject.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 ofLinup.py
that I changed: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 changingto
你犯了两个错误。一个重要,一个不重要。
首先,如果您想使用股票图标,请使用 .set_from_stock( stock_id ) 方法。如果你想使用自己的图标,那么 .set_from_file(/path/to/img.png) 就可以了。
另一个认为女巫可能是主要问题是,当你编写 gtk 应用程序时,你必须调用 gtk.main() 函数。这是主 gtk 循环,所有信号处理/窗口绘制和所有其他 gtk 内容都已完成。如果你不这样做,你的图标就不会被绘制。
您的情况的解决方案是创建两个线程 - 一个用于 gui,第二个用于您的应用程序。在第一个中,您只需调用 gtk.main()。第二步,你将主程序循环起来。当然,当你调用 python 程序时,你已经启动了一个线程:P
如果你不熟悉线程,还有其他解决方案。 Gtk 有一个函数可以延迟调用您指定的函数:
但现在似乎已弃用。也许他们已经提出了更好的解决方案。
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:
But it seems to be deprecated now. Probably they have made a better solution.