【问题标题】:JFrame doesn't appear unless method invoked in main除非在 main 中调用方法,否则 JFrame 不会出现
【发布时间】:2017-03-03 19:24:22
【问题描述】:

我有一个创建带有图像的 JFrame 的类,但每次我创建该类并运行实例化它的方法时,它都不会出现。但是,我注意到如果我要创建完全相同的类并在 main 中运行相同的方法,则会出现框架。

这是我尝试创建的带有 JFrame 的类中的大部分代码:

    JFrame myFrame= new JFrame();
    public void CreateFrame()
    {       
        JLabel background=new JLabel(new ImageIcon("image.jpg"));

        myFrame.add(background);

        background.setLayout(new FlowLayout());
        
        myFrame.setLayout(new GridLayout(1,1));
        myFrame.setSize(360,250);
        myFrame.setUndecorated(true);
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        myFrame.setLocation((dim.width/2-170), dim.height/2-125);
        myFrame.pack();
        myFrame.setVisible(true);
    }

如果我运行代码

MyClass mc = new MyClass();
mc.CreateFrame();

在另一个类的方法中它不会出现。但是,如果我在 main 方法中运行完全相同的代码,它就可以工作。

例如,这不起作用:

示例 1

public class otherClass extends JFrame
{
    public void MethodA()
    {
        MyClass mc = new MyClass();
        mc.CreateFrame();
    }
    
    public static void main(String[] args)
    {
        otherClass oc = new otherClass();
        oc.MethodA();
    }
}

但这确实有效

示例 2

public class otherClass extends JFrame
{
    public void MethodA()
    {
        //CODE
    }
    
    public static void main(String[] args)
    {
        otherClass oc = new otherClass();
        oc.MethodA();
        
        MyClass mc = new MyClass();
        mc.CreateFrame();
    }
}

谁能看出我哪里出错了?抱歉,如果是一个愚蠢的错误,我仍在掌握 Java。 谢谢

编辑

import javax.swing.ImageIcon;
import javax.swing.JWindow;
import javax.swing.JLabel;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.util.Timer;
import java.util.Date;
import javax.swing.JFrame;

public class MyClass
 {
    JFrame homeFrame = new JFrame();
    public void createFrame()
    {       

    JLabel background=new JLabel(new ImageIcon("images.jpg"));

    myFrame.add(background);

    background.setLayout(new FlowLayout());
    
    myFrame.setLayout(new GridLayout(1,1));
    myFrame.setSize(360,250);
    myFrame.setUndecorated(true);
    myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    myFrame.setLocation((dim.width/2-170), dim.height/2-125);
    myFrame.setAlwaysOnTop(true);
    myFrame.pack();
    myFrame.setVisible(true);
    durationOfTime();
}

public void durationOfTime()
{
    MainProgram mp = new MainProgram();
    long startTime = System.currentTimeMillis();
    long elapsedTime = 0L;
    int count =0;
    while (elapsedTime < 2*1000) 
    {
        if(count==0)
        {
            mp.launchInitiation();
        }
        count+=1;
        
        elapsedTime = (new Date()).getTime() - startTime;
    }
    myFrame.setVisible(false);
    mp.homeFrame.setVisible(true);
}

  public static void main(String[] args) 
  {
    MyClass mc = new MyClass();
    mc.createFrame();
  }
}

JFrame 试图制作的类的完整代码。我正在尝试将此 JFrame 用作启动屏幕,但无论我调用什么类

MyClass mc = new MyClass();
mc.createFrame();

从,它只是没有出现。在我的主 GUI 出现之前确实经过了两秒钟,但这个方法应该在登录类型框架中调用。但是,我已经用一个空白的 JFrame / GUI 对其进行了测试,它也会在按钮单击时出现,但它仍然没有出现。

编辑2

我之前也尝试过 @http://examples.oreilly.com/jswing2/code/ch08/SplashScreen.java 的这个 SplashScreen 示例,但我无法让它工作(同样的问题,从 main 调用时出现,但从动作侦听器调用时不出现)

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

public class SplashScreen extends JWindow {
  private int duration;
  public SplashScreen(int d) {
    duration = d;
  }

  // A simple little method to show a title screen in the center
  // of the screen for the amount of time given in the constructor
  public void showSplash() {
    JPanel content = (JPanel)getContentPane();
    content.setBackground(Color.white);

    // Set the window's bounds, centering the window
    int width = 450;
    int height =115;
    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (screen.width-width)/2;
    int y = (screen.height-height)/2;
    setBounds(x,y,width,height);

    // Build the splash screen
    JLabel label = new JLabel(new ImageIcon("oreilly.gif"));
    JLabel copyrt = new JLabel
      ("Copyright 2002, O'Reilly & Associates", JLabel.CENTER);
    copyrt.setFont(new Font("Sans-Serif", Font.BOLD, 12));
    content.add(label, BorderLayout.CENTER);
    content.add(copyrt, BorderLayout.SOUTH);
    Color oraRed = new Color(156, 20, 20,  255);
    content.setBorder(BorderFactory.createLineBorder(oraRed, 10));

    // Display it
    setVisible(true);

    // Wait a little while, maybe while loading resources
    ClassToLoad ctl = new ClassToLoad();
    try {
    Thread.sleep(duration); 
    ctl.initiate();
    } catch (Exception e) {}

    setVisible(false);
  }

