Can you add a GTK4 applicationWindow from a ui file to a GTK4 application?

WBOY
Release: 2024-02-09 19:24:10
forward
642 people have browsed it

您可以将 GTK4 applicationWindow 从 ui 文件添加到 GTK4 应用程序吗?

php editor Zimo is happy to answer a frequently asked question: "Can you add a GTK4 applicationWindow from a ui file to a GTK4 application?" The answer is yes! In GTK4, you can use GtkBuilder to load the UI file and add the applicationWindow widget in it to your GTK application. In this way, you can design and manage the application interface more conveniently and improve development efficiency. However, please note that to successfully load the UI files, you need to ensure that the relevant libraries and tools for GTK4 are installed in your system. Hope this answer helps you!

Question content

I have only been using GTK for a few days and this is a newbie question since my go program requires a GUI. Being a newbie, I took the easiest way I could find to get started using Cambalache to generate a .UI file and then call it in my go application.

I put everything under ApplicationWindow in the .UI file and let it load and work fine with gkt4-builder-tool but in my go app I don't have events in the GUI in the program. Looking at the sample code, I found that I needed to attach the ApplicationWindow to the GTK application instantiated in my go program, and I changed the >ApplicationWindow by just A window and it works just fine since I can add a normal window to the GTK application.

The problem is that I can't find a way to extract the ApplicationWindow from the UI file and then attach it to the application. The only way to attach a window to an application is app.AddWindow() but it only adds GtkWindow, not GtkApplicationWindow and in a strongly typed language like go It’s “no go” (no pun intended).

You can export your GTK application directly into a .UI file along with ApplicationWindow and in theory if you can do this successfully you could extract them both, maybe via this way to connect them, however, I have not successfully exported the GTK application, ApplicationWindow and menu because gkt4-builder-tool keeps getting validation errors (after trying multiple configurations ), so Cambalache doesn't know how to export that combination; or I don't know how to get it to do so; or it's not actually a legal combination in the .UI file.

So my question is, should I give up trying to store the ApplicationWindow in the .UI file and just build the ApplicationWindow widget in code, or is there any other option? Haven't learned it yet?

If it's not really necessary, I could ditch ApplicationWindow and use Windows as another path.

Thank you for your knowledge and experience.

Thanks!

renew:

More clear based on Kripto's comments.

This is the code. This won't run directly because I extracted the relevant snippet in main() from a larger program, and env, log := boot.Initialize() doesn't exist in this snippet, but It is not important to understand the problem.

I know there is only one application window in the GTK GUI. The concept is similar, if not identical, to the Application Window from my old Visual Basic days.

The following is the go code and a condensed version containing the relevant elements in the .UI file:

If I change line 8 in the .UI file:

<object class="GtkApplicationWindow" id="appWin">

Regarding:

<object class="GtkWindow" id="appWin">

Go Code will open the .UI file and it works, but now I don't have the application window.

If I leave line 8 in the .UI file as is, then it still opens the file but the resulting GUI is non-interactive and only when I stop my running Go program It will only turn off running in debug mode in GoLand. This is because to run it I had to make two changes to the go program. :

  1. Change this line:

appWindow := builder.GetObject(appWin).Cast().(*gtk.Window)

to

appWindow := builder.GetObject(appWin).Cast().(*gtk.ApplicationWindow)

  1. Comment out this line:

app.AddWindow(appWindow)

The second one is the problem because now the window is not attached to the application and I'm sure that's why it's non-interactive.

package main

import (
    "os"

    "github.com/diamondburned/gotk4/pkg/gio/v2"
    "github.com/diamondburned/gotk4/pkg/gtk/v4"

    "gitlab.com/trading5124936/core.git/loggers"
)

func main() {
    env, log := boot.Initialize()
    var app *gtk.Application
    app = gtk.NewApplication(`site.TradingAnalyzer`, gio.ApplicationFlagsNone)
    app.ConnectActivate(func() { activate(app, log, env.Paths.GUIFile) })

    if code := app.Run(os.Args); code > 0 {
        os.Exit(code)
    }

}

