在我的应用程序中,我有大约500个按钮,这些按钮在采取特定操作时都会更新其标签和颜色。当我注意到(通过使用cProfile和pdb)问题是由更改按钮颜色引起的时候,我遇到了崩溃和性能问题:
self.button.modify_bg(gtk.STATE_PRELIGHT, color)
self.button.modify_bg(gtk.STATE_NORMAL, color)
像这样的500次调用需要5秒的永久性(这也会冻结GUI),并且应用程序运行的时间越长,速度就越慢。如果有人想知道,我有一个强大的处理器和大量的可用内存。
之前我试图按照docs中的建议使用EventBox。但是,这只会改变按钮后面的颜色,而不是表面上的颜色:
import gtk
win = gtk.Window()
win.connect("destroy", gtk.main_quit)
btn = gtk.Button("test")
eb = gtk.EventBox()
eb.add(btn)
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("red"))
win.add(eb)
win.show_all()
gtk.main()
结果:
我还尝试了另一种涉及检索和修改样式的方法。这导致与modify_bg
相同的缓慢。此外,我还在随机位置随机崩溃,通常会出现低级内存分配错误,例如从gtk中双重释放。
import gtk
win = gtk.Window()
win.connect("destroy", gtk.main_quit)
btn = gtk.Button("test")
#copy the current style and replace the background
style = btn.get_style().copy()
style.bg[gtk.STATE_NORMAL] = gtk.gdk.color_parse("red")
#set the button's style to the one you created
btn.set_style(style)
win.add(btn)
win.show_all()
gtk.main()
按钮的颜色似乎是由操作系统管理的,我无法在没有缓慢,崩溃或不良结果的情况下找到解决方法。我非常需要通过颜色传达有关按钮的重要信息。
那么如何正确更改按钮颜色?
答案 0 :(得分:0)
我最终使用gtk.EventBox
实现了我自己的Button,gtk.Label
在其小部件树中保存了set_label()
。与按钮不同,设置标签颜色似乎与操作系统不冲突。
我还实现了一些便利功能,例如modify_bg
import gtk
class ColoredButton(gtk.EventBox):
'''
This class implements a simple unanimated button
whose color can be changed
'''
def __init__(self, widget = gtk.Label()):
'''
widget must be a gtk.Label
this is not checked in this simple version
'''
#initialize superclass EventBox
super(ColoredButton, self).__init__()
#embed widget inside vbox and hbox
self.widget = widget
self.vbox = gtk.VBox(homogeneous=False, spacing=0)
self.hbox = gtk.HBox(homogeneous=False, spacing=0)
self.hbox.pack_start(self.vbox, expand = True, fill=False)
self.vbox.pack_start(self.widget, expand = True, fill = False)
#draws a frame around the entire construct to make everything look more like a button
self.frame = gtk.Frame()
self.frame.add(self.hbox)
#add the final "button" to this EventBox in order to handle events
self.add(self.frame)
#define which events should be reacted to, those constants can be found in pygtk docs
self.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.add_events(gtk.gdk.ENTER_NOTIFY_MASK)
self.add_events(gtk.gdk.LEAVE_NOTIFY_MASK)
#activate focus
self.set_can_focus(True)
#align the "button" text in the middle of the box
self.widget.set_alignment(xalign=0.5, yalign=0.5)
def show(self):
super(ColoredButton, self).show()
self.hbox.show()
self.vbox.show()
self.frame.show()
self.widget.show()
def set_label(self, label):
self.set_text(label)
def set_text(self, text):
self.widget.set_text(text)
def changeColor(self, color, state = gtk.STATE_NORMAL):
if color is not None:
currentcolor = self.style.bg[state]
#too lazy to look up in docs if color != currentcolor also works
if color.red != currentcolor.red or color.green != currentcolor.green or color.blue != currentcolor.blue:
self.modify_bg(state, color)
def changeTextColor(self, color, state = gtk.STATE_NORMAL):
if color is not None:
currentcolor = self.style.bg[state]
if color.red != currentcolor.red or color.green != currentcolor.green or color.blue != currentcolor.blue:
self.widget.modify_fg(gtk.STATE_NORMAL, color)
def onButtonClick(widget, event = None):
if event.button == 1:
widget.set_label("left click")
elif event.button == 2:
widget.set_label("middle click")
elif event.button == 3:
widget.set_label("right click")
import gtk
w = gtk.Window()
w.connect('destroy', gtk.main_quit)
coloredbutton=ColoredButton(widget = gtk.Label("Hello there"))
coloredbutton.changeColor(gtk.gdk.color_parse("black"))
coloredbutton.changeTextColor(gtk.gdk.color_parse("yellow"))
coloredbutton.set_size_request(width = 100, height = 50)
coloredbutton.connect("button-release-event", onButtonClick)
w.add(coloredbutton)
w.show_all()
gtk.main()
仍然太慢,但不会导致崩溃。通过检查当前颜色是否与我想要设置的颜色相同,我还为不改变的按钮节省了大量的计算时间。
我的代码非常粗略,但它适用于我的目的。随意使其更加强大和/或灵活:
Meteor.methods({
add_new_email: function(address)
{
Accounts.addEmail(Meteor.userId(), address);
}
});