Python GTK - 刷新 table/scrollwindow
Python GTK - refreshing a table/scrollwindow
在这个简单的程序中,我正在绘制一个 window,添加一个搜索框,为用户获取搜索词,在 postgreSQL 数据库中查找并显示结果。它在一定程度上起作用 - 当用户输入第二个查询时。
我尝试了两种不同的方法,但每种方法都会出现不同的问题。在第一种方式中(第 32-35 行 http://pastebin.com/q5bnLxaB),我在 main 中创建输出 window 并将其传递给搜索函数。它崩溃并显示 gtk_scrolled_window_add:断言 'child_widget == NULL' 失败。我想是因为我将树添加到 window 中,因为它已经完成了。要解决此问题,我需要以某种方式重置 window。
在第二种方式(第 56-58 行)中,我只在搜索功能中添加了输出 window,所以它不再有这个崩溃问题。但是,window 本身不会更新第二次或后续搜索的结果。
这些方法中哪一种最明智?我还需要考虑下一步是在每个搜索词旁边添加一个可点击的按钮,它将显示每个返回结果的扩展数据。
顺便说一句,在这两种情况下,输出 window 在输入搜索之前不会出现。它不妨碍功能,但对我来说很奇怪。
#!/usr/bin/python
from gi.repository import Gtk
from gi.repository.GdkPixbuf import PixbufLoader
import urllib2
import psycopg2
import sys
class NotebookWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Rugby Database")
#Create Application Window
self.set_border_width(10)
self.set_default_size(800, 600)
self.set_position(Gtk.WindowPosition.CENTER)
#Add external container (box)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
self.add(vbox)
#Add tabbed window
nbook = Gtk.Notebook()
vbox.pack_start(nbook, True, True, 0)
nbook.show()
#Add Main tab
label = Gtk.Label()
label.set_markup("<b><big>Main</big></b>")
table = Gtk.Table(rows=40, columns=10)
#Add Results field
#results_box = Gtk.ScrolledWindow()
#results_box.set_vexpand(True)
#table.attach(results_box, 0, 1, 1, 39, xpadding=5, ypadding=5)
#Add Search box
entry = Gtk.Entry()
entry.set_property("secondary-icon-stock", Gtk.STOCK_FIND)
entry.connect("icon-press", self.on_search_button)
#entry.connect("activate", self.on_search_enter, results_box)
entry.connect("activate", self.on_search_enter, table)
table.attach(entry, 0, 1, 0, 1, xpadding=5)
nbook.append_page(table, label)
def on_search_button(self, entry, icon, event):
search = entry.get_text()
print("Search for " + search)
def on_search_enter(self, entry, table): #changed from results_box
store = Gtk.ListStore(str, str, str)
tree = Gtk.TreeView(store)
##
results_box = Gtk.ScrolledWindow()
results_box.set_vexpand(True)
table.attach(results_box, 0, 1, 1, 39, xpadding=5, ypadding=5)
##
search = entry.get_text()
search = search.replace("'","''") #deal with apostrophes
entry.set_text("")
print("Search for " + search)
result = self.lookup_player(search)
print result
if len(result) > 0:
for i in range(0, len(result)):
store.append([result[i][0],result[i][1],str(result[i][4])])
print result[i][0],result[i][1],result[i][2],result[i][3],result[i][4],result[i][5],result[i][6],result[i][7],result[i][8]
else:
print "No players found"
#Add column for last name
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Last Name")
column.pack_start(renderer, True)
column.add_attribute(renderer, "text", 0)
tree.append_column(column)
#Add column for first name
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("First Name")
column.pack_start(renderer, True)
column.add_attribute(renderer, "text", 1)
tree.append_column(column)
#Add column for icon
renderer = Gtk.CellRendererPixbuf()
column = Gtk.TreeViewColumn("Show")
column.pack_start(renderer, True)
column.add_attribute(renderer, "stock-id", 2)
tree.append_column(column)
results_box.add(tree)
table.show_all()
tree.show_all()
def on_click_edit(self, button):
print("Editing Player")
def lookup_player(self, pstring):
try:
con = psycopg2.connect(database='Rugby', user='postgres', password = '1234')
cur = con.cursor()
search = "select pl.lastname, pl.firstname, pl.height, pl.weight, to_char(pl.dob, 'DD/MM/YYYY'), cl.name, pl.injury_id, to_char(pl.suspendeduntil, 'DD/MM/YYYY'), pl.photo from player pl inner join club cl on cl.id = pl.currentclub_id where firstname ilike '%s' or lastname ilike '%s'" % (pstring, pstring)
cur.execute(search)
result = cur.fetchall()
return result
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
win = NotebookWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
注意 这是后续问题
因为最初的查询已经得到回答,范围也因此发生了变化(顺便说一句,非常感谢所有帮助过的人!)
你应该在 __init__()
中尽你所能。这包括创建商店(作为实例变量,以便您可以在搜索处理程序中使用它)、创建所有小部件(ScrolledWindow 和 TreeView)以及将列添加到树视图。
在搜索处理程序中,您只应在 ListStore 上调用 clear()
(以删除所有旧结果),然后将新结果添加到存储中。
在这个简单的程序中,我正在绘制一个 window,添加一个搜索框,为用户获取搜索词,在 postgreSQL 数据库中查找并显示结果。它在一定程度上起作用 - 当用户输入第二个查询时。
我尝试了两种不同的方法,但每种方法都会出现不同的问题。在第一种方式中(第 32-35 行 http://pastebin.com/q5bnLxaB),我在 main 中创建输出 window 并将其传递给搜索函数。它崩溃并显示 gtk_scrolled_window_add:断言 'child_widget == NULL' 失败。我想是因为我将树添加到 window 中,因为它已经完成了。要解决此问题,我需要以某种方式重置 window。
在第二种方式(第 56-58 行)中,我只在搜索功能中添加了输出 window,所以它不再有这个崩溃问题。但是,window 本身不会更新第二次或后续搜索的结果。
这些方法中哪一种最明智?我还需要考虑下一步是在每个搜索词旁边添加一个可点击的按钮,它将显示每个返回结果的扩展数据。
顺便说一句,在这两种情况下,输出 window 在输入搜索之前不会出现。它不妨碍功能,但对我来说很奇怪。
#!/usr/bin/python
from gi.repository import Gtk
from gi.repository.GdkPixbuf import PixbufLoader
import urllib2
import psycopg2
import sys
class NotebookWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Rugby Database")
#Create Application Window
self.set_border_width(10)
self.set_default_size(800, 600)
self.set_position(Gtk.WindowPosition.CENTER)
#Add external container (box)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
self.add(vbox)
#Add tabbed window
nbook = Gtk.Notebook()
vbox.pack_start(nbook, True, True, 0)
nbook.show()
#Add Main tab
label = Gtk.Label()
label.set_markup("<b><big>Main</big></b>")
table = Gtk.Table(rows=40, columns=10)
#Add Results field
#results_box = Gtk.ScrolledWindow()
#results_box.set_vexpand(True)
#table.attach(results_box, 0, 1, 1, 39, xpadding=5, ypadding=5)
#Add Search box
entry = Gtk.Entry()
entry.set_property("secondary-icon-stock", Gtk.STOCK_FIND)
entry.connect("icon-press", self.on_search_button)
#entry.connect("activate", self.on_search_enter, results_box)
entry.connect("activate", self.on_search_enter, table)
table.attach(entry, 0, 1, 0, 1, xpadding=5)
nbook.append_page(table, label)
def on_search_button(self, entry, icon, event):
search = entry.get_text()
print("Search for " + search)
def on_search_enter(self, entry, table): #changed from results_box
store = Gtk.ListStore(str, str, str)
tree = Gtk.TreeView(store)
##
results_box = Gtk.ScrolledWindow()
results_box.set_vexpand(True)
table.attach(results_box, 0, 1, 1, 39, xpadding=5, ypadding=5)
##
search = entry.get_text()
search = search.replace("'","''") #deal with apostrophes
entry.set_text("")
print("Search for " + search)
result = self.lookup_player(search)
print result
if len(result) > 0:
for i in range(0, len(result)):
store.append([result[i][0],result[i][1],str(result[i][4])])
print result[i][0],result[i][1],result[i][2],result[i][3],result[i][4],result[i][5],result[i][6],result[i][7],result[i][8]
else:
print "No players found"
#Add column for last name
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Last Name")
column.pack_start(renderer, True)
column.add_attribute(renderer, "text", 0)
tree.append_column(column)
#Add column for first name
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("First Name")
column.pack_start(renderer, True)
column.add_attribute(renderer, "text", 1)
tree.append_column(column)
#Add column for icon
renderer = Gtk.CellRendererPixbuf()
column = Gtk.TreeViewColumn("Show")
column.pack_start(renderer, True)
column.add_attribute(renderer, "stock-id", 2)
tree.append_column(column)
results_box.add(tree)
table.show_all()
tree.show_all()
def on_click_edit(self, button):
print("Editing Player")
def lookup_player(self, pstring):
try:
con = psycopg2.connect(database='Rugby', user='postgres', password = '1234')
cur = con.cursor()
search = "select pl.lastname, pl.firstname, pl.height, pl.weight, to_char(pl.dob, 'DD/MM/YYYY'), cl.name, pl.injury_id, to_char(pl.suspendeduntil, 'DD/MM/YYYY'), pl.photo from player pl inner join club cl on cl.id = pl.currentclub_id where firstname ilike '%s' or lastname ilike '%s'" % (pstring, pstring)
cur.execute(search)
result = cur.fetchall()
return result
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
win = NotebookWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
注意 这是后续问题
你应该在 __init__()
中尽你所能。这包括创建商店(作为实例变量,以便您可以在搜索处理程序中使用它)、创建所有小部件(ScrolledWindow 和 TreeView)以及将列添加到树视图。
在搜索处理程序中,您只应在 ListStore 上调用 clear()
(以删除所有旧结果),然后将新结果添加到存储中。