LibGDX图形模块之查询与配置图形界面

配置和查询

libGDX有一个精心设计的API,可让您查询监视器和显示模式,并切换垂直同步(vsync)。 这可以在配置应用程序或运行时完成。

注意:Android和iOS不支持显示模式更改

查询和设置显示器和显示模式(运行时)

在配置时查询监视器和显示模式是平台相关的.以下小节说明了在每个平台上可以对显示器和显示模式做些什么。

LWJGL平台

使用默认的LWJGL 2后端,您可以获得主监视器的可用显示模式,如下所示:

DisplayMode[] modes = LwjglApplicationConfiguration.getDisplayModes();

您可以获得主监视器(也称为桌面模式)的当前显示模式,如下所示:

DisplayMode desktopMode = LwjglApplicationConfiguration.getDesktopDisplayMode();

一旦你有一个DisplayMode,你可以在LwjglApplicationConfiguration上设置它:

DisplayMode displayMode = LwjglApplicationConfiguration.getDesktopDisplayMode();
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.setFromDisplayMode(displayMode);
new LwjglApplication(new MyAppListener(), config);

您的应用程序将以全屏模式启动(使用DisplayMode对象中的分辨率)。
要在窗口模式下启动应用程序,只需指定窗口的宽度和高度:

LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.width = 800;
config.height = 600;
new LwjglApplication(new MyAppListener(), config);

您还可以通过指定相对于监视器当前显示模式的左上角坐标,将窗口放在主监视器特定位置上:

config.x = 100;
config.y = 100;

要使窗口居中,请使用-1作为坐标(默认值)。
最后,您还可以指定应用程序是否应启用vsync(垂直同步):

config.vSyncEnabled = true;

LWJGL 3平台

当涉及显示器和显示模式时,LWJGL 3后端更加精细。 与LWJGL 2后端不同,它支持多显示器设置。
在配置时查询所有可用的显示器的代码如下:

Monitor[] monitors = Lwjgl3ApplicationConfiguration.getMonitors();

要获得主显示器:

Monitor primary = Lwjgl3ApplicationConfiguration.getPrimaryMonitor();

要获取显示器的所有支持的显示模式,请调用:

DisplayMode[] displayModes = Lwjgl3ApplicationConfiguration.getDisplayModes(monitor);

要获取显示器的当前显示模式,请拨打:

DisplayMode desktopMode = Lwjgl3ApplicationConfiguration.getDisplayMode(monitor);

获取主显示器的显示模式也有一些困难:

DisplayMode[] primaryDisplayModes = Lwjgl3ApplicationConfiguration.getDisplayModes();
DisplayMode primaryDesktopMode = Lwjgl3ApplicationConfiguration.getDisplayMode();

当你得到了DisplayMode ,您可以将其设置到Lwjgl3ApplicationConfiguration上:

DisplayMode primaryMode = LWjgl3ApplicationConfiguration.getDisplayMode();
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setFullscreenMode(primaryMode);
new Lwjgl3ApplicationConfiguration(new MyAppListener(), config);

如此,将使得主显示器以设置好的显示模式以全屏的模式启动,如果你使用其他显示器的显示模式启动当前显示器,它也会以当前的显示模式全屏启动,但是可能会失败(因为可能不存在该显示模式).

注意:建议始终使用显示器的当前显示模式,其他显示模式可能会失败。
要在窗口模式下启动应用程序,请在配置中调用此方法:

Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setWindowedMode(800, 600);

这将在主显示器上以窗口模式启动您的应用程序。 如果你要设置窗口的精确位置:

config.setWindowPosition(100, 100);

您还可以指定您的窗口是否应该调整大小,以及是否有装饰(窗口标题栏,边框):

config.setResizable(false);
config.setDecorated(false);

