- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在不实际点击按钮的情况下与按钮交互的正确方法是什么?
我有一个按钮“按钮”,点击后可以:
我有一个 TreeView ,其行必须在双击时:
只有第一部分有效。 “foo”函数被调用(通过按钮的回调,直接用于 TreeView 项)并且参数(“文件名”)被检索正常,但是如何执行作业的第 2 部分(更改“按钮”的属性, 这是它的图标)?
import gtk
class Lister(object):
def __init__(self):
self.hbox = gtk.HBox()
liststore = gtk.ListStore(str)
liststore.append(["foo"])
liststore.append(["bar"])
treeview = gtk.TreeView(liststore)
self.hbox.pack_start(treeview, False)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("Column 1")
col.pack_start(cell, True)
col.set_attributes(cell,text=0)
treeview.connect('row-activated', self.open_file)
treeview.append_column(col)
def open_file(self, button, *args):
Buttons().the_method(self, "foo")
class Buttons(object):
OPEN_IMAGE = gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_BUTTON)
CLOSED_IMAGE = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
def __init__(self):
self.button = gtk.Button() # THIS is the button to modify
self.hbox = gtk.HBox()
self.hbox.pack_start(self.button, False)
self.button.set_image(self.OPEN_IMAGE)
self.button.connect('clicked', self.the_method, "plop")
self.toggled = True
def the_method(self, button, filename):
print filename
print vars(self)
if self.toggled:
self.button.set_image(self.CLOSED_IMAGE)
self.toggled = False
else:
self.button.set_image(self.OPEN_IMAGE)
self.toggled = True
class GUI(object):
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def __init__(self):
self.window = gtk.Window()
self.window.set_size_request(100, 150)
self.window.connect("delete_event", self.delete_event)
vbox = gtk.VBox()
vbox.pack_start(Buttons().hbox, False, False, 1)
vbox.pack_start(Lister().hbox)
self.window.add(vbox)
self.window.show_all()
return
def main():
gtk.main()
if __name__ == "__main__":
GUI()
main()
最佳答案
我强烈反对 user1146332 的回答。这不是 GTK+ 问题,也不是强设计问题,只是面向对象编程问题。错误的原因是您这样调用 the_method
:
Buttons().the_method(self, "foo")
这是行不通的,因为您混淆了两个不同的基本事物:一个类和一个类的实例。当您调用 Buttons()
时,您正在创建 Buttons
类的新实例。因此,由于此类不是单例,您实际上是在创建一个新实例,带有一个新的 GtkButton,并且最终不会与您之前创建的按钮进行交互。
这里的解决方案是让 Lister
对象知道它需要修改什么,这意味着围绕您之前创建的 Buttons
实例进行存储,例如在 self.button
,并在其上调用 the_method
。
self.button.the_method("foo")
这是您的代码的略微修改版本。重要的是 Lister
实例现在知道它需要修改的 Buttons
实例。
import gtk
class Lister(object):
def __init__(self, button):
self.hbox = gtk.HBox()
self.button = button
liststore = gtk.ListStore(str)
liststore.append(["foo"])
liststore.append(["bar"])
treeview = gtk.TreeView(liststore)
self.hbox.pack_start(treeview, False)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("Column 1")
col.pack_start(cell, True)
col.set_attributes(cell,text=0)
treeview.connect('row-activated', self.open_file)
treeview.append_column(col)
def open_file(self, button, *args):
self.button.the_method("foo")
class Buttons(object):
OPEN_IMAGE = gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_BUTTON)
CLOSED_IMAGE = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
def __init__(self):
self.button = gtk.Button() # THIS is the button to modify
self.hbox = gtk.HBox()
self.hbox.pack_start(self.button, False)
self.button.set_image(self.OPEN_IMAGE)
self.button.connect('clicked', self.the_method, "plop")
self.toggled = True
def the_method(self, filename):
print filename
print vars(self)
if self.toggled:
self.button.set_image(self.CLOSED_IMAGE)
self.toggled = False
else:
self.button.set_image(self.OPEN_IMAGE)
self.toggled = True
class GUI(object):
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def __init__(self):
self.window = gtk.Window()
self.window.set_size_request(100, 150)
self.window.connect("delete_event", self.delete_event)
vbox = gtk.VBox()
buttons = Buttons()
vbox.pack_start(buttons.hbox, False, False, 1)
vbox.pack_start(Lister(buttons).hbox)
self.window.add(vbox)
self.window.show_all()
return
def main():
gtk.main()
if __name__ == "__main__":
GUI()
main()
但是,仍有很大的改进空间。我建议您不要使用 __init__
函数来创建您的小部件,而是使用 create
方法来返回您的小部件树的顶层小部件。这是因为您不能在 __init__
中返回任何内容,因此使用不同的方法比在那里引发异常更容易。
b = Buttons()
vbox.pack_start(b.create(), False, False, 1)
l = Lister(b)
vbox.pack_start(l.create(), False, False, 1)
其他改进可能是(抱歉,我在这里为 GTK 类/函数使用 C 命名,我比 python 更了解它):
GtkToggleButton
而不是自己跟踪按钮状态linuxfr 见:-)
关于 python : How can two GTK widgets interact with each other?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18151670/
我是一名优秀的程序员,十分优秀!