gi.repository.GLib.Ошибка: gtk-builder-ошибка-quark: нет функции с именем `btnProcess_clicked_cb`. (14)

#python #gtk #gnome #glade #pygobject

#python #gtk #gnome #поляна #pygobject

Вопрос:

У меня есть .glade файл, написанный в версии glade 3.38 и PyGObject 3.38. Сейчас я на Ubuntu 21.10 с PyGObject 3.40. Итак, я преобразовал свою поляну из gtk3 в gtk4 с gtk4-builder-tool помощью, но я получил ошибку gi.repository.GLib.Error: gtk-builder-error-quark: No function named btnProcess_clicked_cb. (14)

Файл поляны

 <?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk" version="4.0"/>
  <object class="GtkWindow" id="graywindow">
    <signal name="destroy" handler="graywindow_destroy_cb" swapped="no"/>
    <property name="child">
      <object class="GtkBox">
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel">
            <property name="label" translatable="yes">1811
Jq
IC</property>
            <property name="width-chars">0</property>
            <attributes>
              <attribute name="font-desc" value="Sans Bold 14"></attribute>
              <attribute name="style" value="normal"></attribute>
            </attributes>
          </object>
        </child>
        <child>
          <object class="GtkBox">
            <property name="homogeneous">1</property>
            <child>
              <object class="GtkLabel">
                <property name="label" translatable="yes">Image Ori</property>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkBox">
            <property name="homogeneous">1</property>
            <child>
              <object class="GtkImage" id="imgOri">
                <property name="icon-name">image</property>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkBox">
            <property name="homogeneous">1</property>
            <child>
              <object class="GtkLabel">
                <property name="label" translatable="yes">Prewitt</property>
              </object>
            </child>
            <child>
              <object class="GtkLabel">
                <property name="label" translatable="yes">Global Threshold
</property>
              </object>
            </child>
            <child>
              <object class="GtkLabel">
                <property name="label" translatable="yes">Otsu</property>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkBox">
            <property name="homogeneous">1</property>
            <child>
              <object class="GtkImage" id="imgGray">
                <property name="icon-name">image</property>
              </object>
            </child>
            <child>
              <object class="GtkImage" id="imgGT">
                <property name="icon-name">image</property>
              </object>
            </child>
            <child>
              <object class="GtkImage" id="imgO">
                <property name="icon-name">image</property>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkBox">
            <property name="homogeneous">1</property>
            <child>
              <object class="GtkButton" id="btnProcess">
                <property name="label" translatable="yes">Process</property>
                <property name="focusable">1</property>
                <property name="receives-default">1</property>
                <signal name="clicked" handler="btnProcess_clicked_cb" swapped="no"/>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkBox">
            <property name="homogeneous">1</property>
            <child>
              <object class="GtkEntry">
                <property name="focusable">1</property>
              </object>
            </child>
            <child>
              <object class="GtkButton" id="btnBrowse">
                <property name="label" translatable="yes">browse</property>
                <property name="focusable">1</property>
                <property name="receives-default">1</property>
                <signal name="clicked" handler="btnBrowse_clicked_cb" swapped="no"/>
              </object>
            </child>
          </object>
        </child>
      </object>
    </property>
  </object>
</interface>
 

Файл Python

 from gi.repository import Gtk
import numpy as np
import cv2
import gi
from matplotlib import pyplot as plt
import sys

gi.require_version('Gtk', '4.0')


