调整JFrame大小时为黑色轮廓 [英] Black outline while resizing JFrame

查看:85
本文介绍了调整JFrame大小时为黑色轮廓的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从一个JPanel到下一个JPanel创建平滑的动画,其中第二个JPanel既比第一个JPanel高又宽,这要求我重新缩放JFrame.为此,我创建了以下代码:

I'm trying to create a smooth animation from one JPanel to the next where the second JPanel is both taller and wider than the first requiring me to rescale the JFrame. To do this I created the following code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;

public class Example1 extends JFrame
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public Example1()
    {
        initComponents();
    }

    public static void main(String[] args) 
    {
        try 
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // get look and feel based on OS
        } 
        catch (ClassNotFoundException ex) // catch all errors that may occur
        {
            Logger.getLogger(Example1.class.getName()).log(Level.SEVERE, null, ex);
        } 
        catch (InstantiationException ex) 
        {
            Logger.getLogger(Example1.class.getName()).log(Level.SEVERE, null, ex);
        } 
        catch (IllegalAccessException ex) 
        {
            Logger.getLogger(Example1.class.getName()).log(Level.SEVERE, null, ex);
        } 
        catch (UnsupportedLookAndFeelException ex) 
        {
            Logger.getLogger(Example1.class.getName()).log(Level.SEVERE, null, ex);
        }

        EventQueue.invokeLater(new Runnable()
        {
            public void run() // run the class's constructor, therefore starting
                                // the UI being built
            {
                new Example1().setVisible(true);;
            }
        });
    }

    private WindowListener exitListener = new WindowAdapter() 
    {
        @Override
        public void windowClosing(WindowEvent e) 
        {
            closingEvent(); // if window closing, go to exit menu
        }
    };

    private void initComponents() // method to build initial view for user for installation
    {
        // instantiating elements of the GUI
        pnlStart = new JPanel();
        lblMain = new JLabel();
        lblDivider = new JLabel();
        lblTextPrompt = new JLabel();
        txtAccNum = new JTextField();
        btnNext = new JButton();
        btnExit = new JButton();

        pnlStart.setVisible(true);
        add(pnlStart); // adding the panel to the frame

        removeWindowListener(exitListener);
        addWindowListener(exitListener); // removing before adding the windowlistener, ensures there is only one listener there
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // setting "x" button to do nothing except what exitListener does
        setPreferredSize(new Dimension(600, 400)); // setting measurements of jframe

        setTitle("Example 1.0"); // setting title on JFrame
        setResizable(false); // disabling resizing
        setLayout(null); // ensuring I can specify element positions
        setBackground(Color.WHITE); // setting background color

        lblMain.setText("<html>Please input a number below how many accounts you would like to<br>create: </html>"); // main label that explains what happens, html used for formatting
        lblMain.setFont(lblMain.getFont().deriveFont(18.0f)); // changing font size to 16
        lblMain.setBounds(27, 60, 540, 100); // setting position and measurements
        add(lblMain); // adding label to JFrame

        lblTextPrompt.setText("Amount of accounts (1-10):");
        lblTextPrompt.setFont(lblMain.getFont().deriveFont(16.0f));
        lblTextPrompt.setBounds(166, 190, 198, 18);
        lblTextPrompt.setLabelFor(txtAccNum);
        add(lblTextPrompt);

        txtAccNum.setFont(lblMain.getFont());
        txtAccNum.setBounds(374, 187, 50, 26);
        txtAccNum.addKeyListener(new KeyAdapter() 
        {
            public void keyTyped(KeyEvent e) 
            {
                if (txtAccNum.getText().length() >= 4) // limit textfield to 3 characters
                    e.consume();
            }
        });
        txtAccNum.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                AccDetails(Integer.parseInt(txtAccNum.getText()));
            }
        });
        add(txtAccNum);

        lblDivider.setText(""); // ensuring no text in label
        lblDivider.setBounds(10, 285, 573, 10); // setting bounds and position of dividing line
        lblDivider.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY)); // setting border to label for the dividing
        add(lblDivider); // adding it to JFrame

        btnNext.setText("Next"); // adding text to button for starting
        btnNext.setFont(lblMain.getFont().deriveFont(14.0f)); // setting font size
        btnNext.setBounds(495, 315, 80, 35); // positioning start button
        btnNext.addActionListener(new ActionListener() // add listener for action to run method
        {
            public void actionPerformed(ActionEvent evt) 
            {
                AccDetails(Integer.parseInt(txtAccNum.getText()));
            }
        });
        add(btnNext); // adding button to JFrame

        btnExit.setText("Exit"); // adding text to button for exiting
        btnExit.setFont(btnNext.getFont()); // getting font from start button
        btnExit.setBounds(20, 315, 80, 35); // positioning on form
        btnExit.addActionListener(new ActionListener() // add listener for action to run method
        {
            public void actionPerformed(ActionEvent evt) 
            {
                closingEvent(); // running cancel method (same method as hitting the "x" button on the form)
            }
        });

        add(btnExit); // adding button to JFrame
        repaint(); // repainting what is displayed if going coming from a different form
        revalidate(); // revalidate the elements that will be displayed
        pack(); // packaging everything up to use
        setLocationRelativeTo(null); // setting form position central
        txtAccNum.requestFocusInWindow(); // setting focus on start button when everything is loaded
    }

    private void AccDetails(int accNum) 
    {
        getContentPane().removeAll();
        // instantiating elements of the GUI
        pnlAccDetails = new JPanel();

        pnlAccDetails.setVisible(true);
        add(pnlAccDetails); // adding the panel to the frame

        removeWindowListener(exitListener);
        addWindowListener(exitListener); // removing before adding the windowlistener, ensures there is only one listener there
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // setting "x" button to do nothing except what exitListener does

        while (sizeW != 750 && sizeH != 500)
        {
            setBackground(Color.BLACK);
            Point loc = getLocationOnScreen();
            setPreferredSize(new Dimension(sizeW, sizeH));
            pnlAccDetails.setPreferredSize(new Dimension(sizeW, sizeH));
            repaint();
            revalidate();
            pack();

            sizeW += 1.5;
            sizeH += 1;
            if (toggle)
            {
                setLocation((int)(loc.getX() - 0.75), (int)(loc.getY() - 0.5));
                toggle = false;
            }
            else
            {
                toggle = true;
            }

            try 
            {
                Thread.sleep(1);
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }

        setTitle("Example 1.0"); // setting title on JFrame
        setResizable(false); // disabling resizing
        setLayout(null); // ensuring I can specify element positions
        setBackground(Color.WHITE); // setting background color

        repaint(); // repainting what is displayed if going coming from a different form
        revalidate(); // revalidate the elements that will be displayed
        pack(); // packaging everything up to use
        setLocationRelativeTo(null); // setting form position central
    }

    private void closingEvent() 
    {
        if (JOptionPane.showConfirmDialog(null, "<html><center>Are you sure you want to quit?</center></html>", "Quit?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) 
            System.exit(0); // output warning that it would cancel installation, if accepted...
        else // if not accepted...
        {
        }
    }

    // objects used in UI
    private JPanel pnlStart;
    private JPanel pnlAccDetails;
    private JLabel lblMain;
    private JLabel lblDivider;
    private JLabel lblTextPrompt;
    private JTextField txtAccNum;
    private JButton btnNext;
    private JButton btnExit;

    private int sizeW = 600;
    private int sizeH = 400;
    private boolean toggle = false;
}

虽然此代码可以正常工作,但在调整大小期间,表单不会保留其背景色,而是在新尺寸的基础上显示了黑色轮廓.从我所做的研究中,我了解到这是由于使用了渲染引擎.是否有某种方法可以强制渲染引擎在每次迭代时运行,或者有另一种方法可以执行此操作?我已经看到了使用Universal Tween Engine的建议,但是我找不到任何调整大小的示例,尤其是对于JFrame. 预先感谢

While this code does work, during the resizing, the form doesn't retain it's background colour and instead has a black outline with the new measurements. I understand, from the research I've done, this is due to the rendering engine used. Is there anyway to force the render engine to run at each iteration or is there another way of doing this? I've seen the suggestion of using Universal Tween Engine however I couldn't find any resizing examples, especially for the JFrame. Thanks in advance

推荐答案

如上述注释所述(由@Sergiy Medvynskyy撰写),阻止了Swing Thread导致其无法正确呈现.通过使用Swing Timer,动画可以流畅运行.我用于解决方案的代码是:

As stated in the above comments (by @Sergiy Medvynskyy) blocking the Swing Thread caused it to not render correctly. With using a Swing Timer the animation works smoothly. The code I have used for the solution is:

    timer = new Timer (10, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) 
        {
            Point loc = getLocationOnScreen();
            setPreferredSize(new Dimension(sizeW, sizeH));
            pnlAccDetails.setPreferredSize(new Dimension(sizeW, sizeH));
            repaint();
            revalidate();
            pack();

            sizeW += 3;
            sizeH += 2;
            if (toggle)
            {
                setLocation((int)(loc.getX() - 0.75), (int)(loc.getY() - 0.5));
                toggle = false;
            }
            else
            {
                toggle = true;
            }

            if (sizeW == 750 && sizeH == 500)
            {
                timer.stop();
            }
        }
    });

    timer.start();

在我的原始问题中,上面的代码代替了while循环.感谢Sergiy Medvynskyy的回答.

The above code is used in place of the while loop in my original question. Thanks to Sergiy Medvynskyy for the answer.

这篇关于调整JFrame大小时为黑色轮廓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