Swing:在Linux中调整像框架一样的JFrame,例如

Val*_* Ru 7 java swing jframe mouse-listeners componentlistener

我想知道是否有可能以这种方式实现JFrame的大小调整,它已被调整大小,例如linux中的标准窗口.更确切地说:如果用户开始拖动,则只有未来的大小才能预览窗口,而原始内容不会调整大小.一旦用户释放鼠标,Frame就会调整为该大小.在图像中:

(1)调整大小之前的状态

在此输入图像描述

(2)用户开始下垂(在红色圆圈)

在此输入图像描述

(3)用户释放鼠标,框架调整大小

在此输入图像描述

是否有可能在Java Swing中意识到这一点?

编辑:

由于这个程序有一天也应该在较低的Java RE中作为7运行,我尝试将mKorbel建议与translucend Frame的注释中的建议结合起来.结果接近目标,除了

  • 在我停止移动鼠标后,contentPane的内容会调整大小,而不是在释放鼠标时
  • 帧标题立即调整大小,而不仅仅是我停止拖动框架边框.
  • 它仅在从右侧或底部调整大小时才起作用,否则内容随拖动而移动.

我认为第一点可以通过代码和MouseListener的组合来解析,类似于mouseReleased(),然后调整大小.这是代码,随意尝试.对于进一步的建议,我仍然对任何建议感到高兴.

该代码稍微修改了Java Tutorials 中的GradientTranslucentWindowDemo.java.我希望它可以在这里发布,否则请告诉我任何侵犯版权的行为.黑色JPanel应该是应用程序的内容,因为contentPane保持不可见.

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;

public class GroundFrame extends JFrame {

    Timer timer;
    JPanel panel2;

    public GroundFrame() {
        super("GradientTranslucentWindow");

        setBackground(new Color(0,0,0,0));
        setSize(new Dimension(300,200));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel() {
        panel.setBackground(new Color(0,0,0,0));
        setContentPane(panel);

        setLayout(null);
        panel2 = new JPanel();
        panel2.setBackground(Color.black);
        panel2.setBounds(0,0,getContentPane().getWidth(), getContentPane().getHeight());
        getContentPane().add(panel2);

        addComponentListener(new ComponentListener() {

            @Override
            public void componentShown(ComponentEvent e) {}

            @Override
            public void componentResized(ComponentEvent e) {
                timer = new Timer(50, new Action() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if(timer.isRunning()){

                        }else{
                            resizePanel(getContentPane().getSize());
                        }
                    }

                    @Override
                    public void setEnabled(boolean b) {}

                    @Override
                    public void removePropertyChangeListener(PropertyChangeListener listener) {}

                    @Override
                    public void putValue(String key, Object value) {}

                    @Override
                    public boolean isEnabled() {return false;}

                    @Override
                    public Object getValue(String key) {return null;}

                    @Override
                    public void addPropertyChangeListener(PropertyChangeListener listener) {}
                });
                timer.setRepeats(false);
                timer.start();

            }

            @Override
            public void componentMoved(ComponentEvent e) {}

            @Override
            public void componentHidden(ComponentEvent e) {}
        });
    }

    public void resizePanel(Dimension dim){
        panel2.setBounds(0,0,dim.width, dim.height);
        repaint();
    }

    public static void main(String[] args) {
        GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        boolean isPerPixelTranslucencySupported =
            gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);

        if (!isPerPixelTranslucencySupported) {
            System.out.println(
                "Per-pixel translucency is not supported");
                System.exit(0);
        }

        JFrame.setDefaultLookAndFeelDecorated(true);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GroundFrame gtw = new GroundFrame();
                gtw.setVisible(true);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

mKo*_*bel 6

如果将预览窗口,则仅显示未来大小,而原始内容未调整大小.一旦用户释放鼠标,Frame就会调整为该大小

非常复杂的想法,但是

编辑

使用此代码进行测试

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