func activate(app *gtk.Application, log *loggers.Logger, guiPath string) {
    // You can build UIs using Cambalache (https://flathub.org/apps/details/ar.xjuan.Cambalache)

    b, err := os.ReadFile(guiPath)
    if err != nil {
        log.Critical(err)
        return
    }
    uiXML := string(b)

    builder := gtk.NewBuilderFromString(uiXML, len(uiXML))

    // MainWindow and Button are object IDs from the UI file
    appWindow := builder.GetObject(`appWin`).Cast().(*gtk.Window)

    entry := builder.GetObject(`GeneralSetup.Timezone`).Cast().(*gtk.Entry)
    entry.Connect("changed", func() {
        println(`Changed`)
    })

    app.AddWindow(appWindow)
    appWindow.Show()

}
Copy after login

This is the .UI file:

<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.16.0 -->
<interface domain="ta.site">
  <!-- interface-name TradingAnalyzer.ui -->
  <!-- interface-authors Reg Proctor -->
  <requires lib="gtk" version="4.6"/>
  <object class="GtkApplication" id="app"/>
  <object class="GtkApplicationWindow" id="appWin">
    <property name="default-height">925</property>
    <property name="default-width">1200</property>
    <child>
      <object class="GtkPaned">
        <child>
          <object class="GtkFrame">
            <property name="label">Settings</property>
            <child>
              <object class="GtkStackSidebar">
                <property name="halign">start</property>
                <property name="height-request">900</property>
                <property name="stack">pages</property>
                <property name="valign">start</property>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkFrame">
            <child>
              <object class="GtkStack" id="pages">
                <property name="name">Timezone</property>
                <child>
                  <object class="GtkStackPage" id="GeneralSetup">
                    <property name="child">
                      <object class="GtkFlowBox">
                        <property name="margin-bottom">20</property>
                        <property name="margin-end">50</property>
                        <property name="margin-start">50</property>
                        <property name="margin-top">20</property>
                        <property name="name">Timezone</property>
                        <child>
                          <object class="GtkEntry" id="GeneralSetup.Timezone">
                            <property name="activates-default">True</property>
                            <property name="halign">start</property>
                            <property name="height-request">10</property>
                            <property name="input-purpose">alpha</property>
                            <property name="placeholder-text">Timezone</property>
                            <property name="text">America/Phoenix</property>
                            <property name="tooltip-text">Enter your timezone</property>
                            <property name="valign">center</property>
                            <property name="width-request">50</property>
                          </object>
                        </child>
                      </object>
                    </property>
                    <property name="name">General Setup</property>
                    <property name="title">General Setup</property>
                  </object>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>
Copy after login

Update 2

我找到了部分答案。您可以做到这一点,但您需要将 App 添加到 ApplicationWindow 中,而不是相反,因此这是一个不同的功能。这是它的工作方式(它也有点短,因为我了解到有一个从文件加载的函数):

func activate(app *gtk.Application, log *loggers.Logger, guiPath string, appName string) {

    const ext = `.ui`

    guiPath += `/`
    builder := gtk.NewBuilderFromFile(guiPath + appName + ext)
    // builder := gtk.NewBuilderFromFile(guiPath + `Another template File.ui`)

    appWindow := builder.GetObject(`appWin`).Cast().(*gtk.ApplicationWindow)

    entry := builder.GetObject(`GeneralSetup.Timezone`).Cast().(*gtk.Entry)
    entry.Connect("changed", func() {
        println(`Changed`)
    })

    // ***** THE LINE THAT MAKES THE DIFFERENCE ***
    appWindow.SetApplication(app)
    appWindow.Show()

}

Copy after login

我仍然不确定是否存在将应用程序对象导出到这些 .UI 文件之一的情况。

我还没有找到任何人这样做的例子,我倾向于相信这不是你应该做的,但我仍在学习,所以很容易出错。

解决方法

更新 2 提供了此问题的大部分答案。

此外,到目前为止,我认为没有任何理由将应用程序添加到 UI 文件中。无论如何,它往往会抛出错误。

The above is the detailed content of Can you add a GTK4 applicationWindow from a ui file to a GTK4 application?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!