  public void showSplashAndExit() {
    showSplash();
    System.exit(0);
  }

  public static void main(String[] args) {
    // Throw a nice little title page up on the screen first
    SplashScreen splash = new SplashScreen(10000);
    // Normally, we'd call splash.showSplash() and get on with the program.
    // But, since this is only a test...
    splash.showSplashAndExit();
  }
}

我在 ClassToLoad 行中添加了代码,并在动作侦听器上调用了这个 SplashScreen,发生的情况是程序等待我告诉它的 2 秒,没有出现任何框架,然后是我想要的主类在启动画面可见时加载。我首先尝试了这种方法,但这没有奏效,这导致我使用此编辑上面列出的代码

编辑 3

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

public class TestFrame extends JFrame implements ActionListener 
{
    JPanel thePanel = new JPanel(null); //layout
    JButton button = new JButton();

 public void startGUI()
 {
    this.setLayout(new GridLayout(1,1));
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    

    CREATEMYPANEL();
    this.add(thePanel);

    this.setTitle("NO_TITLE_SET");
    this.setSize(400,400);
    this.setVisible(true);
    this.setResizable(true);
 }

 public void CREATEMYPANEL()
 {
    button.setLocation(242,151);
    button.setSize(100,50);
    button.addActionListener(this);
    button.setText("button");
    thePanel.add(button);

 }

 public void actionPerformed(ActionEvent e)
 {
    if(e.getSource()==button)
    {
         System.out.println("button has been pressed ");
         SplashScreen splash = new SplashScreen(1000);
         splash.showSplash();
    }
 }
 
 public static void main(String[] args )

 {
    TestFrame tf = new TestFrame();
    tf.startGUI();
 }
}  

我从哪里调用启动画面的示例。还是不行。另外,请注意我正在加载的图像是本地图像

对错误的问题格式表示歉意

【问题讨论】:

  • 如需尽快获得更好的帮助,请发帖minimal reproducible exampleShort, Self Contained, Correct Example
  • @khelwood 我还有其他类,我可以按照我描述的方式从方法中创建其他类/框架;为什么这个例子有什么不同。
  • 我刚刚运行了这段代码,两个例子都有效。无论您遇到什么问题,都不会在您显示的代码中表达出来。
  • 为什么otherClass 扩展JFrame 而你却从不使用它?也请遵循naming conventions 并始终如一地使用它们:firstWordLowerCaseMemberfirstWordLowerCaseMethod()FirstWordUpperCaseClassALL_UPPER_CASE_WORDS_CONSTANTS,以便您和我们更轻松地阅读您的代码
  • 我知道您尝试加载的图像存储在本地,但您没有尝试从 URL 加载它吗?这会告诉我们是否是您的图像未加载,因此您的框架的大小为 0, 0

标签: java swing class user-interface jframe


【解决方案1】:

除了我注意到的一些细节之外,您的代码对我有用:

  1. 您正在调用setSize(...),然后调用pack()。可能您的图像没有被加载,因此您的 JFrame 的大小为 0, 0。(因此看起来它从未出现过)。 .pack().setSize(...) 是互斥的。

  2. 您将JLabel 的布局管理器设置为FlowLayout,但从未向其中添加任何内容。 (您可以安全地删除它)

  3. 如果您想在 2 秒后处理 JFrame,我看到您正在导入 java.util.Timer,那么您应该改用 javax.swing.Timer。否则你可能会遇到与线程相关的问题。

  4. 另外不要忘记将您的程序放在Event Dispatch Thread (EDT),因为 Swing 不是线程安全的

按照上述建议,您可以获得以下代码:

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class SplashscreenSample {
    private JFrame myFrame;
    private JLabel background;
    private Timer timer;

    public void createFrame() {

        timer = new Timer(2000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                myFrame.dispose();
                @SuppressWarnings("serial")
                JFrame frame = new JFrame(getClass().getSimpleName()) {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(200, 200);
                    }
                };
                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                timer.stop();
            }
        });

        myFrame = new JFrame(getClass().getSimpleName());
        try {
            background = new JLabel(new ImageIcon(new URL("http://cdn.bulbagarden.net/upload/thumb/6/6b/175Togepi.png/250px-175Togepi.png")));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        myFrame.add(background);

        timer.setInitialDelay(2000);
        timer.start();

        myFrame.setLayout(new GridLayout(1, 1));
        myFrame.setUndecorated(true);
        myFrame.setAlwaysOnTop(true);
        myFrame.pack();
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        myFrame.setLocation((dim.width/2-170), dim.height/2-125);
        myFrame.setVisible(true);
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new SplashscreenSample().createFrame()); 
    }
}

