Gtk3-Python-Glade-不同窗口上的“链接”组合框

时间:2018-11-10 00:03:52

标签: python combobox gtk3

在主窗口中我有两个Gtk.Comboboxes

  • 第一个有自己的Gtk.Liststore
  • 第二个链接到Gtk.TreeModelFilter,第二个Gtk.Liststore链接到

当我在第一个中选择一个值时,第二个将根据我的选择显示值。这在主窗口中效果很好。

但是在我的应用程序中,我需要多次使用此组合框组合,并且当我在另一个窗口中使用它时,这会生成我不理解的Gtk错误:

  

“ Gtk-CRITICAL **:00:27:38.289:   gtk_tree_model_filter_set_visible_func:断言   'filter-> priv-> visible_method_set == FALSE'失败”

有人可以向我解释我的代码有什么问题,以及该错误消息的含义是什么

这是林间空地文件(test.ui)

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkListStore" id="liststore1">
    <columns>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name name -->
      <column type="gchararray"/>
    </columns>
    <data>
      <row>
        <col id="0" translatable="yes">1</col>
        <col id="1" translatable="yes">fruits</col>
      </row>
      <row>
        <col id="0" translatable="yes">2</col>
        <col id="1" translatable="yes">colors</col>
      </row>
    </data>
  </object>
  <object class="GtkListStore" id="liststore2">
    <columns>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name name -->
      <column type="gchararray"/>
    </columns>
    <data>
      <row>
        <col id="0" translatable="yes">10</col>
        <col id="1" translatable="yes">lemon</col>
      </row>
      <row>
        <col id="0" translatable="yes">11</col>
        <col id="1" translatable="yes">apple</col>
      </row>
      <row>
        <col id="0" translatable="yes">12</col>
        <col id="1" translatable="yes">strawberry</col>
      </row>
      <row>
        <col id="0" translatable="yes">20</col>
        <col id="1" translatable="yes">blue</col>
      </row>
      <row>
        <col id="0" translatable="yes">21</col>
        <col id="1" translatable="yes">yellow</col>
      </row>
      <row>
        <col id="0" translatable="yes">22</col>
        <col id="1" translatable="yes">purple</col>
      </row>
    </data>
  </object>
  <object class="GtkTreeModelFilter" id="filter">
    <property name="child_model">liststore2</property>
  </object>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <signal name="destroy" handler="on_quit" swapped="no"/>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">20</property>
        <child>
          <object class="GtkToolbar">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkToolButton">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Open other</property>
                <property name="use_underline">True</property>
                <signal name="clicked" handler="on_other" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkGrid">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="margin_left">20</property>
            <property name="margin_right">20</property>
            <property name="row_spacing">5</property>
            <property name="column_spacing">10</property>
            <property name="column_homogeneous">True</property>
            <child>
              <object class="GtkComboBox" id="w1_combo1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="model">liststore1</property>
                <property name="active">0</property>
                <property name="id_column">0</property>
                <property name="active_id">0</property>
                <child>
                  <object class="GtkCellRendererText"/>
                  <attributes>
                    <attribute name="text">1</attribute>
                  </attributes>
                </child>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkComboBox" id="w1_combo2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="model">filter</property>
                <property name="active">0</property>
                <property name="id_column">0</property>
                <property name="active_id">0</property>
                <child>
                  <object class="GtkCellRendererText"/>
                  <attributes>
                    <attribute name="text">1</attribute>
                  </attributes>
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Combo1</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Combo2</property>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
  <object class="GtkDialog" id="window2">
    <property name="can_focus">False</property>
    <property name="type_hint">dialog</property>
    <property name="transient_for">window1</property>
    <child>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">2</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can_focus">False</property>
            <property name="layout_style">end</property>
            <child>
              <object class="GtkButton" id="btn_close">
                <property name="label" translatable="yes">Close</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="valign">center</property>
            <property name="margin_left">20</property>
            <property name="margin_right">20</property>
            <property name="margin_top">20</property>
            <property name="margin_bottom">20</property>
            <property name="vexpand">True</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkGrid">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="valign">center</property>
                <property name="margin_top">20</property>
                <property name="margin_bottom">20</property>
                <property name="vexpand">True</property>
                <property name="row_spacing">5</property>
                <property name="column_spacing">10</property>
                <property name="column_homogeneous">True</property>
                <child>
                  <object class="GtkComboBox" id="w2_combo1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="model">liststore1</property>
                    <property name="active">0</property>
                    <property name="id_column">0</property>
                    <property name="active_id">0</property>
                    <child>
                      <object class="GtkCellRendererText"/>
                      <attributes>
                        <attribute name="text">1</attribute>
                      </attributes>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkComboBox" id="w2_combo2">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="model">filter</property>
                    <property name="active">0</property>
                    <property name="id_column">0</property>
                    <property name="active_id">0</property>
                    <child>
                      <object class="GtkCellRendererText"/>
                      <attributes>
                        <attribute name="text">1</attribute>
                      </attributes>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="top_attach">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Combo1</property>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Combo2</property>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <action-widgets>
      <action-widget response="-7">btn_close</action-widget>
    </action-widgets>
  </object>
