จะเปลี่ยนจากหน้าต่างหนึ่งไปอีกหน้าต่างหนึ่งใน 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()

นี่คือไฟล์ Glade 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. เมื่อสลับไปยังหน้าต่างอื่น UI แสดงว่าหน้าต่างแรกปิดและหน้าต่างที่สองเปิดขึ้น ซึ่งผู้ใช้คนใดยอมรับไม่ได้โดยสิ้นเชิง ฉันไม่คิดว่าฉันกำลังเปลี่ยนไปใช้หน้าต่างอื่นอย่างถูกต้อง วิธีที่แท้จริงในการสลับหน้าต่างใน Gtk วิธีการทำสิ่งต่าง ๆ ของแอปพลิเคชันคืออะไร? ฉันไม่พบข้อมูลอ้างอิงที่ถูกต้องทุกที่บนเว็บ ไม่พบตัวอย่างใดๆ

  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