或者您可以使用Splashscreen 类...

例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;

public class SplashScreen extends JWindow {
    private int duration;

    public SplashScreen(int d) {
        duration = d;
    }

    // A simple little method to show a title screen in the center
    // of the screen for the amount of time given in the constructor
    public void showSplash() {
        ImageIcon icon = null;
        try {
            icon = new ImageIcon(new URL("http://www.cqsisu.com/data/wallpapers/5/718448.gif"));
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        JPanel content = (JPanel) getContentPane();
        content.setBackground(Color.white);

        // Set the window's bounds, centering the window
        int width = icon.getIconWidth();
        int height = icon.getIconHeight();
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (screen.width - width) / 2;
        int y = (screen.height - height) / 2;

        setBounds(x, y, width, height);

        // Build the splash screen
        JLabel label = new JLabel(icon);
        JLabel copyrt = new JLabel("Copyright 2002, O'Reilly & Associates", JLabel.CENTER);
        copyrt.setFont(new Font("Sans-Serif", Font.BOLD, 12));
        content.add(label, BorderLayout.CENTER);
        content.add(copyrt, BorderLayout.SOUTH);
        Color oraRed = new Color(156, 20, 20, 255);
        content.setBorder(BorderFactory.createLineBorder(oraRed, 10));

        // Display it
        setVisible(true);

        // Wait a little while, maybe while loading resources
        loadResources();

        setVisible(false);
    }

    public void loadResources() {
        TestFrame tf = new TestFrame();
        try {
            Thread.sleep(duration);
            tf.startGUI();
        } catch (Exception e) {
        }
    }

    public static void main(String[] args) {
        SplashScreen splash = new SplashScreen(10000);
        splash.showSplash();
    }
}

【讨论】:

  • 我实际上首先尝试了 SplashScreen 类的实现,但我遇到了类似的问题。每次我调用该方法时,框架都不会出现。所以我放弃了,尝试了一种新的方法。感谢您的回答。非常感谢
  • @15150776 每当您尝试某事时,将其添加到您的问题中,解释为什么它对您不起作用(建议包括该意图的minimal reproducible example),因此人们不必猜测您'已经尝试过,而你没有尝试过。我的代码对你有帮助吗?还是没有?如果不是,请解释原因。
  • 我也没有直接使用你所有的代码,而是尝试了你建议的错误的修改,仍然无法让它工作。我还是 Java 初学者,不太了解你的代码时不想使用它
  • @15150776 你不明白什么?如果我为此行运行代码(只是更改“oreily.gif”,因为我不拥有该 gif):new URL("http://www.cqsisu.com/data/wallpapers/5/718448.gif") 它可以工作。我可以看到 gif 正在播放
  • 另一个问题是 ClassToLoad 代码,该代码显示。如果此代码需要很长时间加载,并且不直接涉及 GUI 代码,则需要从后台线程调用它,例如在 SwingWorker 的 doInBackground 方法中,然后需要主 gui 或启动屏幕在其运行完成时通知,例如通过向 SwingWorker 添加 PropertyChangeListener 并监听 `SwingWorker.StateValue.DONE。
【解决方案2】:

尝试在类的构造函数中创建和设置可见的框架。
会不会是在你的程序计数的时候

 while (elapsedTime < 2*1000) 
    {
        if(count==0)
        {
            mp.launchInitiation();
        }
        count+=1;

        elapsedTime = (new Date()).getTime() - startTime;
    }

它阻塞了 2 秒,等待这个方法完成,返回 create 方法然后完成那个?

看来这可能是一个更好的评论,但出于某种原因我需要 50 个代表才能发表评论。

【讨论】:

  • 嗯,谢谢。它现在实际上正在加载,但仍然出现错误。框架在左上角加载,而不是在中心加载,我得到一个 IllegalStateComponentException 说框架是可显示的,所以我的其余代码不会执行。知道该怎么做吗?此外,如果我删除导致错误的行(myFrame.setUndecorated(true)),图像就不会加载到框架中。顺便说一句,我只在构造函数中将框架设置为可见
  • 使框架居中:frame.setLocationRelativeTo(null);
  • 你也可以setLocationRelativeTo(GUIELEMENT X);
  • 我认为是frame.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
  • setUndecorated 用于在从主调用时显示框架之前工作。我认为这可能与 JFrame 可见然后调用 setUndecorated 的事实有关。然而,我更大的问题是图像实际上无法正确加载。要么我在 JFrame 中出现黑屏,要么 JFrame 只是没有出现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多