Я вставил две графики matplotlib в контейнер, используя GTK3, Python и Glade.Они отображают погоду локали, используя данные стороннего API.Я хочу, чтобы графики обновлялись при вводе новой локали и нажатии кнопки обновления.
Каждое из приведенных ниже решений заканчивалось различными проблемами.Слишком много, чтобы разграничить.Как правило, им удалось отобразить другой экземпляр главного окна с новыми графиками, но старый экземпляр со старыми графиками остается открытым.Я пытался:
Уничтожить родительский контейнер и затем загрузить обновленный.Следующий код вызывает ошибку сегментации.Код пытается передать объект из нового экземпляра компоновщика в старый.Я считаю, что это моя главная проблема.Я не знаю, как передать экземпляр компоновщика, с которым я работаю, в on_refresh_button_click()
без необходимости переписывать все в один класс.
def on_refresh_button_click(self, widget):
parent = self.get_parent()
grandparent = parent.get_parent()
parent.destroy()
city_name = "yerevan"
db = "test.db"
get_updated_data(city_name)
builder = builder_with_signals()
read_weather_from_db(db, builder, city_name)
grandparent.add(parent)
parent.show_all()
Использование self.get_parent()
получить родительский контейнер кнопки как объект для работы.Это почти сработало, я думаю.Я мог бы remove()
и destroy()
контейнер, содержащий граф.И я думаю, что я также успешно добавил обновленный.Но я не мог заставить это показать.Код:
def on_refresh_button_click(self, widget):
parent = self.get_parent()
city_name = "yerevan"
db = "test.db"
get_updated_data(city_name)
fig_list = read_weather_from_db(db, city_name)
for child in parent:
try:
for grandchild in child:
if Gtk.Buildable.get_name(grandchild) == "chart_past":
parent = child # Confusing, yes.
old = grandchild
new = FigureCanvas(fig_list[0])
props = {}
for key in parent.list_child_properties():
props[key.name] = parent.child_get_property(old, key.name)
parent.remove(old)
parent.add(new)
for name, value in props.items():
parent.child_set_property(new, name, value)
parent.show_all()
child.show_all()
grandchild.show_all()
# Try to find the newly added object
for item in parent:
print("trying to find another:", Gtk.Buildable.get_name(item))
except:
print(Gtk.Buildable.get_name(child))
Удаление старого контейнера / виджета и добавление нового, используя этот код из здесь :
def replace_widget(old, new):
parent = old.get_parent()
props = {}
for key in Gtk.ContainerClass.list_child_properties(type(parent)):
props[key.name] = parent.child_get_property(old, key.name)
parent.remove(old)
parent.add(new)
for name, value in props.iteritems():
parent.child_set_property(new, name, value)
Уничтожение главного окна перед запуском скрипта с нуля с другим языковым стандартом:
def on_refresh_button_click(self, widget):
builder = setup_builder()
add_signals(builder)
window = builder.get_object("window1")
window.destroy()
display_data("yerevan")
Закрытие программы и ее перезапуск, что не вызываетсмысл даже для меня, но:
def on_refresh_button_click(self, widget):
Gtk.main_quit()
display_data("yerevan")
Использование canvas.draw()
из здесь , здесь и здесь .
Замена add_with_viewport()
на add()
, потому что this говорит о проблемах.
Также читайте разные частиэтой документации и пробовал несколько других вещей, но это были долгие два дня, поэтому я забыл.
Большинство примеров, кажется, создают приложения с GTK3 и Python, но без Glade.Они также используют классы.Я не хочу использовать классы (на данный момент).Я хотел бы увидеть, если кто-нибудь знает решение, прежде чем я переписать все это в один класс.Я, наверное, просто неправильно понимаю или что-то упустил.
Я супер новичок в GTK и Glade, и это моя первая попытка, так что извините за беспорядок.Я пропустил код SQL CRUD и код, который отправляет запросы в API.Те работают отлично.Соответствующий код:
# SETUP THE BUILDER
def setup_builder():
return Gtk.Builder()
def add_signals(builder):
builder.add_objects_from_file('weather.xml', ('window1', 'refresh_button', 'box_charts'))
return builder.connect_signals({'on_window1_destroy': (on_window1_destroy,'window1'),
'on_refresh_button_click': (on_refresh_button_click,),
})
def builder_with_signals():
builder = setup_builder()
add_signals(builder)
return builder
# READ DATA FROM DATABASE
def read_weather_from_db(db, builder, city_name):
chart_future_values = read_db(db, "chart_future", city_name)
chart_past_values = read_db(db, "chart_past", city_name)
fig_future = embed_chart("day and time", "temp", chart_future_values["xticks"], chart_future_values["datetimes_x_axis"], chart_future_values["temps"])
fig_past = embed_chart("day and time", "temp", chart_past_values["xticks"], chart_past_values["datetimes_x_axis"], chart_past_values["temps"])
add_canvas(builder, "chart_future", fig_future)
add_canvas(builder, "chart_past", fig_past)
return builder
# EMBED THE CHARTS INTO CONTAINERS
def embed_chart(xlabel, ylabel, xticks, xticklabels, yticks):
fig = Figure(figsize=(5, 5), dpi=100)
chart = fig.add_subplot(111)
chart.set_xlabel(xlabel)
chart.set_ylabel(ylabel)
chart.set_xticks(xticks)
chart.set_xticklabels(xticklabels, rotation=90)
chart.plot(xticks, yticks)
return fig
def add_canvas(builder, chart_container, fig):
canvas = FigureCanvas(fig)
subbox_chart = builder.get_object(chart_container)
subbox_chart.add(canvas)
# THIS RUNS THE SCRIPT
def display_data(city_name="isfahan"):
get_updated_data(city_name)
builder = builder_with_signals()
read_weather_from_db("test.db", builder, city_name)
show_gtk(builder)
def on_window1_destroy(self, widget):
Gtk.main_quit()
# HERE IS THE IMPORTANT BIT
def on_refresh_button_click(self, widget):
# I DON'T KNOW WHAT TO PUT HERE
def show_gtk(builder):
window_main = builder.get_object('window1')
window_main.show_all()
Gtk.main()
Не думаю, что вам нужен XML-файл Glade, но я не уверен, потому что я новичок в этом:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<signal name="destroy" handler="on_window1_destroy" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox" id="box_main">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox" id="box_charts">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow" id="chart_past">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="min_content_width">500</property>
<property name="min_content_height">500</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="chart_future">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="min_content_width">500</property>
<property name="min_content_height">500</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="refresh_button">
<property name="label" translatable="yes">refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="button-press-event" handler="on_refresh_button_click" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>