学习java gui,想实现一个没有默认标题栏\边框,可以拖动和缩放的窗体.现在我已经实现自定义标题栏/边框,拖动的功能,缩放还有点问题,即:从左上,左下,和右上缩小窗口时会跳动,还会移动窗口位置,不知道怎么解决.(四条边框缩放还未完成,我的思路是,先得到窗体的宽高和屏幕位置,再根据鼠标相对于窗体的位置来调整窗体的屏幕位置和宽高.按照这种思路,在从左上角,左下角,右上角缩小窗体时,由于设置窗体屏幕位置后,还要调整一下窗体的宽高,所以会产生跳动的感觉,我不知道这种思路有没有问题,所以没有再做下去.)以下是源码,复制运行一下,可以看到效果.
import java.awt.*;
import java.awt.event.*;public class PyWin extends Frame
{
//构造函数
public PyWin(String winname,int width,int height)
{
GridBagConstraints gbc = new GridBagConstraints();
GridBagLayout gbl = new GridBagLayout();
//gbl.columnWidths=
this.setTitle(winname);
this.setUndecorated(true);
this.setSize(width,height);
this.setLayout(gbl);//重要,必须与后面的gbl.setConstraints是同一个对象,否则无法约束其中的组件
this.setBackground(new Color(200,200,100));
//添加改变窗体大小事件监听类
DragWinSize dws = new DragWinSize();
this.addMouseListener(dws);
this.addMouseMotionListener(dws);
//添加主panel
Panel pnl = new Panel();
//设置布局约束
gbc.fill=GridBagConstraints.BOTH;
gbc.weightx=1.0;
gbc.weighty=1.0;
gbc.insets = new Insets(2,2,2,2);
//添加布局约束
gbl.setConstraints(pnl,gbc);
add(pnl);
pnl.setLayout(gbl); //----------标题栏-------------------
gbc.insets = new Insets(0,0,0,0);
gbc.gridx=0;//GridBagConstraints.REMAINDER;
gbc.gridy=0;//GridBagConstraints.RELATIVE;
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.anchor=GridBagConstraints.NORTH;
Panel titlebar = new Panel();//标题栏
gbl.setConstraints(titlebar,gbc);
titlebar.setBackground(new Color(110,210,132));
titlebar.addMouseMotionListener(new MoveWinPos());
pnl.add(titlebar);
//添加标题
titlebar.setLayout(gbl);
Label title = new Label(winname,Label.LEFT);
title.addMouseMotionListener(new MoveWinPos());
gbc.gridx=0;//GridBagConstraints.RELATIVE;
gbc.gridy=0;
gbc.anchor=GridBagConstraints.WEST;
gbc.fill=GridBagConstraints.EAST;
gbl.setConstraints(title,gbc);
titlebar.add(title);
//最小化,最大化,关闭按钮panel
Panel ope = new Panel();
gbc.gridx=1;//GridBagConstraints.RELATIVE;
gbc.gridy=0;
gbc.anchor=GridBagConstraints.EAST;
gbc.fill=GridBagConstraints.WEST;
gbl.setConstraints(ope,gbc);
titlebar.add(ope);
ope.setLayout(new FlowLayout(FlowLayout.RIGHT));
//按钮
Label btnclose = new Label("×");
Label btnmax = new Label("□");
Label btnmin = new Label("-");
ope.add(btnmin);
ope.add(btnmax);
ope.add(btnclose);
//---------正文内容容器------------------
gbc.gridx=0;//GridBagConstraints.REMAINDER;
gbc.gridy=GridBagConstraints.REMAINDER;
gbc.fill=GridBagConstraints.BOTH;
Panel gutpnl = new Panel();//内容容器
gbl.setConstraints(gutpnl,gbc);
gutpnl.setBackground(new Color(210,250,232));
gutpnl.addMouseMotionListener(new MoveWinPos());
pnl.add(gutpnl); } //main
public static void main(String arg[])
{
PyWin myWin=new PyWin("my 2 window",300,300);
myWin.setVisible(true);
}
}
class MoveWinPos implements MouseMotionListener
{
public Point tcpt = null;//鼠标相对于顶层容器的坐标
public Component topc = null;//顶层容器
public Point mspt = new Point();//鼠标的屏幕坐标 //获取顶层容器
private Component getTopComponent(MouseEvent e)
{
Component cp=(Component)e.getSource();
while(cp.getParent()!=null)
{
cp=cp.getParent();
}
return cp;
} //获取鼠标的屏幕坐标
private Point getMspt(MouseEvent e)
{
Point pt1 = ((Component)e.getSource()).getLocationOnScreen();
Point pt2 = e.getPoint();
mspt.x=pt1.x+pt2.x;
mspt.y=pt1.y+pt2.y;
return mspt;
} public void mouseDragged(MouseEvent e)
{
if(topc == null)
{
topc = getTopComponent(e);
}
getMspt(e);
topc.setLocation(mspt.x-tcpt.x,mspt.y-tcpt.y);
} //获取鼠标相对于顶层容器的坐标
public void mouseMoved(MouseEvent e)
{
//获取鼠标相对于顶层容器的坐标
tcpt=e.getPoint();
Component cp=(Component)e.getSource();
cp.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
Rectangle rec=null;
while(cp.getParent()!=null)
{
rec=cp.getBounds();
tcpt.x+=rec.x;
tcpt.y+=rec.y;
cp=cp.getParent();
}
//////////////////////////////
}
}

