Как перейти из одного окна в другое в Gtk.Application с помощью Pygobject Gtk+3?

Я новичок в Gtk и Python. Я использую Python 2.7.14 и Pygobject (pygi-aio-3.24.1_rev1-setup). У меня есть рабочая программа, которая может вызывать другое окно, показывать это окно и закрывать исходное окно. А именно: Это основная программа.

 #!/usr/bin/python
# coding=utf8

from gi.repository import GObject, Gio, Gdk, Gtk
import blnkwin1

class MyApplication(Gtk.Application):
    # Main initialization routine
    def __init__(self, application_id, flags):
        Gtk.Application.__init__(self, application_id=application_id, flags=flags)
        self.connect("activate", self.new_window)

    def new_window(self, *args):
        AppWindow(self)

class AppWindow(object):
    def __init__(self, application):
        self.Application = application

        # Read GUI from file and retrieve objects from Gtk.Builder
        try:
            GtkBuilder = Gtk.Builder.new_from_file("Lgnwin.glade")
            GtkBuilder.connect_signals(blnkwin.lgn(application,GtkBuilder))
        except GObject.GError:
            print("Error reading GUI file")
            raise

        # Fire up the main window
        self.MainWindow = GtkBuilder.get_object("LoginWindow")
        self.MainWindow.set_application(application)
        self.MainWindow.show()
        if GtkBuilder.get_application.get_window_by_id(2):
            GtkBuilder.get_application.get_window_by_id(2).destroy()

    def close(self, *args):
            self.MainWindow.destroy()

# Starter
def main():
    # Initialize GTK Application
    Application = MyApplication("com.b.example", Gio.ApplicationFlags.FLAGS_NONE)

    # Start GUI
    Application.run()

if __name__ == "__main__": main()

Это файл поляны Lgnwin.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkApplicationWindow" id="LoginWindow">
    <property name="width_request">800</property>
    <property name="height_request">600</property>
    <property name="can_focus">False</property>
    <property name="resizable">False</property>
    <property name="icon">icon100.png</property>
    <child>
      <object class="GtkGrid" id="grid1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkBox" id="box1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkLabel" id="label1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="vexpand">True</property>
                <property name="label" translatable="yes">लॉगीन करा</property>
                <attributes>
                  <attribute name="font-desc" value="Mangal 16"/>
                </attributes>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="margin_top">5</property>
                <property name="margin_bottom">5</property>
                <property name="label" translatable="yes">युजरनेम</property>
                <attributes>
                  <attribute name="font-desc" value="&lt;Enter Value&gt; 14"/>
                  <attribute name="foreground" value="#201f4a4a8787"/>
                </attributes>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="uname">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="margin_top">2</property>
                <property name="margin_bottom">2</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label3">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="margin_top">5</property>
                <property name="margin_bottom">5</property>
                <property name="label" translatable="yes">पासवर्ड</property>
                <attributes>
                  <attribute name="font-desc" value="&lt;Enter Value&gt; 14"/>
                  <attribute name="foreground" value="#201f4a4a8787"/>
                </attributes>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">3</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="pswd">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="margin_top">2</property>
                <property name="margin_bottom">2</property>
                <property name="visibility">False</property>
                <property name="invisible_char">●</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">4</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="loginbtn">
                <property name="label" translatable="yes">लॉगीन</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="margin_top">10</property>
                <signal name="clicked" handler="loginbtn_clicked_cb" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">5</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="left_attach">1</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <placeholder/>
        </child>
        <child>
          <placeholder/>
        </child>
        <child>
          <placeholder/>
        </child>
      </object>
    </child>
  </object>
</interface>

Это еще один файл, в котором я обрабатываю нажатие кнопки, а также вызываю следующее окно:

from gi.repository import GObject, Gio, Gdk, Gtk
class lgn(object):
    def __init__(self, application, builder):
        self.Application = application
def loginbtn_clicked_cb(self, button):
    builder = Gtk.Builder.new_from_file("blankwin.glade")
    builder.connect_signals(self)
    self.lgnwins = builder.get_object("applicationwindow1")
    self.lgnwins.set_application(self.Application)

    self.Application.get_window_by_id(2).set_visible(True)
    self.Application.get_window_by_id(1).destroy()

Это файл Glade для второго окна Blankwin.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkApplicationWindow" id="applicationwindow1">
    <property name="can_focus">False</property>
    <property name="default_width">800</property>
    <property name="default_height">600</property>
    <child>
      <object class="GtkLabel" id="label1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="label" translatable="yes">This is Just a blank Window</property>
      </object>
    </child>
  </object>
</interface>

Эта программа работает нормально. Но имеет несколько зародышевых недостатков. Моя проблема:

  1. При переключении на другое окно пользовательский интерфейс показывает, что первое окно закрывается, а второе открывается, что совершенно неприемлемо для любого пользователя. Я не думаю, что правильно переключаюсь на другое окно. Каков подлинный способ переключения окон в Gtk.Application? Я не мог найти правильную ссылку нигде в Интернете. Примеров не нашел.

  2. Я также хочу вернуться к своему первому окну, так как это приложение будет иметь строку меню, и пользователь вернется после выполнения задачи обратно в главное окно. Как я могу это сделать? Любые примеры будут полезны.