public class ComponentEventDemo extends JPanel
        implements ComponentListener, HierarchyListener,
        ItemListener {

    private JFrame frame;
    private static final long serialVersionUID = 1L;
    private JTextArea display;
    private JLabel label;
    private JComboBox comboBox;
    private JComboBox comboBox1;
    private String newline = "\n";
    private Vector<String> listSomeString = new Vector<String>();
    private Vector<String> listSomeAnotherString = new Vector<String>();

    public ComponentEventDemo() {
        listSomeString.add("-");
        listSomeString.add("Snowboarding");
        listSomeString.add("Rowing");
        listSomeString.add("Knitting");
        listSomeString.add("Speed reading");
        listSomeString.add("Pool");
        listSomeString.add("None of the above");
//
        listSomeAnotherString.add("-");
        listSomeAnotherString.add("XxxZxx Snowboarding");
        listSomeAnotherString.add("AaaBbb Rowing");
        listSomeAnotherString.add("CccDdd Knitting");
        listSomeAnotherString.add("Eee Fff Speed reading");
        listSomeAnotherString.add("Eee Fff Pool");
        listSomeAnotherString.add("Eee Fff None of the above");
        comboBox = new JComboBox(listSomeString);
        comboBox1 = new JComboBox(listSomeAnotherString);
        display = new JTextArea();
        display.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(display);
        scrollPane.setPreferredSize(new Dimension(350, 200));

        label = new JLabel("This is a label", JLabel.CENTER);
        label.addComponentListener(this);

        JCheckBox checkbox = new JCheckBox("Label visible", true);
        checkbox.addItemListener(this);
        checkbox.addComponentListener(this);

        JPanel panel = new JPanel(new GridLayout(1, 2));
        panel.add(label);
        panel.add(checkbox);
        panel.addComponentListener(this);
        frame = new JFrame("ComponentEventDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(panel, BorderLayout.PAGE_END);
        frame.pack();
        frame.setVisible(true);
    }

    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            label.setVisible(true);
            label.revalidate();
            label.repaint();
        } else {
            label.setVisible(false);
        }
    }

    protected void displayMessage(String message) {
        //If the text area is not yet realized, and
        //we tell it to draw text, it could cause
        //a text/AWT tree deadlock. Our solution is
        //to ensure that the text area is realized
        //before attempting to draw text.
        // if (display.isShowing()) {
        display.append(message + newline);
        display.setCaretPosition(display.getDocument().getLength());
        //}
    }

    public void componentHidden(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
    }

    public void componentMoved(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Moved");
    }

    public void componentResized(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
    }

    public void componentShown(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Shown");

    }

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

            public void run() {
                ComponentEventDemo componentEventDemo = new ComponentEventDemo();
            }
        });
    }

    public void hierarchyChanged(HierarchyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
Run Code Online (Sandbox Code Playgroud)


Den*_*kiy 6

模仿这种行为的一个简单技巧是使帧不可调整大小并将帧的某些部分专用于调整大小句柄,然后添加鼠标侦听器并自行调整大小:

    public static class GroundFrame extends JFrame {
        private boolean doResize = false;

        public GroundFrame() throws HeadlessException {
            setResizable(false);

            getContentPane().addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    Point point = e.getPoint();
                    if (point.x >= getWidth() - 50) {
                        doResize = true;
                    }
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    if (doResize) {
                        setSize(e.getX(), getHeight());
                        doResize = false;
                    }
                }
            });
        }
    }
Run Code Online (Sandbox Code Playgroud)

您甚至可以使jframe未修饰并执行所有操作,如自己调整大小,移动,关闭等.

但同样,这种行为是由窗口管理器或合成管理器控制的(例如,你可以调整compiz为你做这样的事情).我认为实时调整大小是NeXT的主要广告功能之一,当时迈出了重要的一步:)

此外,我尝试的另一个技巧是基于java 7报告在事件发生时调整事件大小,而不是鼠标释放,因此可以在首次调整大小后保存窗口大小,然后恢复它,直到调整大小完成.但是,工作不顺利:

    public static class GroundFrame extends JFrame {
        private Timer timer;
        private Dimension oldSize;

        public GroundFrame() throws HeadlessException {
            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    oldSize = null;
                    invalidate();
                }
            });
            timer.setRepeats(false);

            addComponentListener(new ComponentAdapter() {
                public void componentResized(ComponentEvent e) {
                    if (oldSize == null) {
                        oldSize = getSize();
                        timer.start();
                    } else {
                        setSize(oldSize);
                        timer.restart();
                    }
                }
            });
        }
    }
Run Code Online (Sandbox Code Playgroud)


Dav*_*amp 6

+1给mKorbel和Denis Tulskiy的答案.

我做了一些可能有帮助的抽象解决方案.它支持JFrameJFrame(NORTH,EAST,SOUTH和WEST)的所有四个边调整大小(增加和减少高度和宽度),当鼠标移动到其中一个角时,它也可以同时按宽度和高度重新调整大小.

