1

Тема: Rust gtk3 Glade помилка при закритті програми

Створюю програму з інтерфейсом gtk3 за допомогою Glade.
Створив кнопку виходу з програми в меню і прив'язав до дії ось так:

let glade_scr = include_str!("MainWindow.glade");
let builder = gtk::Builder::from_string(glade_scr);
let quit_menu_item: gtk::MenuItem = builder.
        object("QuitMenuItem").unwrap();

quit_menu_item.connect_activate(|_|
        {
            gtk::main_quit();
        });

Програма закривається, але видає таку помилку:
Attempted to quit a GTK main loop when none is running.

Я розумію, що воно намагається закрити вже закриту програму,
але не розумію як виправити це.

2

Re: Rust gtk3 Glade помилка при закритті програми

Судячи з цього опису, ще не відкриту. Має бути щось на кшталт

let app = Application::builder()
        .application_id("org.example.HelloWorld")
        .build();
...
application.run(); // <- main_quit зупиняє цю функцію
Подякували: Teg Miles, leofun012

3 Востаннє редагувалося Teg Miles (01.03.2024 21:49:00)

Re: Rust gtk3 Glade помилка при закритті програми

koala написав:

Судячи з цього опису, ще не відкриту. Має бути щось на кшталт

let app = Application::builder()
        .application_id("org.example.HelloWorld")
        .build();
...
application.run(); // <- main_quit зупиняє цю функцію

Так, цю кнопку створено до application.run().
Хіба є різниця до чи після run створювати кнопку?

Я розділив програму на два крейти:
Перший

mod main_window;
use gtk::prelude::*;
use crate::main_window::build_ui;


fn main()
{
    let application = gtk::Application::builder().
        application_id("org.example.Movar").build();

    application.connect_activate(build_ui);
    application.run();
}

І другий:

use gtk::prelude::*;

pub fn build_ui(app: &gtk::Application)
{
    let glade_scr = include_str!("MainWindow.glade");
    let builder = gtk::Builder::from_string(glade_scr);
    let main_window: gtk::Window = builder.object("MainWindow").unwrap();
    let search_history_listbox: gtk::ListBox = builder.object(
        "HistorySearchListBox").unwrap();
    let listboxrow = gtk::ListBoxRow::new();
    let hor_box = gtk::Box::new(gtk::Orientation::Horizontal, 0);
    listboxrow.add(&hor_box);
    let binding = "Слово".to_string();
    let opt_item: Option<&str> = Some(&binding);
    let item_label = gtk::Label::new(opt_item);
    hor_box.pack_start(&item_label, true, true, 0);
    search_history_listbox.add(&listboxrow);

    let quit_menu_item: gtk::MenuItem = builder.
        object("QuitMenuItem").unwrap();

    quit_menu_item.connect_activate(|_|
        {
            gtk::main_quit();
        });

    main_window.set_application(Some(app));
    main_window.show_all();
}

Поки що це вінегрет, бо я ще експериментую з Rust.

4 Востаннє редагувалося koala (01.03.2024 22:38:00)

Re: Rust gtk3 Glade помилка при закритті програми

Я з GTK не працював, але після гуглення гадаю, що вам треба робити

quit_menu_item.connect_click( |_| gtk::main_quit() );

замість connect_activate. Фунція, передана в connect_activate, викликається при створенні об'єкта.

5

Re: Rust gtk3 Glade помилка при закритті програми

let item_label = gtk::Label::new(Some(&"Слово"));

до речі.

6

Re: Rust gtk3 Glade помилка при закритті програми

koala написав:

Я з GTK не працював, але після гуглення гадаю, що вам треба робити

quit_menu_item.connect_click( |_| gtk::main_quit() );

замість connect_activate. Фунція, передана в connect_activate, викликається при створенні об'єкта.

У цього віджета немає функції connect_click, швидше за все, це функція для звичайної кнопки, а не кнопки меню.

7

Re: Rust gtk3 Glade помилка при закритті програми

Цілком можливо - я ж кажу, з GTK не працював. Треба проглянути, які там сигнали є. Може, select.

8