The LWJGL 3 backend also allows you to specify how to deal with HDPI monitors. The operating system may report logical sizes and coordinates instead of pixel-based coordinates to you for drawing surface sizes or mouse events. E.g. on a Macbook Pro with a retina display running Mac OS X, the OS reports only half the width/height of the underlying pixel surface. The LWJGL 3 backend can report drawing surface sizes as returned by Gdx.graphics.getWidth()/getHeight() and mouse coordinates either in those logical coordinates, or in pixel coordinates. To configure this behaviour, set a HDPI mode:

LWJGL 3后端还允许您指定如何处理HDPI监视器,要配置此行为,请设置HDPI模式:

config.setHdpiMode(HdpiMode.Logical);

This will report mouse coordinates and drawing surface sizes in logical coordinates. It is also the default for this backend. If you want to work in raw pixels, use HdpiMode.Pixels. Note that when using logical coordinates, you will have to convert these to pixel coordinates for OpenGL functions like glScissor, glViewport or glReadPixels. All libGDX classes calling these functions will take into account the HdpiMode you set. If you call these functions yourself, use HdpiUtils.

运行时查询和设置显示器和显示模式

LibGDX通过Graphics 接口提供API,可以在运行时查询监视器,显示模式和其他相关方面。 一旦知道可能的配置,你可以设置它们,例如 切换到全屏模式,或切换垂直同步。

检查是否支持显示模式更改

只有一部分平台支持显示模式更改。 值得注意的是,Android和iOS不支持切换到任意全屏显示模式。 更改显示模式之前检查您的应用程序当前正在运行的平台是否支持显示模式更改是一个不错的习惯:

if(Gdx.graphics.supportsDisplayModeChange()) {
   // change display mode if necessary
}

请注意,图形中所有与显示模式有关的功能将不会在不支持显示模式更改的平台上执行任何操作。

查询监视器

要查询所有连接的显示器,请使用以下方法:

Monitor[] monitors = Gdx.graphics.getMonitors();

在Android,iOS,GWT和LWJGL 2后端,只有主显示器才会被返回, LWJGL 3后端返回所有连接的显示器。

如果仅仅查询主监视器,请使用:

Monitor primary = Gdx.graphics.getPrimaryMonitor();

要查询当前窗口所在的显示器,可以调用如下代码:

Monitor currMonitor = Gdx.graphics.getMonitor();

It is good practice to toggle full-screen on the monitor the window is on, instead of say the primary monitor. This allows users to move the application window to another monitor, and then enable full-screen mode there.

查询显示模式

一旦你有了Monitor 实例后,您可以查询其支持的显示模式:

DisplayMode[] modes = Gdx.graphics.getDisplayModes(monitor);

要获取当前显示模式,请使用以下方法:

DisplayMode currMode = Gdx.graphics.getDisplayMode(monitor);

切换到全屏模式

使用来自特定显示器的DisplayMode,您可以切换到全屏,如下所示:

Monitor currMonitor = Gdx.graphics.getMonitor();
DisplayMode displayMode = Gdx.graphics.getDisplayMode(monitor);
if(!Gdx.graphics.setFullscreenMode(displayMode)) {
   // switching to full-screen mode failed
}

如果切换到全屏模式失败,后端将恢复最后一个窗口模式配置。

切换到窗口模式

要更改窗口的大小,或从全屏模式切换到窗口模式,请使用以下方法:

Gdx.graphics.setWindowedMode(800, 600);

将窗口设置为窗口模式,并将其定位在调用此方法之前的显示器上。

多窗口API(LWJGL 3后端)

一些应用程序(如编辑器或其他仅限桌面的工具)可从多窗口设置中受益。 LWJGL 3后端提供了一个额外的非跨平台API来创建多个窗口。

每一个程序都是配置窗口属性开始:

Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setWindowedMode(800, 600);
new Lwjgl3ApplicationConfiguration(new MyMainWindowListener(), config);

