[英]How to change pygtk gtk.Button color PROPERLY
在我的應用程序中,我有大約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()
似乎按鈕的顏色是由操作系統管理的,沒有緩慢,崩潰或不良結果,我無法找到解決方法。 我非常需要通過顏色傳達有關按鈕的重要信息。
那么如何正確更改按鈕的顏色呢?
我最終通過使用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()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.