解决方案 »

  1.   

    接上面的代码://改变窗体大小事件类
    class DragWinSize implements MouseListener,MouseMotionListener
    {
    //判断鼠标位置
    Point bpt = new Point(); //基点
    int direc = 0; //鼠标在窗体上的位置:1左上,2右上,3右下,4左下,5上,6右,7下,8左 public void mouseClicked(MouseEvent e){};
    public void mouseEntered(MouseEvent e){};
    public void mouseExited(MouseEvent e){};
    public void mousePressed(MouseEvent e){};
    public void mouseReleased(MouseEvent e){System.out.println("mouse released:"+direc);}; //获取指定值
    public int getSpecifyInt(int theInt,boolean ope,int dynamicInt)
    {
    if (ope==true)
    {
    if(theInt>dynamicInt){return theInt;}else{return dynamicInt;}
    }
    else
    {
    if(theInt<dynamicInt){return theInt;}else{return dynamicInt;}
    }
    } public void mouseDragged(MouseEvent e)
    {
    Point mpt = e.getPoint(); //鼠标位置
    Frame fram = (Frame)e.getSource();
    Dimension fsize = fram.getSize(); //窗体宽高
    Point ftlpt = fram.getLocationOnScreen(); //窗体左上角屏幕坐标 int mix = fram.getLayout().minimumLayoutSize(fram).width;
    int miy = fram.getLayout().minimumLayoutSize(fram).height; //调整窗口大小
    switch(direc)
    {
    case 1 :
    fram.setLocation(ftlpt.x+mpt.x,ftlpt.y+mpt.y);
    fram.setSize(getSpecifyInt(mix,true,fsize.width-mpt.x),getSpecifyInt(miy,true,fsize.height-mpt.y));
    break;
    case 2 :
    fram.setLocation(ftlpt.x,ftlpt.y+mpt.y);
    fram.setSize(getSpecifyInt(mix,true,mpt.x),getSpecifyInt(miy,true,fsize.height-mpt.y));
    break;
    case 3 :
    fram.setLocation(ftlpt.x,ftlpt.y);
    fram.setSize(getSpecifyInt(mix,true,mpt.x),getSpecifyInt(miy,true,mpt.y));
    break;
    case 4 :
    fram.setLocation(ftlpt.x+mpt.x,ftlpt.y);
    fram.setSize(getSpecifyInt(mix,true,fsize.width-mpt.x),getSpecifyInt(miy,true,mpt.y));
    break;
    case 5 :
    fram.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
    break;
    case 7 :
    fram.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
    break;
    case 6 :
    fram.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
    break;
    case 8 :
    fram.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
    break;
    default:
    fram.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    break;
    }
    ///重要:拖动时,实时调整组件位置大小
    fram.setVisible(true);
    }
    public void mouseMoved(MouseEvent e)
    {
    Point mpt = e.getPoint(); //鼠标位置
    Frame fram = (Frame)e.getSource();
    Dimension fsize = fram.getSize(); //窗体宽高 //判断鼠标是否在窗体边线
    //四个顶点
    if(0<=mpt.x && mpt.x<=10 && 0<=mpt.y && mpt.y<=10)//左上角
    {
    direc=1;bpt.x=fsize.width;bpt.y=fsize.height;
    }
    else if(fsize.width-11<=mpt.x && mpt.x<=fsize.width-1 && 0<=mpt.y && mpt.y<=10)//右上角
    {
    direc=2;bpt.x=0;bpt.y=fsize.height;
    }
    else if(fsize.width-11<=mpt.x && mpt.x<=fsize.width-1 && fsize.height-11<mpt.y && mpt.y<=fsize.height-1)//右下角
    {
    direc=3;bpt.x=0;bpt.y=0;
    }
    else if(0<=mpt.x && mpt.x<=10 && fsize.height-11<=mpt.y && mpt.y<=fsize.height-1)//坐下角
    {
    direc=4;bpt.x=fsize.width;bpt.y=0;
    }
    //四条边线
    else if(0<=mpt.y && mpt.y<=1) //上边线
    {
    direc=5;bpt.x=0;bpt.y=fsize.height;
    }
    else if(fsize.width-2<mpt.x && mpt.x<=fsize.width-1) //右边线
    {
    direc=6;bpt.x=0;bpt.y=0;
    }
    else if((fsize.height-3)<=mpt.y && mpt.y<=(fsize.height-1)) //下边线
    {
    direc=7;bpt.x=0;bpt.y=0;
    }
    else if(0<=mpt.x && mpt.x<=1) //左边线
    {
    direc=8;bpt.x=fsize.width;bpt.y=0;
    }
    else
    {
    direc=0;bpt.x=0;bpt.y=0;
    }
    switch(direc)
    {
    case 1 :
    fram.setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR));
    break;
    case 2 :
    fram.setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR));
    break;
    case 3 :
    fram.setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR));
    break;
    case 4 :
    fram.setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR));
    break;
    case 5 :
    fram.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
    break;
    case 7 :
    fram.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
    break;
    case 6 :
    fram.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
    break;
    case 8 :
    fram.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
    break;
    default:
    fram.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    break;
    }
    }
    }
      

  2.   

    IBM 有个开源的包 叫IFRAME  好像不会闪 具体忘记了 找找看
      

  3.   

    http://download.boulder.ibm.com/ibmdl/pub/software/dw/java/j-iframe.zip他这个拖动 有点延迟 但是不会闪烁 可能是加了XXXms内只改变一次
      

  4.   

    IFrame 第900行  加了Thread.sleep(300); 
    注释掉 效果跟你这个差不多