Re: Rust gtk3 Glade помилка при закритті програми

Узагалі, я так розумію, коректно буде закривати вікно, а не викликати глобальний main_quit.

Перепрошую, хочу уточнити: з вашим кодом програма закривається, коли ви обираєте цей пункт з меню? Тобто закривається вона через паніку у main_quit, але це стається через клацання мишкою?

9

Re: Rust gtk3 Glade помилка при закритті програми

https://github.com/gtk-rs/gtk/blob/59c380036f2582ecd259ffc4d84c24ace0512604/src/rt.rs#L137

Подякували: leofun011

10

Re: Rust gtk3 Glade помилка при закритті програми

koala написав:

Узагалі, я так розумію, коректно буде закривати вікно, а не викликати глобальний main_quit.

Перепрошую, хочу уточнити: з вашим кодом програма закривається, коли ви обираєте цей пункт з меню? Тобто закривається вона через паніку у main_quit, але це стається через клацання мишкою?

Програма закривається. Але оскільки я запускаю її через application.run(), то закривати треба через gtk::Application::quit(),
а не gtk::main_quit().
Бо для нього потрібно запускати програму через gtk::main().
Ось так має бути:

quit_menu_item.connect_activate(|_|
        {
            //gtk::main_quit();
            gtk::Application::quit(app);
        });

Але виникає інша проблема:
pub fn build_ui(app: &gtk::Application)
   |                   ---  - let's call the lifetime of this reference `'1`
   |                   |
   |                   `app` is a reference that is only valid in the function body
...
22 | /     quit_menu_item.connect_activate(|_|
23 | |         {
24 | |             //gtk::main_quit();
25 | |             gtk::Application::quit(app);
26 | |         });
   | |          ^
   | |          |
   | |__________`app` escapes the function body here
   |            argument requires that `'1` must outlive `'static`

Життєвий цикл змінної закінчується перед внутрішньою анонімною функцією.
Не розумію як виправити. move перед |_| не допомагає.

11

Re: Rust gtk3 Glade помилка при закритті програми

І він правий. app, що передається до build_ui - це посилання на той application, що його проголошено в main. І ніхто не гарантує, що на момент виклику замикання він ще існуватиме. Але саме для цього ніби й придумали сигнали:

app.connect(&"quit", true, |app|gtk::Application::quit(app) ); //тепер app буде себе закривати, отримавши сигнал quit
quit_menu_item.connect_activate(|menu_item|menu_item.emit_by_name(&"quit", &[])); //а меню буде цей сигнал надсилати

Взагалі правильніше, як я розумію, було б за id, але то вже самі колупайтеся.

12 Востаннє редагувалося Teg Miles (02.03.2024 10:48:45)

Re: Rust gtk3 Glade помилка при закритті програми

koala написав:

І він правий. app, що передається до build_ui - це посилання на той application, що його проголошено в main. І ніхто не гарантує, що на момент виклику замикання він ще існуватиме. Але саме для цього ніби й придумали сигнали:

app.connect(&"quit", true, |app|gtk::Application::quit(app) ); //тепер app буде себе закривати, отримавши сигнал quit
quit_menu_item.connect_activate(|menu_item|menu_item.emit_by_name(&"quit", &[])); //а меню буде цей сигнал надсилати

Взагалі правильніше, як я розумію, було б за id, але то вже самі колупайтеся.

Не працює, ось помилка:

25  |                 |app| gtk::Application::quit(app));
    |                       ---------------------- ^^^ expected `&Application`, found `&[Value]`
    |                       |
    |                       arguments to this function are incorrect
    |
    = note: expected reference `&gtk::Application`
               found reference `&[gtk::glib::Value]`

Але я знайшов більш стисле й ефективне рішення:

quit_menu_item.connect_activate(clone!(@weak main_window => move|_|
        {
            main_window.close()
        }));

clone! це з glib.

13

Re: Rust gtk3 Glade помилка при закритті програми

Гм. Тобто фактично ви клонуєте main_window. А об'єкти, схоже, зберігають щось на кшталт Rc на реальні вікна. Ну тоді так і треба.