首页 > 解决方案 > GTK+3 大小分配事件不像 GTK+2 那样实时

问题描述

我正在尝试从 GTK+2 迁移到 GTK+3,但发现了一个问题。在 GTK+2 中,当用户主动调整窗口大小时,大小分配事件会实时发生。但是在 GTK+3 中,直到释放鼠标单击才发生调整大小,在拖动时没有大小分配信号,就像在 GTK+2 中一样。是否有任何解决方法,或者 GTK+3 就是这样?我可以看到窗口中的任何内容都没有更新,直到释放鼠标单击拖动,在 GTK+2 中窗口中的东西主动调整。

我需要在窗口主动调整大小时更新小部件,并实时了解所有小部件的大小,以便在大小更改时重新绘制一些小部件,因为在调整大小时需要查看模式。但是在 GTK+3 中,小部件在拖动事件完成之前不会进行任何尺寸更改或更新(将窗口拖动到所需尺寸后释放鼠标按钮)。这对我不起作用,如果没有解决方案,我将被迫坚持使用 GTK+2。

编辑:我被要求提供在 GTK2 中工作的代码,所以这里有一个像 gtk2 中需要的小程序,在调整窗口大小时显示高度和宽度,但在 gtk3 中,高度和宽度仅在之后显示调整窗口大小后释放鼠标按钮。我还可以清楚地看到,在 gtk3 中,窗口的内部区域在释放鼠标按钮之前不会调整大小,因此似乎 gtk3 本身在检测到调整大小完成之前不会调整任何小部件的大小。

int main (int argc, char **argv)
{
  gtk_init(&argc, &argv);
  main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(main_window), "test window");
  g_signal_connect(main_window, "size-allocate", G_CALLBACK(getsize_main_window), NULL);
  gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 600);
  gtk_window_set_position(GTK_WINDOW(main_window), GTK_WIN_POS_CENTER);
  g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_widget_show_all(main_window);
  gtk_main();
  return 0;
}

void getsize_main_window(GtkWidget *widget, GtkAllocation *allocation, void *data)
{
  printf ("main window width = %d, height = %d\n", allocation->width, allocation->height);
}

标签: clinuxgtk

解决方案


我下载、构建并运行了针对两者构建的测试程序gtk+-2.0gtk+-3.0. 我正在使用 Fedora 29 并安装了两者 gtk2gtk3

该程序在两个版本中的行为相似。我得到了类似的事件日志和事件频率。

所以,我无法在这里重现您的问题。

您是否能够在您的系统上验证您的测试程序的“不良”行为gtk3?也就是说,它是否准确地展示了您的问题以及您的完整程序?有没有以前没有提到的其他注意事项?

在我运行这个测试之前,我打算建议可能有一个更好的信号/事件来挂钩。而且, for 的行为gtk2可能是一个副作用(在 中“修复”了gtk3)。我打算尝试不同的活动,看看是否有一个更好的选择

请注意,如果您可以改进示例代码(即直到它与gtk3.


请注意,您的示例程序一开始并没有完全编译。所以,我修复了编译错误。

我在您的日志消息中添加了一些员工时间戳以帮助调试。

这是修改后的程序(as test.c):

#include <stdio.h>
#include <time.h>
#include <gtk/gtk.h>

gpointer main_window;

typedef long long tsc_t;

int last_wid = -99999;
int last_hgt = -99999;
int evt_count = 0;
tsc_t tsczero;
tsc_t tsctlat;

tsc_t
tscget(void)
{
    struct timespec ts;
    tsc_t tsc;

    clock_gettime(CLOCK_MONOTONIC,&ts);

    tsc = ts.tv_sec;
    tsc *= 1000000000;
    tsc += ts.tv_nsec;

    tsc -= tsczero;

    return tsc;
}

double
tscsec(tsc_t tsc)
{
    double sec;

    sec = tsc;
    sec /= 1e9;

    return sec;
}

void
getsize_main_window(GtkWidget *widget, GtkAllocation *geo, void *data)
{
    int chgflg = 0;
    tsc_t tscnow;

    tscnow = tscget();

    if (last_wid != geo->width)
        chgflg = 1;

    if (last_hgt != geo->height)
        chgflg = 1;

    ++evt_count;

    if (chgflg) {
        printf("%.9f getsize_main_window: width=%d%+d height=%d%+d events=%d (ELAPSED: %.9f)\n",
            tscsec(tscnow),
            geo->width, geo->width - last_wid,
            geo->height, geo->height - last_hgt,
            evt_count,
            tscsec(tscnow - tsctlat));
        evt_count = 0;
    }

    if (chgflg) {
        last_wid = geo->width;
        last_hgt = geo->height;
    }

    tsctlat = tscnow;
}

int
main(int argc, char **argv)
{
    char buf[100];

    tsczero = tscget();
    tsctlat = tscget();

    gtk_init(&argc, &argv);

    main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    sprintf(buf,"test window v%d",V);
    gtk_window_set_title(GTK_WINDOW(main_window), buf);

    g_signal_connect(main_window, "size-allocate",
         G_CALLBACK(getsize_main_window), NULL);

    gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 600);
    gtk_window_set_position(GTK_WINDOW(main_window), GTK_WIN_POS_CENTER);

    g_signal_connect(G_OBJECT(main_window), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_show_all(main_window);
    gtk_main();

    return 0;
}

这是我创建的[粗略] Makefile

ifndef V
V := 2
endif

PKG = gtk+-$(V).0
CFLAGS += $(shell pkg-config --cflags $(PKG))
LIBS = $(shell pkg-config --libs $(PKG))

all: test

test.o: test.c
    cc -c $(CFLAGS) "-DV=$(V)" test.c

test: test.o
    cc -o test test.o $(LIBS)

clean:
    rm -f *.o test

推荐阅读