编程语言
首页 > 编程语言> > java – 在某些情况下不会显示Swing应用程序

java – 在某些情况下不会显示Swing应用程序

作者:互联网

我正在编写一个实用程序来帮助测试更大的系统,如果我在系统中运行它,我的UI根本就不显示.我自己运行时工作正常.更多细节:

>我正在测试的系统有许多进程,由控制器管理.部署后,controller.exe会生成并终止子进程,包括我的java应用程序.当由控制器启动时,我的应用程序运行良好(工作,生成日志等)但Swing UI根本不渲染.
>我可以从命令行自己启动我的应用程序,UI显示就好了.根据Process Explorer,Path,Command Line和Current Directory都与从控制器启动应用程序时观察到的值相同.
>当应用程序无法访问时,单击Process Explorer中的“Bring to Front”会弹出一个对话框. “这个过程找不到可见的窗户.”单击手动生成的进程上的相同按钮可将Swing UI按预期方式显示在前面.
>我在Windows XP中测试它.控制器进程在SYSTEM下运行.我使用“at 09:45 /interactive cmd.exe” trick为我的手动启动生成一个命令提示符作为SYSTEM. Process Explorer验证两个方法(手动/控制器)将java进程生成为SYSTEM.
>这两个过程之间唯一明显的区别是父母.系统进程作为controller.exe的子进程生成,而我的手动执行是cmd.exe的子进程.
>我使用jdwp远程调试到隐形进程,一切看起来都很正常. UI代码执行,不会抛出异常,我的JLists甚至会填充他们监视的数据.据我所知,一切正常;我只是看不到任何一个.

如果在其他地方已经回答,我道歉.我尽力搜索,但我能找到的所有问题都是关于某些组件无法渲染,而不是整个应用程序无法显示.

谢谢!

编辑:
根据反馈,我换了一个尽可能小的演示程序.这是整个代码:

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class AceProbe
{
  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run()
      {
        JFrame frame = new JFrame("Visible?");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(new JLabel("Test"), BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
      }
    });
  }
}

从命令行运行它会按预期显示窗口.但是,当控制器生成进程时,不会显示任何内容.当由控制器生成时,我可以使用-agentlib远程调试进程:jdwp = transport = dt_socket,suspend = y,server = y,address = 8000并验证所有线程是否按预期生成,并且没有异常被扔了.

我的直觉来自于控制器处于一些奇怪的图形配置中,并且由于父进程是新的java进程,也许Swing没有使用正确的GraphicsDevice?我尝试添加此代码:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
for(GraphicsDevice d : ge.getScreenDevices())
{
  Log.println(d);
  for (GraphicsConfiguration c : d.getConfigurations())
  {
    Log.println(c);
    Log.println(c.getBounds());
  }
}

日志包含:

Win32GraphicsDevice[screen=0]
sun.awt.Win32GraphicsConfig@13f459d[dev=Win32GraphicsDevice[screen=0],pixfmt=0]
java.awt.Rectangle[x=0,y=0,width=1920,height=1080]

这似乎表明只有一个设备有一个配置,所以我有点不知所措.

解决方法:

你有一个Concurency in Swing问题.Swing是单线程的,所有输出到Swing GUI必须在EDT上完成.

>基本上你可以通过在invokeLater或invokeAndWait中将输出包装到GUI来解决这个问题
>正确的方法是从SwingWorker或Runnable #Thread调用后台任务(在Runnable中,输出必须包装到invokeLater或invokeAndWait中)

编辑

import java.awt.*;
import java.util.*;
import javax.swing.*;

public class SSCCE extends JFrame {

    private static final long serialVersionUID = 1L;

    public SSCCE() {
        super("SSCCE");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setContentPane(createContent());
        pack();
        centerFrameOnMonitor(0);
        setVisible(true);
    }

    private JComponent createContent() {
        JPanel ret = new JPanel();
        JButton button = new JButton("I have a tooltip");
        button.setToolTipText("I wonder where this tooltip is going to popup!");
        ret.add(button);
        return ret;
    }

    /**
     * Centers this frame in the middle of the monitor with the monitorIndex specified. This method assumes that all monitors are laid out
     * horizontally. The 0th index monitor would be the one furthest left.
     * @param monitorIndex
     */
    private void centerFrameOnMonitor(int monitorIndex) {
        GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] devices = e.getScreenDevices();
        if (monitorIndex < 0 || monitorIndex >= devices.length) {
            throw new RuntimeException("Monitor Index out of bounds: " + monitorIndex);
        }
        Arrays.sort(devices, new Comparator<GraphicsDevice>() {

            @Override
            public int compare(GraphicsDevice a, GraphicsDevice b) {
                return (int) (a.getDefaultConfiguration().getBounds().getX() - b.getDefaultConfiguration().getBounds().getX());
            }
        });
        GraphicsConfiguration gc = devices[monitorIndex].getDefaultConfiguration();
        Rectangle gcBounds = gc.getBounds();
        Point p = new Point((int) (gcBounds.getX() + (gcBounds.getWidth() / 2 - this.getWidth() / 2)), (int) (gcBounds.getY() + (gcBounds.getHeight() / 2 - this.getHeight() / 2)));
        this.setLocation(p);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                SSCCE sSCCE = new SSCCE();
            }
        });
    }
} 

EDIT2:

功能测试返回

来自HP Elite,WinXp,Java6,低调GPU

标签:java,swing,windows-xp
来源: https://codeday.me/bug/20190729/1574309.html