class grayProcess:
    def graywindow_destroy_cb(self, object, data=None):
        Gtk.main_quit()

    def btnBrowse_clicked_cb(self, object, data=None):
        self.dialog = Gtk.FileChooserDialog(
            'Please Choose a File',
            None,
            Gtk.FileChooserAction.OPEN,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        self.response = self.dialog.run()

        global url
        if self.response == Gtk.ResponseType.OK:
            self.search = self.builder.get_object('txtSearch')
            imgOri = self.builder.get_object('imgOri')
            url = self.dialog.get_filename()
            self.search.set_text(str(url))
            imgOri.set_from_file(url)

        elif self.response == Gtk.ResponseType.cancel:
            print('Cancel Clicked')

        self.dialog.destroy()

    def btnProcess_clicked_cb(self, object, data=None):
        self.img = cv2.imread(url)
        imgGrey = self.builder.get_object('imgGray')


# Prewitt Start
        self.gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
        img_gaussian = cv2.GaussianBlur(self.gray, (3, 3), 0)

        kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
        kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
        img_prewittx = cv2.filter2D(img_gaussian, -1, kernelx)
        img_prewitty = cv2.filter2D(img_gaussian, -1, kernely)

        cv2.imwrite('image/prewitt.jpg', img_prewittx   img_prewitty)
        imgGrey.set_from_file('image/prewitt.jpg')

# Prewitt End

# Global Threshold Start
        self.img = cv2.imread(url, 0)
        imgGt = self.builder.get_object('imgGT')
        dimensao = self.img.shape
        img = cv2.medianBlur(self.img, 5)

        ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
        value = cv2.countNonZero(th1)
        titles = ['Original Image', 'Global Thresholding (v = 127)']
        images = [img, th1]

        for i in range(len(images)):
            plt.subplot(2, 2, i 1), plt.imshow(images[i], 'gray')
            plt.title(titles[i])
            plt.xticks([]), plt.yticks([])

            cv2.imwrite('image/Global Threshold.jpg', th1)
            imgGt.set_from_file('image/Global Threshold.jpg')
# Global Threshold End

# Start Otsu
        self.img = cv2.imread(url, 0)
        imgo = self.builder.get_object('imgO')
        ret, thresh2 = cv2.threshold(self.img, 127, 255, cv2.THRESH_BINARY_INV)

        titles = ['Original Image', 'BINARY',
                  'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
        images = [self.img, thresh2]

        for i in range(0, 6):
            plt.subplot(2, 3, i 1), plt.imshow(images[i], 'gray')
            plt.title(titles[i])
            plt.xticks([]), plt.yticks([])

            cv2.imwrite('image/otsu.jpg', thresh2)
            imgo.set_from_file('image/otsu.jpg')

# Otsu End

    def __init__(self):
        self.gladefile = ('uts_cv.glade')
        self.builder = Gtk.Builder()
        self.builder.add_from_file(self.gladefile)
        self.builder.connect_signals(self)
        self.window = self.builder.get_object('graywindow')

        self.window.show()


if __name__ == '__main__':
    main = grayProcess()
    Gtk.main()
 

Ответ №1:

Согласно документам gtk4, https://docs.gtk.org/gtk4/migrating-3to4.html#adapt-to-gtkbuilder-api-changes

gtk_builder_connect_signals() больше не существует. Вместо этого сигналы всегда подключаются автоматически. Если вам нужно добавить пользовательские данные в ваши сигналы, gtk_builder_set_current_object() необходимо вызвать. Важным предостережением является то, что вы должны сделать это перед загрузкой любого XML. Это означает, что если вам нужно использовать gtk_builder_set_current_object() , вы больше не можете использовать gtk_builder_new_from_file() , gtk_builder_new_from_resource() , или gtk_builder_new_from_string() . Вместо этого вы должны использовать vanilla gtk_builder_new() , затем вызвать gtk_builder_set_current_object() , а затем загрузить XML с помощью gtk_builder_add_from_file() , gtk_builder_add_from_resource() , или gtk_builder_add_from_string() . Вы должны проверить возвращаемое значение на наличие сбоя и вручную прервать g_error() его, если что-то пошло не так.

Самый простой способ использовать сигналы сейчас, imo Gtk.Template , вы можете посмотреть документацию здесь, https://pygobject.readthedocs.io/en/latest/guide/gtk_template.html