Некоторые этикетки не на английском языке, не обращайте на них внимания. Заранее спасибо.


person Rohit S    schedule 02.01.2018    source источник
comment
первое окно закрывается и открывается второе окно, что совершенно неприемлемо для любого пользователя - если вы уничтожите текущее окно и покажете другое, это звучит так, как будто все работает так, как вы просили. Вам нужно объяснить, чего вы ожидаете.   -  person Jussi Kukkonen    schedule 02.01.2018
comment
Я пытаюсь переключиться на следующее окно. Я хочу перейти к следующему окну, как и любое другое обычное приложение. В моем приложении будет окно входа в систему, а затем окно главного меню, в котором я помещу строку меню сверху. оттуда пользователю нужно открывать разные окна с разными меню и возвращаться в главное меню после выполнения задачи. Мой код этого не делает, и я не мог найти способ сделать это.   -  person Rohit S    schedule 03.01.2018
comment
Вы хотите, чтобы и первое, и второе окно открывались одновременно? Или только одно окно за раз?   -  person theGtknerd    schedule 04.01.2018
comment
Я хочу одно окно за раз. Моя проблема в том, что я думаю, что не использую Gtk.Application так, как он предназначен для использования. Должен быть правильный способ смены окон. Я не могу понять, как. Ни в одном из руководств не показано, как управлять несколькими окнами и как переключаться между ними. Любые ресурсы или примеры будут очень полезны.   -  person Rohit S    schedule 05.01.2018
comment
Это может стать продолжительным разговором. Почему вы не видите меня в чате Gtk?   -  person theGtknerd    schedule 06.01.2018


Ответы (1)


Вот файл .py

#!/usr/bin/env python3

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

UI_FILE = "pygtk_stack.ui"


class GUI:
    def __init__(self):

        self.builder = Gtk.Builder()
        self.builder.add_from_file(UI_FILE)
        self.builder.connect_signals(self)

        self.stack = Gtk.Stack()
        self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self.view_one = self.builder.get_object('box1')
        self.view_two = self.builder.get_object('box2')
        self.stack.add_named(self.view_one, "view one" )
        self.stack.add_named(self.view_two, "view two" )
        window = self.builder.get_object('window')
        window.add(self.stack)
        window.show_all()

    def view_two_activated (self, meuitem):
        self.stack.set_visible_child(self.view_two)

    def view_one_clicked (self, button):
        self.stack.set_visible_child(self.view_one)

    def on_window_destroy(self, window):
        Gtk.main_quit()

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

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

И файл pygtk_stack.ui:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkBox" id="box1">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="orientation">vertical</property>
    <child>
      <object class="GtkMenuBar" id="menubar1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkMenuItem" id="menuitem3">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">_View</property>
            <property name="use_underline">True</property>
            <child type="submenu">
              <object class="GtkMenu" id="menu1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkMenuItem" id="menuitem1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">View 2</property>
                    <property name="use_underline">True</property>
                    <signal name="activate" handler="view_two_activated" swapped="no"/>
                  </object>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
    <child>
      <placeholder/>
    </child>
  </object>
  <object class="GtkBox" id="box2">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="orientation">vertical</property>
    <child>
      <object class="GtkButton" id="button1">
        <property name="label" translatable="yes">Go back</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <signal name="clicked" handler="view_one_clicked" swapped="no"/>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel" id="label1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="label" translatable="yes">Second view</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">1</property>
      </packing>
    </child>
  </object>
  <object class="GtkWindow" id="window">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">window</property>
    <property name="default_width">500</property>
    <property name="default_height">400</property>
    <signal name="destroy" handler="on_window_destroy" swapped="no"/>
    <child>
      <placeholder/>
    </child>
  </object>
</interface>

Моя версия Glade не поддерживает GtkStack, поэтому этот пример немного хакерский. Надеюсь, вы сможете понять, что вам нужно. Я добавил переход, который вы можете отключить, если он вам не нравится.

person theGtknerd    schedule 06.01.2018
comment
Вот как я этого хочу, но это не использует Gtk.Application. Я думал об использовании ApplicationWindow с Gtk.Application. Можно ли это сделать с помощью класса Gtk.Application? - person Rohit S; 06.01.2018
comment
Вам конкретно нужно GtkApplication? Не для того, чтобы сомневаться в вас или в чем-то еще, просто убедиться. - person theGtknerd; 06.01.2018
comment
@RohitS Какая функция GtkApplication вам нужна? - person theGtknerd; 06.01.2018
comment
Я ожидал центральный объект, где я мог бы добавлять и удалять файлы поля по мере необходимости. Я ожидал арки типа MVC. Я прочитал эту страницу - python-gtk-3-tutorial.readthedocs .io/en/latest/application.html Похоже, что Gtk.Application создан для таких вещей. Вот почему я хотел Gtk.Application. - person Rohit S; 06.01.2018
comment
@RohitS Если вы хотите иметь приложение типа MVC, GtkApplication ничего для вас не сделает (но создаст дополнительную работу). Пожалуйста, опубликуйте новый вопрос, уточняющий то, что вы уже сказали мне, дайте ссылку здесь, и я постараюсь вам помочь. - person theGtknerd; 06.01.2018
comment
я задал отдельный вопрос. Вот ссылка - stackoverflow.com/questions/48135506/ - person Rohit S; 07.01.2018