在这个例子中,窗口由MyMainWindowListener(一个标准的ApplicationListener)驱动。 libGDX不直接报告图标化或焦点丢失等事件。 为此,LWJGL 3后端引入了一个名为Lwjgl3WindowListener的桌面专用接口。 您可以提供此接口的实现来接收和响应这些事件:

config.setWindowListener(new Lwjgl3WindowListener() {
   @Override
   public void iconified() {
      // the window is not visible anymore, potentially stop background
      // work, mute audio, etc.
   }

   @Override
   public void deiconified() {
      // the window is visible again, start-up background work, unmute
      // audio, etc.
   }
 
   @Override
   public void focusLost() {
      // the window lost focus, pause the game
   }

   @Override
   public void focusGained() {
      // the window received input focus, unpause the game
   }

   @Override
   public boolean windowIsClosing() {
      // if there's unsaved stuff, we may not want to close 
      // the window, but ask the user to save her work
      if(isStuffUnsaved) {
         // tell our app listener to show a save dialog
         return false;
      } else {
         // OK, the window may close
         return true;
      }
});

如果窗口失去焦点,LWJGL 3后端不会报告暂停和恢复事件。 只有在应用程序被 iconfified/deiconified 时才会报告暂停和恢复事件,或者应用程序关闭。

为了产生其他窗口,您的代码需要将Gdx.app转换为Lwjgl3Application。 这只有在您的项目直接依赖于LWJGL 3后端时才可能。 您将无法与其他平台共享此类代码。 一旦你有一个Lwjgl3Application,你可以创建一个这样的新窗口:

Lwjgl3Application lwjgl3App = (Lwjgl3Application)Gdx.app;
Lwjgl3WindowConfiguration windowConfig = new Lwjgl3WindowConfiguration();
windowConfig.setWindowListener(new MyWindowListener());
windowConfig.setTitle("My other window");
Lwjgl3Window window = Lwjgl3App.newWindow(new MyOtherWindowAppListener(), windowConfig);

建议让每个窗口都有自己的ApplicationListener。 一个应用程序的所有窗口在同一个线程上更新,一个接一个。 LWJGL 3后端将确保为当前正在更新的窗口设置静态Gdx.graphics和Gdx.input。 这意味着您的ApplicationListener本质上可以忽略其他窗口,并且假装它是城里唯一的监听器。

这有一个例外。 当使用Gdx.app.postRunnable()时,LWJGL 3后端无法决定Runnable已经发布了哪个窗口。 例如。 该方法可能已经从工作线程被调用,并且在Runnable被发布的时候,当前可以更新不同的窗口。 要解决这个问题,建议将窗口特定的Runnable实例直接发送到窗口:
····java
// e.g. in a worker thread
window.postRunnable(new MyRunnable());
····
这样可以确保在执行Runnable时为特定窗口设置静态Gdx.graphics和Gdx.input。

Lwjgl3Window类有其他方法可以修改Windows属性。 您可以在ApplicationListener中获取当前窗口,然后继续修改它:

// in ApplicationListener#render()
Lwjgl3Window window = ((Lwjgl3Graphics)Gdx.graphics).getWindow();
window.setVisible(false); // hide the window
window.iconifyWindow(); // iconify the window
window.deiconifyWindow(); // deiconify window
window.closeWindow(); // close the window, also disposes the ApplicationListener

//TODO 待续

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,701评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,288评论 25 707
  • 1 前言 一直想沿着图像处理这条线建立一套完整的理论知识体系,同时积累实际应用经验。因此有了从使用AVFounda...
    RichardJieChen阅读 5,677评论 5 12
  • 再有联系是七年以后,一直觉得七年是个很神奇的存在,科学说七年时间身体的细胞就会更新一次,所以,想要忘记一个...
    迷鹿橙子阅读 183评论 0 0
  • 广袤无垠的宇宙世界中,有许许多多的行星。有的无比耀眼,得到了无数人的关注;有的自由自在,随着自己随心所欲;有...
    朝阳中的那抹灿烂阅读 556评论 0 0