</interface>

和python文件(test.py):

#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- 

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import sys

class Main:
    def __init__(self):

        self.builder = Gtk.Builder()
        self.builder.add_from_file('test.ui')
        self.builder.connect_signals(self)
        self.obj = self.builder.get_object

        self.window = self.obj('window1')
        self.combo1 = self.obj('w1_combo1')
        self.combo2 = self.obj('w1_combo2')
        self.combo1.connect('changed', self.on_select, self.combo2)
        self.filter = self.obj('filter')
        self.filter.set_visible_func(self.filter_func)

        self.combo1_val = None

        self.window.show()

    def on_other(self, btn):
        Other(self.obj)

    def on_select(self, combo, next_combo):
        self.combo1_val = combo.get_active_id()
        self.filter.refilter()
        next_combo.set_active(0)

    def filter_func(self, model, iter, data):
        if self.combo1_val is None: return True
        else: return self.combo1_val == model[iter][0][:1]

    def on_quit(self, widget):
        Gtk.main_quit()

class Other:
    def __init__(self, obj):

        self.obj = obj
        self.window = self.obj('window2')

        self.combo1 = self.obj('w2_combo1')
        self.combo2 = self.obj('w2_combo2')
        self.combo1.connect('changed', self.on_select, self.combo2)
        self.filter = self.obj('filter')
        self.filter.set_visible_func(self.filter_func)
        self.btn_close = self.obj('btn_close')
        self.btn_close.connect('clicked', self.on_hide)

        self.combo1_val = None

        self.window.show()

    def on_select(self, combo, next_combo):
        self.combo1_val = combo.get_active_id()
        self.filter.refilter()
        next_combo.set_active(0)

    def filter_func(self, model, iter, data):
        if self.combo1_val is None: return True
        else: return self.combo1_val == model[iter][0][:1]

        self.window.show()

    def on_hide(self, btn):
        self.window.hide()



def main():
    app = Main()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())

谢谢。

1 个答案:

答案 0 :(得分:0)

问题是由于以下事实:主窗口上的第二个组合框和“其他”窗口上的第二个组合框正在使用相同的过滤器。 我创建了另一个过滤器,第二个组合框现在有自己的过滤器,这些过滤器链接到一个通用的Gtk.Liststore。

现在一切正常。

以下是更正的文件:

一个空地:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkListStore" id="liststore1">
    <columns>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name name -->
      <column type="gchararray"/>
    </columns>
    <data>
      <row>
        <col id="0" translatable="yes">1</col>
        <col id="1" translatable="yes">fruits</col>
      </row>
      <row>
        <col id="0" translatable="yes">2</col>
        <col id="1" translatable="yes">colors</col>
      </row>
    </data>
  </object>
  <object class="GtkListStore" id="liststore2">
    <columns>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name name -->
      <column type="gchararray"/>
    </columns>
    <data>
      <row>
        <col id="0" translatable="yes">10</col>
        <col id="1" translatable="yes">lemon</col>
      </row>
      <row>
        <col id="0" translatable="yes">11</col>
        <col id="1" translatable="yes">apple</col>
      </row>
      <row>
        <col id="0" translatable="yes">12</col>
        <col id="1" translatable="yes">strawberry</col>
      </row>
      <row>
        <col id="0" translatable="yes">20</col>
        <col id="1" translatable="yes">blue</col>
      </row>
      <row>
        <col id="0" translatable="yes">21</col>
        <col id="1" translatable="yes">yellow</col>
      </row>
      <row>
        <col id="0" translatable="yes">22</col>
        <col id="1" translatable="yes">purple</col>
      </row>
    </data>
  </object>
  <object class="GtkTreeModelFilter" id="w1_filter">
    <property name="child_model">liststore2</property>
  </object>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <signal name="destroy" handler="on_quit" swapped="no"/>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">20</property>
        <child>
          <object class="GtkToolbar">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkToolButton">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Open other</property>
                <property name="use_underline">True</property>
                <signal name="clicked" handler="on_other" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkGrid">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="margin_left">20</property>
            <property name="margin_right">20</property>
            <property name="row_spacing">5</property>
            <property name="column_spacing">10</property>
            <property name="column_homogeneous">True</property>
            <child>
              <object class="GtkComboBox" id="w1_combo1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="model">liststore1</property>
                <property name="active">0</property>
                <property name="id_column">0</property>
                <property name="active_id">0</property>
                <child>
                  <object class="GtkCellRendererText"/>
                  <attributes>
                    <attribute name="text">1</attribute>
                  </attributes>
                </child>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkComboBox" id="w1_combo2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="model">w1_filter</property>
                <property name="active">0</property>
                <property name="id_column">0</property>
                <property name="active_id">0</property>
                <child>
                  <object class="GtkCellRendererText"/>
                  <attributes>
                    <attribute name="text">1</attribute>
                  </attributes>
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Combo1</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Combo2</property>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
  <object class="GtkTreeModelFilter" id="w2_filter">
    <property name="child_model">liststore2</property>
  </object>
  <object class="GtkDialog" id="window2">
    <property name="can_focus">False</property>
    <property name="type_hint">dialog</property>
    <property name="transient_for">window1</property>
    <child>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">2</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can_focus">False</property>
            <property name="layout_style">end</property>
            <child>
              <object class="GtkButton" id="btn_close">
                <property name="label" translatable="yes">Close</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="valign">center</property>
            <property name="margin_left">20</property>
            <property name="margin_right">20</property>
            <property name="margin_top">20</property>
            <property name="margin_bottom">20</property>
            <property name="vexpand">True</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkGrid">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="valign">center</property>
                <property name="margin_top">20</property>
                <property name="margin_bottom">20</property>
                <property name="vexpand">True</property>
                <property name="row_spacing">5</property>
                <property name="column_spacing">10</property>
                <property name="column_homogeneous">True</property>
                <child>
                  <object class="GtkComboBox" id="w2_combo1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="model">liststore1</property>
                    <property name="active">0</property>
                    <property name="id_column">0</property>
                    <property name="active_id">0</property>
                    <child>
                      <object class="GtkCellRendererText"/>
                      <attributes>
                        <attribute name="text">1</attribute>
                      </attributes>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkComboBox" id="w2_combo2">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="model">w2_filter</property>
                    <property name="active">0</property>
                    <property name="id_column">0</property>
                    <property name="active_id">0</property>
                    <child>
                      <object class="GtkCellRendererText"/>
                      <attributes>
                        <attribute name="text">1</attribute>
                      </attributes>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="top_attach">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Combo1</property>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Combo2</property>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <action-widgets>
      <action-widget response="-7">btn_close</action-widget>
    </action-widgets>
  </object>
</interface>

还有一个python:

#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- 

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import sys

class Main:
    def __init__(self):

        self.builder = Gtk.Builder()
        self.builder.add_from_file('test.ui')
        self.builder.connect_signals(self)
        self.obj = self.builder.get_object

        self.window = self.obj('window1')
        self.combo1 = self.obj('w1_combo1')
        self.combo2 = self.obj('w1_combo2')
        self.combo1.connect('changed', self.on_select, self.combo2)
        self.filter = self.obj('w1_filter')
        self.filter.set_visible_func(self.filter_func)

        self.combo1_val = None

        self.window.show()

    def on_other(self, btn):
        Other(self.obj)

    def on_select(self, combo, next_combo):
        self.combo1_val = combo.get_active_id()
        self.filter.refilter()
        next_combo.set_active(0)

    def filter_func(self, model, iter, data):
        #print(self.combo1_val, model[iter][0][:1])
        if self.combo1_val is None: return True
        else: return self.combo1_val == model[iter][0][:1]

    def on_quit(self, widget):
        Gtk.main_quit()

class Other:
    def __init__(self, obj):

        self.obj = obj
        self.window = self.obj('window2')

        self.combo1 = self.obj('w2_combo1')
        self.combo2 = self.obj('w2_combo2')
        self.combo1.connect('changed', self.on_select, self.combo2)
        self.filter = self.obj('w2_filter')
        self.filter.set_visible_func(self.filter_func)
        self.btn_close = self.obj('btn_close')
        self.btn_close.connect('clicked', self.on_hide)

        self.combo1_val = None

        self.window.show()

    def on_select(self, combo, next_combo):
        self.combo1_val = combo.get_active_id()
        self.filter.refilter()
        next_combo.set_active(0)

    def filter_func(self, model, iter, data):
        #print(self.combo1_val, model[iter][0][:1])
        if self.combo1_val is None: return True
        else: return self.combo1_val == model[iter][0][:1]

        self.window.show()

    def on_hide(self, btn):
        self.window.hide()



def main():
    app = Main()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())