在Java Swing中创建X窗口(X11)并获取其ID

3

有人能帮我使用Eclipse在Java Swing中创建X11窗口吗?还需要获取x11 id的函数。在Java中创建X11窗口的基本要求是什么。

5个回答

3

Tom回答了你问题的第一部分。答案的第二部分是:要获取X11窗口的id,您需要使用本地代码(用C或C++编写的代码)并通过JNI接口访问它。

您可能需要通过标题在所有现有窗口中运行搜索以获取所需的窗口。

这是一个递归函数,将从根窗口开始搜索具有所需名称的窗口。

Window windowWithName(Display *dpy, Window top, char *name)
{
    Window *children, dummy;
    unsigned int nchildren;
    unsigned int i;
    Window w = 0;
    char *window_name;

    if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
        return (top);

    if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
        return (0);

    for (i = 0; i < nchildren; i++)
    {
        w = windowWithName(dpy, children[i], name);
        if (w)
            break;
    }
    if (children)
        XFree((char *) children);
    return (w);
}

注意:不幸的是,在X11实现的XFetchName函数中存在一个被广泛记录的内存泄漏问题,这个问题从未得到解决。如果你运行valgrind并发现有轻微的内存泄漏问题,那么就是这个函数导致的。

不,Java不实现这个功能。请记住,在Java中一旦获得了XWindow ID,您将无法对其执行任何操作,只能像Java中的普通整数一样进行操作。这意味着,如果您要对窗口ID执行某些操作,最有可能是需要再次在本地代码中完成。 - ldog
非常感谢您提供的信息,但我计划调用一个可执行的C程序,并传递窗口ID以显示视频流。希望这样可以实现。 - Raji

2
只是为了扩展 @Zubzub 和 @ArtemGr 给出的答案,以下极简的 AWT 示例对我有效,至少在 Sun 的 Java 1.8 中有效:
import java.awt.Dimension;

import javax.swing.JFrame;

import sun.awt.X11.XWindow;

class C {
    public static void main(final String args[]) {
        final JFrame frame = new JFrame();
        frame.setPreferredSize(new Dimension(200, 200));
        frame.pack();
        frame.setVisible(true);
        final XWindow xWindow = (XWindow) frame.getPeer();
        frame.setTitle("Window id: 0x" + Long.toHexString(xWindow.getWindow()));
    }
}

一旦窗口可见,您可以使用 xwininfo 工具验证其 id。
但请注意,即使您的 AWT 应用程序仅在 X11 下运行,上述解决方案也不是可移植的:
  • GCJ 将使用 gnu.java.awt.peer.gtk.GtkFramePeer,而
  • 较早的 Sun JDK 版本(1.4 及以下版本)将使用 sun.awt.motif.MFramePeer。尽管从 1.5 开始 XToolkit 是默认值,在 1.5 和 1.6 上仍然可以重新启用旧的MToolkit,以及
  • 我不确定关于 IBM J9BEA JRockitOraclelwAWTApache Harmony

2

在Swing中创建一个X11窗口就像使用new Frame(),然后跟着setVisible(true)一样容易。获取任何未抽象化的细节将会更加困难。当然,您可以始终打开到端口6000左右的java.net.Socket并自己运行X11。


你的意思是框架和X11窗口是一样的吗? - Raji
不同的是,创建一个AWT框架至少会创建一个X11窗口。我已经很多年没有看过X11了。如果我没记错的话,X11将为每个重量级组件创建一个“窗口”。 - Tom Hawtin - tackline
Java Swing中的JFrame也是一个重量级组件,因此希望它也能创建一个X窗口。 - Raji

1

如果您正在使用Sun JVM并且不介意使用反射和“setAccessible(true)”覆盖包访问权限,则可以使用Sun的工具包创建X11窗口。 https://www.docjar.com/docs/api/sun/awt/X11/XWindow.html

但是,并非所有工具包方法都可能存在:我怀疑未在工具包本身中使用的方法已被删除。例如,大多数XlibUtil并不存在其中。 以下是一个示例,展示如何使用Scala反射来访问工具包方法:http://gist.github.com/567076

您还可以使用JNA在Java中编写xlib部分的代码;请参见问题:Using Xlib via JNA to move a window


1

对于那些仍在寻找的人:

您需要找到程序最顶层的组件,并获取该组件的 'componentpeer'。在Linux下,它将是扩展XWindow的XComponent peer类型,XWindow又扩展自XBaseWindow。XBaseWindow具有类型为long的属性窗口。这就是您要找的。您可能需要使用反射来获取它。

hf


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接