基本上我做的是:

  • 添加MouseMotionListenerMouseListenerJFrame
  • 覆盖mouseDragged(..),mouseMoved(..),mousePressed(..)mouseReleased(..)Listener秒.
  • 设置JFrame为不可调整大小.
  • mouseMoved(..)听从鼠标底部或右侧10px或更少的时候.的JFrame,它然后将调整大小的适当的方向(高度或宽度),改变小鼠Cursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)对于远右/宽度大小调整,Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)对于底部/ hieght调整大小,Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)为帧大小调整高度的顶部或Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)相应地与呼叫为左侧宽度调整大小)canResize(true).
  • mouseDragged(..)更新的宽度或高度为新的大小及其在方向拖
  • mouseReleased(..)设置JFrame为新的大小.
  • mousePressed(..)我们检查用户按下的坐标(这允许我们查看帧大小是否正在减少/增加).

看看我做的这个例子:

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class JFrameSizeAfterDrag extends JFrame {

    //direction holds the position of drag
    private int w = 0, h = 0, direction, startX = 0, startY = 0;

    public JFrameSizeAfterDrag() {
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        addMouseListener(new MouseAdapter() {
            //so we can see if from where the user clikced is he increasing or decraesing size
            @Override
            public void mousePressed(MouseEvent me) {
                super.mouseClicked(me);
                startX = me.getX();
                startY = me.getY();
                System.out.println("Clicked: " + startX + "," + startY);
            }

            //when the mouse is relaeased set size
            @Override
            public void mouseReleased(MouseEvent me) {
                super.mouseReleased(me);
                System.out.println("Mouse released");
                if (direction == 1 || direction == 2 || direction == 5 || direction == 6) {
                    setSize(w, h);
                } else {//this should move x and y by as much as the mouse moved then use setBounds(x,y,w,h);
                    setBounds(getX() - (startX - me.getX()), getY() - (startY - me.getY()), w, h);
                }
                validate();
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            private boolean canResize;

            //while dragging check direction of drag
            @Override
            public void mouseDragged(MouseEvent me) {
                super.mouseDragged(me);
                System.out.println("Dragging:" + me.getX() + "," + me.getY());
                if (canResize && direction == 1) {//frame height  change
                    if (startY > me.getY()) {//decrease in height
                        h -= 4;
                    } else {//increase in height
                        h += 4;
                    }
                } else if (canResize && direction == 2) {//frame width  change
                    if (startX > me.getX()) {//decrease in width
                        w -= 4;
                    } else {//increase in width
                        w += 4;
                    }
                } else if (canResize && direction == 3) {//frame height  change
                    if (startX > me.getX()) {//decrease in width
                        w += 4;
                    } else {//increase in width
                        w -= 4;
                    }
                } else if (canResize && direction == 4) {//frame width  change
                    if (startY > me.getY()) {//decrease in height
                        h += 4;
                    } else {//increase in height
                        h -= 4;
                    }
                } else if (canResize && direction == 5) {//frame width and height  change bottom right
                    if (startY > me.getY() && startX > me.getX()) {//increase in height and width
                        h -= 4;
                        w -= 4;
                    } else {//decrease in height and with
                        h += 4;
                        w += 4;
                    }
                } /* Windows dont usually support reszing from top but if you want :) uncomment code in mouseMoved(..) also
                 else if (canResize && direction == 6) {//frame width and height  change top left
                 if (startY > me.getY() && startX > me.getX()) {//decrease in height and with
                 h += 4;
                 w += 4;
                 } else {//increase in height and width
                 h -= 4;
                 w -= 4;
                 }
                 } else if (canResize && direction == 8) {//frame width and height  change top right
                 if (startY > me.getY() && startX > me.getX()) {//increase in height and width
                 h -= 4;
                 w -= 4;
                 } else {//decrease in height and with
                 h += 4;
                 w += 4;
                 }
                 }
                 */ else if (canResize && direction == 7) {//frame width and height  change bottom left
                    if (startY > me.getY() && startX > me.getX()) {//increase in height and width
                        h -= 4;
                        w -= 4;
                    } else {//decrease in height and with
                        h += 4;
                        w += 4;
                    }
                }
            }

            @Override
            public void mouseMoved(MouseEvent me) {
                super.mouseMoved(me);
                if (me.getY() >= getHeight() - 10 && me.getX() >= getWidth() - 10) {//close to bottom and right side of frame show south east cursor and allow height witdh simaltneous increase/decrease
                    //System.out.println("resize allowed..");
                    canResize = true;
                    setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
                    direction = 5;
                } /*Windows dont usually support reszing from top but if you want :) uncomment code in mouseDragged(..) too
                 else if (me.getY() <= 28 && me.getX() <= 28) {//close to top side and left side of frame show north west cursor and only allow increase/decrease in width and height simultaneosly
                 //System.out.println("resize allowed..");
                 canResize = true;
                 setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
                 direction = 6;
                 }  else if (me.getY() <= 28 && me.getX() >= getWidth() - 10) {//close to top and right side of frame show north east cursor and only allow increase/decrease in width and height simultaneosly
                 //System.out.println("resize allowed..");
                 canResize = true;
                 setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
                 direction = 8;
                 } 
                 */ else if (me.getY() >= getHeight() - 10 && me.getX() <= 10) {//close to bottom side and left side of frame show north west cursor and only allow increase/decrease in width and height simultaneosly
                    //System.out.println("resize allowed..");
                    canResize = true;
                    setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
                    direction = 7;
                } else if (me.getY() >= getHeight() - 10) {//close to bottom of frame show south resize cursor and only allow increase height
                    //System.out.println("resize allowed");
                    canResize = true;
                    setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
                    direction = 1;
                } else if (me.getX() >= getWidth() - 10) {//close to right side of frame show east cursor and only allow increase width
                    //System.out.println("resize allowed");
                    canResize = true;
                    setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
                    direction = 2;
                } else if (me.getX() <= 10) {//close to left side of frame show east cursor and only allow increase width
                    //System.out.println("resize allowed");
                    canResize = true;
                    setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
                    direction = 3;
                } else if (me.getY() <= 28) {//close to top side of frame show east cursor and only allow increase height
                    // System.out.println("resize allowed..");
                    canResize = true;
                    setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
                    direction = 4;
                } else {
                    canResize = false;
                    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    // System.out.println("resize not allowed");
                }
            }
        });

        //just so GUI is visible and not small
        add(new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        });

        pack();
        setVisible(true);
    }

    @Override
    public void setVisible(boolean bln) {
        super.setVisible(bln);
        w = getWidth();
        h = getHeight();
    }

    public static void main(String[] args) {

        /**
         * Create GUI and components on Event-Dispatch-Thread
         */
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JFrameSizeAfterDrag();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

很好的例子,你让我固定的代码加入MouseAdapter其中覆盖mouseReleased(..)它调用resizePanel(...)mouseReleased(..)

在这里看到的固定码(也动如增加了一些小事情ComponentAdapter,而不是ComponentListenerAbstractAction代替Action):

import java.awt.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

public class JFrameSizeAfterDrag2 extends JFrame {

    private Timer timer;
    private JPanel panel2;
    boolean canResize = true,firstTime = true;


    public JFrameSizeAfterDrag2() {
        super("GradientTranslucentWindow");

        setBackground(new Color(0, 0, 0, 0));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setContentPane(new JPanel(null) {//contentpane layout is null only
            @Override
            protected void paintComponent(Graphics g) {
                Paint p = new GradientPaint(0.0f, 0.0f, new Color(0, 0, 0, 0), 0.0f, getHeight(), new Color(0, 0, 0, 0), true);
                Graphics2D g2d = (Graphics2D) g;
                g2d.setPaint(p);
                g2d.fillRect(0, 0, getWidth(), getHeight());
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
        });

        panel2 = new JPanel();
        panel2.setBackground(Color.black);
        getContentPane().add(panel2);

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent me) {
                super.mouseReleased(me);
                if (canResize) {
                    resizePanel(getContentPane().getSize());
                }
            }
        });

        addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                timer = new Timer(50, new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (timer.isRunning()) {
                            canResize = false;
                        } else {
                            canResize = true;
                            if (firstTime == true) {
                                firstTime = false;
                                resizePanel(getContentPane().getSize());
                            }
                        }
                    }
                });
                timer.setRepeats(false);
                timer.start();

            }
        });
        pack();
    }

    public void resizePanel(Dimension dim) {
        panel2.setBounds(0, 0, dim.width, dim.height);
        revalidate();
    }

    public static void main(String[] args) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        boolean isPerPixelTranslucencySupported = gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);

        if (!isPerPixelTranslucencySupported) {
            System.out.println("Per-pixel translucency is not supported");
            System.exit(0);
        }

        JFrame.setDefaultLookAndFeelDecorated(true);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrameSizeAfterDrag2 gtw = new JFrameSizeAfterDrag2();
                gtw.setVisible(true);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)