2015-12-02 76 views
0

在我的應用程序中,我有大約500個按鈕,當採取特定操作時,它們都會更新它們的標籤和顏色。我也陷入了崩潰,當我發現性能問題(通過使用CPROFILE和PDB),這個問題是通過改變按鈕的顏色造成的:如何更改pygtk gtk.Button顏色正確

這樣
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() 

結果:

button is not red

我也試過這涉及檢索和修改了樣式替代。這導致與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

我最終通過使用gtk.EventBox來實現我自己的按鈕,該按鈕的小部件樹中保存着gtk.Label。與按鈕不同,設置標籤顏色似乎不會與操作系統衝突。

我還實施了幾個方便的功能,如set_label()

modify_bg仍然太慢,但它不會導致死機。通過檢查當前顏色是否與我想設置的顏色相同,我還爲不改變的按鈕節省了大量計算時間。

我的代碼很粗略,但它適用於我的目的。隨意使其更加堅固和/或柔性:

my colored button

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()