【问题标题】:How to transition from one window to other in Gtk.Application with Pygobject Gtk+3?如何使用 Pygobject Gtk+3 在 Gtk.Application 中从一个窗口转换到另一个窗口?
【发布时间】:2018-01-02 15:28:43
【问题描述】:

我是 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()

这是第二个窗口blankwin.glade的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. 当切换到另一个窗口时,UI 显示第一个窗口关闭,第二个窗口打开,这对任何用户来说都是完全不可接受的。我认为我没有正确切换到其他窗口。在 Gtk.Application 处事方式中切换窗口的正宗方法是什么?我在网上的任何地方都找不到正确的参考资料。找不到任何示例。

  2. 我也想回到我的第一个窗口,因为这个应用程序将有菜单栏,用户将在完成任务后返回到主窗口。我怎么做?任何示例都会有所帮助。

有些标签不是英文的,请不要介意。在此先感谢。

【问题讨论】:

  • “第一个窗口关闭,第二个窗口打开,这对任何用户来说都是完全不可接受的”——如果你破坏当前窗口并显示另一个窗口,听起来一切都按照你的要求工作。你需要解释你预期会发生什么。
  • 我正在尝试切换到下一个窗口。我想像任何其他普通应用程序一样进入下一个窗口。我的应用程序将有登录窗口,然后是主菜单窗口,我将把菜单栏放在顶部。从那里用户需要使用不同的菜单打开不同的窗口,并在完成任务后返回主菜单。我的代码没有这样做,我找不到任何方法。
  • 您要同时打开第一个窗口和第二个窗口吗?还是一次只有一个窗口?
  • 我一次想要一个窗口。我的问题是我认为我没有使用 Gtk.Application ,因为它打算被使用。必须有正确的方法来改变窗口。我不知道怎么做。没有任何教程显示如何管理多个窗口以及如何在它们之间进行更改。任何资源或示例都会非常有帮助。
  • 这可能会变成一个冗长的对话。为什么你在 Gtk chat 不见我?

标签: python gtk gtk3 pygobject


【解决方案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,所以这个例子有点hacky。希望你能弄清楚你需要什么。我添加了一个过渡,如果你不喜欢,你可以禁用它。

【讨论】:

  • 这就是我想要的,但这不使用 Gtk.Application。我正在考虑将 ApplicationWindow 与 Gtk.Application 一起使用。是否可以使用 Gtk.Application 类来做到这一点?
  • 您是否特别需要 GtkApplication?不要怀疑你或任何东西,只是确保。
  • @RohitS 你需要GtkApplication的哪个功能?
  • 我期待一个中心对象,我可以根据需要添加和删除我的空地文件。我期待 MVC 类型的拱门。我读了这个页面-python-gtk-3-tutorial.readthedocs.io/en/latest/application.html这听起来像 Gtk.Application 是用来做这样的事情的。这就是我想要 Gtk.Application 的原因。
  • @RohitS 如果您正在寻找 MVC 类型的应用程序,GtkApplication 不会为您做任何事情(但会创建更多工作)。请发布一个新问题,详细说明您已经告诉我的内容,链接回到这里,我会尽力帮助您。
猜你喜欢
  • 1970-01-01
  • 2021-05-09
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多