为什么这个JDialog在模态时会在Win7中闪烁?

时间:2011-11-01 15:00:20

标签: java windows-7 flicker java-7 jdialog

在Windows 7和Java 1.7(或1.6中,注释掉指出的两行)中,创建一个名为“test”的NetBeans / Eclipse项目,其中包含两个类Test和DroppableFrame,并将此代码粘贴到其中。然后运行它。

如果你使用modal = true运行,它就会闪烁。如果使用modal = false运行,则不会。我做错了什么?

// test.java
package test;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Test implements KeyListener, MouseListener
{
    public Test(boolean m_modal)
    {
        Dimension prefSize;
        Insets inset;
        Font fontLabel, fontInput, fontButtons;
        int buttonCenters, buttonBackoff, buttonWidth, buttonCount, thisButton, buttonTop;
        String caption;

        JLayeredPane m_pane;
        JLabel m_lblBackground;
        JScrollPane m_txtInputScroll;
        int m_width, m_height, m_actual_width, m_actual_height;
        boolean m_singleLineInput   = true;
        String m_caption            = "Sample Modal Input";

        m_width     = 450;
        m_height    = m_singleLineInput ? /*single line*/180 : /*multi-line*/250;
        m_frame     = new DroppableFrame(false);
        caption     = m_caption;
        m_frame.setTitle(caption);

        // Compute the actual size we need for our window, so it's properly centered
        m_frame.pack();
        Insets fi       = m_frame.getInsets();
        m_actual_width  = m_width  + fi.left + fi.right;
        m_actual_height = m_height + fi.top  + fi.bottom;
        m_frame.setSize(m_width  + fi.left + fi.right,
                        m_height + fi.top  + fi.bottom);

        prefSize = new Dimension(m_width  + fi.left + fi.right,
                                 m_height + fi.top  + fi.bottom);
        m_frame.setMinimumSize(prefSize);
        m_frame.setPreferredSize(prefSize);
        m_frame.setMinimumSize(prefSize);
        m_frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        m_frame.setSize(m_width, m_height);
        m_frame.setLocationRelativeTo(null);    // Center window
        m_frame.setLayout(null);                // We handle all redraws

        Container c = m_frame.getContentPane();
        c.setBackground(Color.WHITE);
        c.setForeground(Color.BLACK);

        m_pane = new JLayeredPane();
        m_pane.setLayout(null);
        m_pane.setBounds(0, 0, m_width, m_height);
        m_pane.setVisible(true);
        m_pane.setBorder(BorderFactory.createEmptyBorder());
        c.add(m_pane);

        // Set the background image
        m_lblBackground = new JLabel();
        m_lblBackground.setBounds(0, 0, m_width, m_height);
        m_lblBackground.setHorizontalAlignment(JLabel.LEFT);
        m_lblBackground.setVerticalAlignment(JLabel.TOP);
        m_lblBackground.setVisible(true);
        m_lblBackground.setBackground(Color.WHITE);
        m_pane.add(m_lblBackground);
        m_pane.moveToFront(m_lblBackground);

        // Create the fonts
        fontLabel   = new Font("Calibri", Font.BOLD, 20);
        fontInput   = new Font("Calibri", Font.BOLD, 14);
        fontButtons = fontLabel;

        // Create the visible label contents
        JLabel m_lblLabel = new JLabel();
        m_lblLabel.setBounds(15, 52, 423, 28);
        m_lblLabel.setHorizontalAlignment(JLabel.LEFT);
        m_lblLabel.setVerticalAlignment(JLabel.CENTER);
        m_lblLabel.setFont(fontLabel);
        m_lblLabel.setForeground(Color.BLUE);
        m_lblLabel.setText("A sample input:");
        m_lblLabel.setVisible(true);
        m_pane.add(m_lblLabel);
        m_pane.moveToFront(m_lblLabel);

        // Create the input box
        if (m_singleLineInput)
        {   // It's a single-line input box
            m_txtInputSingleLine = new JTextField();
            m_txtInputSingleLine.setBounds(15, 85, 421, 25);
            m_txtInputSingleLine.setFont(fontInput);
            m_txtInputSingleLine.setText("Initial Value");
            m_txtInputSingleLine.setVisible(true);
            m_txtInputSingleLine.addKeyListener(this);
            m_pane.add(m_txtInputSingleLine);
            m_pane.moveToFront(m_txtInputSingleLine);

        } else {
            m_txtInput          = new JTextArea();
            m_txtInputScroll    = new JScrollPane(m_txtInput);
            m_txtInputScroll.setBounds(15, 83, 421, 100);
            m_txtInputScroll.setAutoscrolls(true);
            m_txtInputScroll.setVisible(true);
            m_txtInput.setFont(fontInput);
            m_txtInput.setLineWrap(true);
            m_txtInput.setWrapStyleWord(true);
            m_txtInput.setTabSize(2);
            m_txtInput.setText("Initial Value");
            m_txtInput.setVisible(true);
            m_pane.add(m_txtInputScroll);
            m_pane.moveToFront(m_txtInputScroll);
        }

        // Determine which buttons are specified
        buttonCount = 0;
        m_buttons = _CANCEL_BUTTON + _OKAY_BUTTON;
        if ((m_buttons & _NEXT_BUTTON) != 0)
        {
            m_btnNext = new JButton("Next");
            m_btnNext.setFont(fontButtons);
            m_btnNext.addMouseListener(this);
            inset = m_btnNext.getInsets();
            inset.left = 3;
            inset.right = 3;
            m_btnNext.setMargin(inset);
            m_pane.add(m_btnNext);
            m_pane.moveToFront(m_btnNext);
            ++buttonCount;
        }
        if ((m_buttons & _CANCEL_BUTTON) != 0)
        {
            m_btnCancel = new JButton("Cancel");
            m_btnCancel.setFont(fontButtons);
            m_btnCancel.addMouseListener(this);
            inset = m_btnCancel.getInsets();
            inset.left = 3;
            inset.right = 3;
            m_btnCancel.setMargin(inset);
            m_pane.add(m_btnCancel);
            m_pane.moveToFront(m_btnCancel);
            ++buttonCount;
        }
        if ((m_buttons & _ACCEPT_BUTTON) != 0)
        {
            m_btnAccept = new JButton("Accept");
            m_btnAccept.setFont(fontButtons);
            m_btnAccept.addMouseListener(this);
            inset = m_btnAccept.getInsets();
            inset.left = 3;
            inset.right = 3;
            m_btnAccept.setMargin(inset);
            m_pane.add(m_btnAccept);
            m_pane.moveToFront(m_btnAccept);
            ++buttonCount;
        }
        if ((m_buttons & _OKAY_BUTTON) != 0)
        {
            m_btnOkay = new JButton("Okay");
            m_btnOkay.setFont(fontButtons);
            m_btnOkay.addMouseListener(this);
            inset = m_btnOkay.getInsets();
            inset.left = 3;
            inset.right = 3;
            m_btnOkay.setMargin(inset);
            m_pane.add(m_btnOkay);
            m_pane.moveToFront(m_btnOkay);
            ++buttonCount;
        }

        // Determine the coordinates for each button
        buttonCenters   = (m_width / (buttonCount + 1));
        buttonWidth     = (int)((double)buttonCenters * 0.80);
        buttonBackoff   = (m_width / (buttonCount + 2)) / 2;

        // Position the buttons
        thisButton  = 1;
        buttonTop   = m_singleLineInput ? 130 : 200;
        if (m_btnNext != null)
        {   // Position and make visible this button
            m_btnNext.setBounds( + (thisButton * buttonCenters) - buttonBackoff, buttonTop, buttonWidth, 40);
            m_btnNext.setVisible(true);
            ++thisButton;
        }
        if (m_btnCancel != null)
        {   // Position and make visible this button
            m_btnCancel.setBounds((thisButton * buttonCenters) - buttonBackoff, buttonTop, buttonWidth, 40);
            m_btnCancel.setVisible(true);
            ++thisButton;
        }
        if (m_btnAccept!= null)
        {   // Position and make visible this button
            m_btnAccept.setBounds((thisButton * buttonCenters) - buttonBackoff, buttonTop, buttonWidth, 40);
            m_btnAccept.setVisible(true);
            ++thisButton;
        }
        if (m_btnOkay != null)
        {   // Position and make visible this button
            m_btnOkay.setBounds((thisButton * buttonCenters) - buttonBackoff, buttonTop, buttonWidth, 40);
            m_btnOkay.setVisible(true);
            ++thisButton;
        }

// The modal code causes some slow component rendering.
// Needs looked at to figure out why
        if (m_modal)
        {   // Make it a modal window
            m_frame.setModal(m_width, m_height, fi, m_pane);

        } else {
            // Make it a non-modal window
            m_frame.setVisible(true);
            m_frame.forceWindowToHaveFocus();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        m_frame.dispose();
        System.exit(0);
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    public static void main(String[] args)
    {
        boolean modal = true;
        Test t = new Test(modal);
    }

    private DroppableFrame  m_frame;

    private int             m_buttons;
    private JTextField      m_txtInputSingleLine;
    private JTextArea       m_txtInput;
    private JButton         m_btnNext;
    private JButton         m_btnCancel;
    private JButton         m_btnAccept;
    private JButton         m_btnOkay;

    public static final int _NEXT_BUTTON    = 1;
    public static final int _CANCEL_BUTTON  = 2;
    public static final int _ACCEPT_BUTTON  = 4;
    public static final int _OKAY_BUTTON    = 8;
    public static final int _NEXT_CANCEL    = 3;
    public static final int _ACCEPT_CANCEL  = 6;
    public static final int _OKAY_CANCEL    = 10;
}


        // DroppableFrame.java
    package test;

    import java.awt.*;
    import java.awt.event.ComponentEvent;
    import java.io.*;
    import java.util.*;
    import java.awt.dnd.*;
    import java.awt.datatransfer.*;
    import java.awt.event.ComponentListener;
    import java.awt.event.InputEvent;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import javax.swing.*;

    public class DroppableFrame extends JFrame
                                implements  DropTargetListener,
                                            DragSourceListener,
                                            DragGestureListener,
                                            ComponentListener
    {
        public DroppableFrame(boolean isResizeable)
        {
            super("JFrame");

            m_dragSource    = DragSource.getDefaultDragSource();
            m_dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
            this.setDropTarget(new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this));
            addComponentListener(this);

            m_isResizeable  = isResizeable;
            m_modal         = false;
            setResizable(isResizeable);
        }

        /**
         * Sets the frame to a modal state
         * @param width
         * @param height
         */
        public void setModal(int            width,
                             int            height,
                             Insets         fi,
                             JLayeredPane   m_pan)
        {
            int i;
            Component[] comps;
            Component c;
            Point p;

            m_modal         = true;
            m_modalDialog   = new Dialog((JFrame)null, getTitle(), true);
            m_modalDialog.setLayout(null);
            m_modalDialog.setResizable(m_isResizeable);
            m_modalDialog.setSize(width + fi.left + fi.right, height + fi.top + (fi.bottom * 2));
            m_modalDialog.setAlwaysOnTop(true);
            m_modalDialog.setLocationRelativeTo(null);
            if (m_pan != null)
            {   // Add/copy the pane's components
                comps = m_pan.getComponents();
                if (comps != null)
                    for (i = 0; i < comps.length; i++)
                    {   // Add and reposition the component taking into account the insets
                        c = m_modalDialog.add(comps[i]);
                        p = c.getLocation();
                        c.setLocation(p.x + fi.left, p.y + fi.top + fi.bottom);
                    }
            }
            m_modalDialog.setVisible(true);
        }

        @Override
        public void paint(Graphics g)
        {
            Dimension d = getSize();
            Dimension m = getMaximumSize();

            boolean resize = d.width > m.width || d.height > m.height;
            d.width = Math.min(m.width, d.width);
            d.height = Math.min(m.height, d.height);
            if (resize)
            {
                Point p = getLocation();
                setVisible(false);
                setSize(d);
                setLocation(p);
                setVisible(true);
            }
            super.paint(g);
        }

        @Override
        public void dragDropEnd(DragSourceDropEvent DragSourceDropEvent){}

        @Override
        public void dragEnter(DragSourceDragEvent DragSourceDragEvent){}

        @Override
        public void dragExit(DragSourceEvent DragSourceEvent){}

        @Override
        public void dragOver(DragSourceDragEvent DragSourceDragEvent){}

        @Override
        public void dropActionChanged(DragSourceDragEvent DragSourceDragEvent){}

        @Override
        public void dragEnter (DropTargetDragEvent dropTargetDragEvent)
        {
            dropTargetDragEvent.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
        }

        @Override
        public void dragExit (DropTargetEvent dropTargetEvent) {}

        @Override
        public void dragOver (DropTargetDragEvent dropTargetDragEvent) {}

        @Override
        public void dropActionChanged (DropTargetDragEvent dropTargetDragEvent){}

        @Override
        public synchronized void drop(DropTargetDropEvent dropTargetDropEvent)
        {
            try
            {
                Transferable tr = dropTargetDropEvent.getTransferable();
                if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
                {
                    dropTargetDropEvent.acceptDrop (DnDConstants.ACTION_COPY_OR_MOVE);
                    java.util.List fileList = (java.util.List)tr.getTransferData(DataFlavor.javaFileListFlavor);
                    Iterator iterator = fileList.iterator();
                    while (iterator.hasNext())
                    {
                        File file = (File)iterator.next();
                        if (file.getName().toLowerCase().endsWith(".xml"))
                        {   // Do something with the file here

                        } else {
                            System.out.println("Ignored dropped file: " + file.getAbsolutePath());
                        }
                    }
                    dropTargetDropEvent.getDropTargetContext().dropComplete(true);

                } else {
                    dropTargetDropEvent.rejectDrop();

                }

            } catch (IOException io) {
                dropTargetDropEvent.rejectDrop();

            } catch (UnsupportedFlavorException ufe) {
                dropTargetDropEvent.rejectDrop();

            }
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dragGestureEvent)
        {
        }

        public void setTranslucency(float opaquePercent)
        {
            try
            {
                if (System.getProperty("java.version").substring(0,3).compareTo("1.6") <= 0)
                {   // Code for translucency works in 1.6, raises exception in 1.7
                    Class awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities");
                    Method mSetWindowOpacity;
                    mSetWindowOpacity = awtUtilitiesClass.getMethod("setWindowOpacity", Window.class, float.class);
                    if (mSetWindowOpacity != null)
                    {
                        if (!m_modal)
                            mSetWindowOpacity.invoke(null, this, opaquePercent);
                    }

                } else {
// If compiling in 1.6 or earlier, comment-out these next two lines
                    if (!m_modal)
                        setOpacity(opaquePercent);
                }

            } catch (NoSuchMethodException ex) {
            } catch (SecurityException ex) {
            } catch (ClassNotFoundException ex) {
            } catch (IllegalAccessException ex) {
            } catch (IllegalArgumentException ex) {
            } catch (InvocationTargetException ex) {
            } catch (IllegalComponentStateException ex) {
            } catch (Throwable t) {
            } finally {
            }
        }

        @Override
        public void componentResized(ComponentEvent e)
        {
            Dimension d = getSize();
            Dimension m = getMaximumSize();

            boolean resize = d.width > m.width || d.height > m.height;
            d.width = Math.min(m.width, d.width);
            d.height = Math.min(m.height, d.height);
            if (resize)
                setSize(d);
        }

        @Override
        public void componentMoved(ComponentEvent e) {
        }

        @Override
        public void componentShown(ComponentEvent e) {
        }

        @Override
        public void componentHidden(ComponentEvent e) {
        }

        @Override
        public void dispose()
        {
            if (m_modal)
            {
                m_modalDialog.setVisible(false);
                m_modalDialog = null;
            }
            super.dispose();
        }

        public void forceWindowToHaveFocus()
        {
            Rectangle bounds;
            Insets insets;
            Robot robot = null;

            if (m_modal)
                m_modalDialog.setVisible(true);
            setVisible(true);
            toFront();

            bounds = getBounds();
            insets = getInsets();

            try {
                robot = new Robot();
                robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + insets.top / 2);
                robot.mousePress(InputEvent.BUTTON1_MASK);
                robot.mouseRelease(InputEvent.BUTTON1_MASK);

            } catch (AWTException ex) {
            }
        }

        protected DragSource            m_dragSource;
        protected boolean               m_isResizeable;
        protected boolean               m_modal;
        protected Dialog                m_modalDialog;
    }

1 个答案:

答案 0 :(得分:1)

看起来您正在向AWT Dialog添加Swing组件。这肯定会引起问题。使用JDialog似乎可以消除闪烁。