??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品一区免费在线,9999精品视频,日本高清视频精品http://www.aygfsteel.com/lishen226/zh-cnFri, 20 Jun 2025 00:49:25 GMTFri, 20 Jun 2025 00:49:25 GMT60[转]JAVA Painting-Swing实现U要一http://www.aygfsteel.com/lishen226/archive/2009/10/20/298972.html锋行锋行Tue, 20 Oct 2009 01:58:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/10/20/298972.htmlhttp://www.aygfsteel.com/lishen226/comments/298972.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/10/20/298972.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/298972.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/298972.htmlJAVA Painting-Swing实现U要一
首先推荐<Painting in AWT and Swing>by Amy Fowler?
Sun在JDK 1.0最初发布了(jin)囑ŞAPI?代号AWT (abstract windowing toolkit)Q里面除对GUI基本支持Q如l合各OS的事件分发机制等Q外Q自有一套重量开发GUI的思\Qƈ提供?jin)一l常规用的重量U组件。所谓重量lg是每个lg都引用一个本地对{体peer成员对象Q这个对{体对象利用本地pȝGUI APIl制lg。后来在JDK1.1QAWT包中引进?jin)一套轻量开发GUI的新思\Qƈ提供?jin)一l轻量lg。所谓轻量lg是自n没有本地对等体,而借助重量U组件作为容器来l制lg。JDK 1.1之后Qsun在开发GUI思\上,在效率,扩展性等斚wl出?jin)很多创斎ͼq基于这U新思\推出一套丰富的新组Ӟ轻量U组Ӟ(j)Qsun为此打出一个新的响亮的代号---SwingQƈ推荐以后的GUI开发都应该ZSWING的GUI开发思\开展,应该使用或扩展这套SWING的组件?
不论是AWT模式q是SWING模式QSun的GUI开发思\都是UOO的。开发h员L构徏多个lg对象实例来组合徏立GUIQ这些对象是因不同的输入输出表现被封装ؓ(f)多种lgcȝ实例Q而这些组件类是有合理的承关pd而容易扩展的“套g”。而且两种模式最基本的统一的程序运行思\都是Q?
1Q通过建立各种lg的实例来负责GUI的工作?
2Q?U定出GUI变化时机—java应用E序随需发出h调用或对操作pȝU某U操作的监听Q如暴露被遮挡的H口内容Q?
3. 在时机到来时?#8220;框架E序”来判断ƈ调用应该调用的目标组件实例所提供的各UŞ式的paintҎ(gu)Q各lg在此Ҏ(gu)里通过java 2d API包来实现自己的具体绘刉辑Q来完成各组件绘制?
4. 在GUI的整个生命周期里Q通过以上?23模式来完成整个应用界面的随需而变?
下文主要分析SWING模式?
Swing?开发GUI的基本约定包括:(x)SWING提供4个顶层容器JFrame,JDialog,JApplet,JWindowQ如果是桌面应用Q则GUI必须要有一个JFrameQ如果是览器应用,则GUI必须要有一个JApplet。其他swinglgQ或自定义开发的Swinglg都扩展自JComponentQƈ且其实例要存在于层容器的层ơ树(wi)中。下面是一个符合约定的GUI的运行分析?
import javax.swing.JFrame;
import javax.swing.JLabel;
public class BasicSwing {
public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
private void createAndShowGUI() {
JFrame frame = new JFrame("BasicSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label=new JLabel("hello world");
        frame.getContentPane().add(label);
        frame.setSize(100,200);
        frame.setVisible(true);
}
        });
    }
}
invokeLaterҎ(gu)在执行时首先?x)gq创建getToolkit---pȝ属性awt.toolkitl出?jin)要加蝲的类Q在windowsq_下即为WToolkit。WToolkit在初始化时会(x)启动AWT-WINDOWSU程(setDaemon-true)Q该U程一直负责从win32pȝ中获取底层事件ƈ接挂到EventQueue事g队列中;同时ȀzAWT-ShutdownU程(setDaemon-false)Q该U程一直监是否满_闭GUI的条ӞpeerMap is nullQAWT-WINDOWS is busyQEDT is busyQ,若是则主动要求关闭EDT也就是GUI最l退出(因ؓ(f)GUI环境下只有EDT是非daemonU程Q;WToolkitq有是加蝲sun.java2d.Disposerc,其将在类加蝲初始化时启动Java2D DisposerU程(setDaemon-true, MAX_PRIORITY)Q该U程一直跟t监被废弃的注册记录(WToolkit一个,q有各种peerQ,监测到后执行对应的DisposecL完成相应的资源回收?
invokeLaterҎ(gu)同时?x)创建EventQueue挂在AppContext里,q上向EventQueue提交InvocationEvent以执行上面例子中的RunableQ这导致启动第一个AWT-EventQueue-NU程QEDT-(setDaemon-false)Q?
EDT启动后将一直从EventQueue获取AWTEVENTq行dispatch分发处理Q处理过E中若遇到某些意外或被强制中断都有可能导致EDT熄火Q此时AWT-Shutdown被notify(g)彻底终止AWT的时机是否到来,若不满条g新的EDTQAWT-EventQueue-N+1被启动?
以上徏立v界面GUI的基本运行框架。上qC子的mainU程很快退出,而EDTU程处理InvocationEvent,处理q程x执行Runable.runҎ(gu)体?
在EDT中,JFrame被构造,在其构造过E中Q会(x)q加dispose记录?
(addRecord(JFrame.anchorObject, WindowDisposerRecord(appContext,this));)qJava2D Disposer以在失去引用旉攄口资源?
随后JFrame被setvisibleQ在setvisibleq程中,通过WToolkit createFramePeerQƈ注册在AWT-Shutdown的peerMap中以支持AWT-AutoShutDown机制?
Setvisible中将?j)调用peer.pShow-native代码Q即发送给win32h昄H口Q窗口被打开后awt_windowsU程在eventloop中得到wm_paint消息q行处理Q这是一个异步过E?
awt_windows处理中将有选择地通过RepaintManager加入重画记录区几何区?
RepaintManager. nativeAddDirtyRegioq调度重ȝE单位在EDT中进行绘?
postEvent-InvocationEvent(ProcessingRunnable)QProcessingRunnable随后
在EDT中run时将Ҏ(gu)重画录执行可能的H口内容l制--卛_子组件回调paintq程?
上述是SWING层重量U容器组件的一个绘制场景,可以看到是经由awt-windows eventloopC(jin)底层事g后触发paintl制Q然而对轻量UswinglgQ其paint都是通过java代码中对repaint调用而触发,其会(x)向RepaintManager.addDirtyRegionQ同时scheduleProcessingRunnable。这是整个GUI生命周期内对l制的两U不同的触发方式Q但触发后的处理都是交由RepaintManager?
回过头去看,JFrame被构造的时候就?x)创建root pane, layered pane,content pane, glass pane{?q些没有对等体的轻量USwinglg在构造时都将repaint。虽然在创徏windows对等H口之前q些Swinglg已l在要求l制Q但是RepaintManager能够协调好这个步调(具体x当收到repainth时要判断情况Q像q时的请求因为顶层容器还没有l制则不?x)记录到重画区?j)。所以最l效果就是在peer.pshow的时候只能看C个空H口Q随后底层消息到来后通过paint回调画这些子lgQ最后hello world才显C出来。如果眼好Q能够看有一?#8220;闪烁”?
q是一个最单的swing应用E序的基本运行机制分析,下面再具体分析?
Swing的GUIL由顶层容器组件和轻量Uswinglgl合建立Q顶层容器和其他lg区别主要在于层容器没有自n的paint逻辑?
所有顶层容器都是通过使用底层pȝAPI来绘制对{体的方式进行paintQ自w没有java2d的paint逻辑实现Q对{体L什么样层容器是什么样Q它只是可以控制对等体的一些可配显C属性。所以效果就是比如在windowsq_上画一个jframeQ除在桌面上昄一个窗口还?x)在d栏上昄一个条目。Swing?个顶层容器都是在addNotify时才?x)getToolkit().createPeer(this)QF(tun)rame/Dialog/WindowQ?而addNotifyq不是在构造时被调用,而是在pack/show或setvisibleQ这3个所谓的realizedL(fng)化方法)(j)时被调用。创Z(jin)对等体peer后还要通过peer.pShowQshow/setVisible(true)调用Q调用才?x)要求底层系l进行显C(所以只有pack是不?x)显C窗口的Q。在昄H口后底层消息队列得到通知Q此后随着H口被最化后恢复或被遮盖后恢复{系l操作后同样能从底层消息得到通知Q这时的监听处理有选择地通知lRepaintManager一个重画请求进行窗口内?子组仉甅R?
而轻量swinglg绘制有关的职责都委托给?jin)ui成员对象Qui对象使用JAVA2D API q行l制Qpaint成什么样那就是这个组件的样子。具体就是在构造的时候即要updateUI{setUI(UIManger.getUI(this))}。UIManger?x)根据当前L&F的选择Q根据this.uiClassID来得到ui成员cdƈ建立实例Q以后的paint回调{都推托lui成员cpaintQ这也算是一U策略模式。Setui的过E中除了(jin)保存q个ui实例外,repaint来通知RepaintManagerq行paint回调完成lgl制。轻量swinglg在addNotify时也?x)去创徏对等体getToolkit().createPeer(this)( LightWeightPeer)Q但q个peer的实玎ͼNullComponentPeerQ是个空壛_Q只是作Z个轻量lg的标讎ͼ以后的很多事件处理等都要判断peer是否instance of LightWeightPeer从而能够进行不同处理。同L(fng)Addnotify也不是在构造时被调用,而是在被加入container时被调用?
注意Q构造方法本w就是状态模式的W一状态,所以GUIlg的构造方法里应该要努力完成自n的绘制来W合自己的地位。轻量lg是按这个意义在构造方法里去通知repaintmanagerq行自nl制的,但是层容器却将真正的绘制意图createPeer延迟C(jin)L(fng)Ҏ(gu)里。这是因为首先一个合乎思维的表N辑是先有容器,再将子组件向容器里添加, 所以最层容器L先行构造出来,然后再被一层层地追加轻量子组件。如果最层容器在构造时去L(fng)Q则p求后l的构造都应该在EDT中进行,而且每次add子组仉要导致revalidateQ但若将最层容器的绘制分dgq到L(fng)Ҏ(gu)里,则可以表达是在容器里盛满?jin)要昄的子lg后再一股脑L(fng)l制出来的概念,cM于在q行一ơweb面的完整加?然后注意在具现方法执行后如果要操作组仉在EDT中进行即可,而且层容器提供一个特有的packҎ(gu)Q用来一ơ性对所有子lg验证大小位置q行重布局Qpack之后再showQ这L(fng)一ơ性计展现是最有效率的?
层容器和轻量lg是q样诞生q绘制的Q在此后的生命周期里Q都按事g监听机制完成GUI随需而变Q无论是pȝ事gQ还是因为repaint调用dpost事gQ事件到来后再在EDT中执行监听器里的paintl制。Swing已经提供的顶层容器和轻量U组件因各自的定义已l注册了(jin)各自的paint监听Q开发h员可以再行维护或按此模式开发新lg从而满_用的需要。比如,jbutton默认有mousepress listenerQ在mousepress事g到来后,监听响应中会(x)讄鼠标颜色加深来表C按下,然后再调用repaint要求重画Q随后在EDT中执行jbutton的paint回调Q此时按深颜色绘Ӟ于是一个被按下的效果就出来?jin)?
下面在具体分析各cM件的处理?
对于层容器的受底层事g消息的触发,当得到的通知是因为expose暴露隐藏区(暴露被遮蔽的部分或恢复最化或第一ơ绘制等Q时Q处理过E会(x)涉及(qing)到双~存的处理,卛_果可能,直接使用~存中的旧图像信息进行覆盖而不再重新绘制?
所谓双~存机制是将一整片的显C内Ҏ(gu)时写入一张内存空间里Q然后一ơ性内存拷入显C区来进行显C,q样处理是因为如果直接写入显C区Q随着昄该写入线E逐渐写入Q可能经历多ơ屏q刷斎ͼD每次h都Ş成过E图像,lh眼造成闪烁感觉Q同时一个副收益是可以针对每个H口都做~存待用Q而不仅仅是针对一个屏q双~存Q,当窗口被遮挡的部分重现时直接拯~存来覆盖,不用再执行绘画逻辑Q提高了(jin)效率?
现在的OS一般都提供双缓存机制支持,如果底层pȝ自n支持以每个窗口ؓ(f)单位做双~存Q则该expose消息被本地处理Q不需要通知q行子组件的l制Q如果底层不支持Q则该消息会(x)到达wcomponetpeer.handleexpose中进行回调处理,此时swing机制下有一个参数控制的双缓存机制可以提供。这里的参数控制需要从RepaintManager的构造过E说赗?
首先RepaintManager可以通过static setCurrentManager(SomeCurrentManager)来进行全局指定。默认情况用currentRepaintManager(){new RepaintManager(BUFFER_STRATEGY_TYPE)}得到一个gq创建的单例。RepaintManager有一D静态类初始化过E,涉及(qing)到双~存讄Q?
static {
nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
                    new GetPropertyAction("awt.nativeDoubleBuffering")));//JVM的启动参数控Ӟ默认false
        String bs = AccessController.doPrivileged(
                          new GetPropertyAction("swing.bufferPerWindow"));//是否每窗口缓存?
        if (headless) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
        else if (bs == null) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_NOT_SPECIFIED;
        }
        else if ("true".equals(bs)) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_ON;
        }
        else {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
}
private RepaintManager(short bufferStrategyType) {
        // If native doublebuffering is being used, do NOT use
        // Swing doublebuffering.
        doubleBufferingEnabled = !nativeDoubleBuffering;

this.bufferStrategyType = bufferStrategyType;

}
public void setDoubleBufferingEnabled(boolean aFlag) {
        doubleBufferingEnabled = aFlag;

doubleBufferingEnabledQ开启双~存Q,nativeDoubleBufferingQ利用本地双~存机制Q,bufferStrategyTypeQ每H口双缓存策略)(j)
q几个参数将影响到RepaintManager的成员对象paintManager的选择Q也是一个策略模式,该paintManager是负责绘制的核心(j)cR?
private synchronized PaintManager getPaintManager() {
        if (paintManager == null) {
            PaintManager paintManager = null;
            if (doubleBufferingEnabled && !nativeDoubleBuffering) {
                switch (bufferStrategyType) {
                case BUFFER_STRATEGY_NOT_SPECIFIED:
                    if (((SunToolkit)Toolkit.getDefaultToolkit()).
                                                useBufferPerWindow()) {//windows下是否禁用vista dwm,在没有声明bufferPerWindow的情况下由windowspȝҎ(gu)确定paintmanager?
                        paintManager = new BufferStrategyPaintManager();
                    }
                    break;
                case BUFFER_STRATEGY_SPECIFIED_ON:
                    paintManager = new BufferStrategyPaintManager();
                    break;
                default:
                    break;
                }
            }
            // null case handled in setPaintManager
            setPaintManager(paintManager);
        }
        return paintManager;
    }
void setPaintManager(PaintManager paintManager) {
        if (paintManager == null) {
            paintManager = new PaintManager();
        }

}
回到上文Q当handleexposeӞ通过getPaintEventDispatcher 来createPaintEventQ在UIManager.initializeҎ(gu)RepaintManager.HANDLE_TOP_LEVEL_PAINTQ属性swing.handleTopLevelPaintQ确定是SwingPaintEventDispatcherq是直接使用PaintEventDispatcher?
若ؓ(f)false,在PaintEventDispatcher中,直接创建PaintEvent-PAINT提交Q此后该事gl合q后由wcomponentpeer.handleEventQ该处理通过一个自w维护的paintArea几何脏区域进行重d域优化,最l委托给C(j)ontainerq行子组件绘Ӟq是非SWING模式-即AWT模式Q没有双~存的概c(din)?
补充Q在Swing和它的RepainManager出现以前QGUI的模?AWT模式L要先形成一个PaintEventQ触发可能来自底层消?PAINTcdQ也可能来自repaint-UPDATEcdQ,postlEventQueueQƈl织一ơ合qӞ(x)
public abstract class WComponentPeer{
void handlePaint(int x, int y, int w, int h) {
    System.out.println("handlePaint>>>"+x+":"+y+":"+w+":"+h);
        postPaintIfNecessary(x, y, w, h);
    }

    private void postPaintIfNecessary(int x, int y, int w, int h) {
        if ( !ComponentAccessor.getIgnoreRepaint( (Component) target) ) {
            PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
                createPaintEvent((Component)target, x, y, w, h);
            if (event != null) {
                postEvent(event);
            }
        }
}
public class PaintEventDispatcher {
public PaintEvent createPaintEvent(Component target, int x, int y, int w,
                                       int h) {

        return new PaintEvent((Component)target, PaintEvent.PAINT,
                              new Rectangle(x, y, w, h));
    }

public abstract class Component{
public void repaint(long tm, int x, int y, int width, int height) {
        if (this.peer instanceof LightweightPeer) {
                ~~~
                parent.repaint(tm, px, py, pwidth, pheight);
            }
        } else {
            if (isVisible() && (this.peer != null) &&
                (width > 0) && (height > 0)) {
                PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
                                              new Rectangle(x, y, width, height));
                Toolkit.getEventQueue().postEvent(e);
            }
        }
}

public class EventQueue{
private void postEvent(AWTEvent theEvent, int priority) {
        if (coalesceEvent(theEvent, priority)) {//post之前L需要合q?
            return;
        }


private boolean coalesceEvent(AWTEvent e, int priority) {

        if (e instanceof PaintEvent) {
            return coalescePaintEvent((PaintEvent)e);//对painteventq行一轮合q处理,D同一重量U组件的多次paintevent被合qؓ(f)一个paintevent{待dispatch。以提高效率
        }

然后EDT中在Component.dispatchImpl中委托给wcomponentpeer处理?

public abstract class Component{

dispatchEventImpl{
/*
         * 9. Allow the peer to process the event.
         * Except KeyEvents,
         */
            if (tpeer != null) {
                tpeer.handleEvent(e);
            }
       

public abstract class WComponentPeer{

public void handleEvent(AWTEvent e) {

switch(id) {
            case PaintEvent.PAINT:
                // Got native painting
                paintPending = false;
                // Fallthrough to next statement
            case PaintEvent.UPDATE:
                // Skip all painting while layouting and all UPDATEs
                // while waiting for native paint
                if (!isLayouting && ! paintPending) {
                    paintArea.paint(target,shouldClearRectBeforePaint());
                }
                return;
            default:
            break;
        }

Peer处理q程中将利用自nl护的PaintAreaq行重画区域的优化,q执行子lgpaint回调?
/**
     * Invokes paint and update on target Component with optimal
     * rectangular clip region.
     * If PAINT bounding rectangle is less than
     * MAX_BENEFIT_RATIO times the benefit, then the vertical and horizontal unions are
     * painted separately.  Otherwise the entire bounding rectangle is painted.
     *
     * @param   target Component to <code>paint</code> or <code>update</code>
     * @since   1.4
     */
    public void paint(Object target, boolean shouldClearRectBeforePaint) {
        Component comp = (Component)target;
~~~
        if (ra.paintRects[HORIZONTAL] != null && ra.paintRects[VERTICAL] != null) {
            Rectangle paintRect = ra.paintRects[HORIZONTAL].union(ra.paintRects[VERTICAL]);
            int square = paintRect.width * paintRect.height;
            int benefit = square - ra.paintRects[HORIZONTAL].width
                * ra.paintRects[HORIZONTAL].height - ra.paintRects[VERTICAL].width
                * ra.paintRects[VERTICAL].height;
            // if benefit is comparable with bounding box
            if (MAX_BENEFIT_RATIO * benefit < square) {
                ra.paintRects[HORIZONTAL] = paintRect;
                ra.paintRects[VERTICAL] = null;
            }
        }
        for (int i = 0; i < paintRects.length; i++) {
            if (ra.paintRects[i] != null
                && !ra.paintRects[i].isEmpty())
            {
                // Should use separate Graphics for each paint() call,
                // since paint() can change Graphics state for next call.
                Graphics g = comp.getGraphics();
                if (g != null) {
                    try {
                        g.setClip(ra.paintRects[i]);
                        if (i == UPDATE) {
                            updateComponent(comp, g);
                        } else {
                            if (shouldClearRectBeforePaint) {
                                g.clearRect( ra.paintRects[i].x,
                                             ra.paintRects[i].y,
                                             ra.paintRects[i].width,
                                             ra.paintRects[i].height);
                            }
                            paintComponent(comp, g);
                        }
                    } finally {
                        g.dispose();
                    }
                }
            }
        }
    }
若ؓ(f)true,在SwingPaintEventDispatcher.createPaintEventQ?
if (component instanceof RootPaneContainer) {//如果是顶层容?
            AppContext appContext = SunToolkit.targetToAppContext(component);
            RepaintManager rm = RepaintManager.currentManager(appContext);
            if (!SHOW_FROM_DOUBLE_BUFFER ||//参数swing.showFromDoubleBuffer控制Q默认true定swing//是否?x)考虑双缓存支?
                  !rm.show((Container)component, x, y, w, h)) {
                rm.nativeAddDirtyRegion(appContext, (Container)component,
                                        x, y, w, h);
            }
return new IgnorePaintEvent(component, PaintEvent.PAINT,
                                        new Rectangle(x, y, w, h));//q回一个将被忽略的假事件提?

如果SHOW_FROM_DOUBLE_BUFFER 考虑双缓存支持,进行rm.showQ其交给getPaintManager().showQ这时的paintmanager是经q了(jin)前面所说的几个参数选择的,也就是说Q考虑当前是否当前正能双~存doubleBufferingEnabledQ是否不使用本地双缓存nativeDoubleBufferingQ?BUFFER_STRATEGY_TYPE是否指定?jin)每H口~存的双~存支持{略Q如果没有指定策略是否或本地windowspȝ环境没有开启vista dwm效果Q如果都满用BufferStrategyPaintManagerQ借由swing提供每窗口双~存机制Q检查swing记录中是否具有有效缓存,若存在则?x)要求该区直接拷贝flip卛_Q如果没有成功执行双~存拯Q则加入Repaintmanager重画区域q行swing模式的重甅R?
层容器除了(jin)在对{体发过消息后处理paintQ也h自己的repaintҎ(gu)M动创造绘L机?
public void repaint(long time, int x, int y, int width, int height) {
       if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {//属性swing.handleTopLevelPaint定Q默认true
            RepaintManager.currentManager(this).addDirtyRegion(
                              this, x, y, width, height);
        }
        else {
            super.repaint(time, x, y, width, height);
        }
    }
q里的repaint首先确定RepaintManager.HANDLE_TOP_LEVEL_PAINT-如果不支持将委托lC(j)omponent.repaintQŞ成PaintEventq进行提交走AWT模式。支持的话将?j)RepaintManager加入重画区后通过调度走SWING模式。SWING模式是走RepaintManager的方式。自w的repaint不会(x)去考虑每窗口双~存直接拯区域Q因时的需求就是要求重新绘甅R?
轻量Uswinglg在自qrepaintҎ(gu)M动创造绘L机?
JComponent.Repaint{RepaintManager.currentManager(this).addDirtyRegion}走SWING模式处理?
SWING模式都是借由RepaintManager来安排绘画,它维护了(jin)一个几何区域ƈ负责重画的框架。外界L要求先加入RepaintManager重绘区,在加入的同时Ȁ发v一个调度重ȝ
SunToolkit.getSystemEventQueueImplPP(context).
                postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
                                              processingRunnable))

InvocationEvent?
注意Q通过上文分析Q对于顶层容器处理底层消息的触发Ӟ走swing处理模式而通过swingpaintEventdispatcherd建painitevent旉向repaintmanager登记脏区Q如果不使用每窗口双~存{略Q外Q还要额外post一个IgnorePaintEvent。该paintevent在随后的EDT里按awt模式走peer处理时ƈ没有加入awt的重画脏区,实际上忽略掉?jin)绘制意义,q样做避免了(jin)在swing和awt两种模式的重复绘Ӟ但同时Ş成依然将paint事g通知到组件的效果?
public void coalescePaintEvent(PaintEvent e) {
        Rectangle r = e.getUpdateRect();
        if (!(e instanceof IgnorePaintEvent)) {
            paintArea.add(r, e.getID());
        }



锋行 2009-10-20 09:58 发表评论
]]>
[转]Swing中的多线E?/title><link>http://www.aygfsteel.com/lishen226/archive/2009/10/20/298965.html</link><dc:creator>锋行</dc:creator><author>锋行</author><pubDate>Tue, 20 Oct 2009 01:49:00 GMT</pubDate><guid>http://www.aygfsteel.com/lishen226/archive/2009/10/20/298965.html</guid><wfw:comment>http://www.aygfsteel.com/lishen226/comments/298965.html</wfw:comment><comments>http://www.aygfsteel.com/lishen226/archive/2009/10/20/298965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/lishen226/comments/commentRss/298965.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/lishen226/services/trackbacks/298965.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">Swing中的多线E?br /> 关键? swing中的多线E?<br /> 本文关于Swing中的多线E,发表?998q?月。一个月后,我们发表?jin)另一文章《用Swing WorkerU程》,该文更深入地讨论?jin)这一主题。要更好C(jin)解多U程在Swing中如何工作,我们你把q两文章都看一下?<br /> 注意Q在2000q?月我们修改了(jin)q篇文章和它的例子以适用于一个更新版本的SwingWorkercRSwingWorkercȝq个版本修正?jin)一些微妙的U程bug?</font></p> <p><font style="background-color: #cce8cf">Swing API的设计目标是强大、灵zd易用。特别地Q我们希望能让程序员们方便地建立新的SwinglgQ不论是从头开始还是通过扩展我们所提供的一些组件?<br /> Zq个目的Q我们不要求Swinglg支持多线E访问。相反,我们向组件发送请求ƈ在单一U程中执行请求?<br /> 本文讨论U程和Swinglg。目的不仅是Z(jin)帮助你以U程安全的方式用Swing APIQ而且解释?jin)我们?f)什么会(x)选择现在q样的线E方案?<br /> 本文包括以下内容Q?</font></p> <p><font style="background-color: #cce8cf">单线E规则:(x)SwingU程在同一时刻仅能被一个线E所讉K。一般来_(d)q个U程是事件派发线E(event-dispatching threadQ?</font></p> <p><font style="background-color: #cce8cf">规则的例外:(x)有些操作保证是线E安全的?<br /> 事g分发Q如果你需要从事g处理Qevent-handlingQ或l制代码以外的地方访问UIQ那么你可以使用SwingUtilitiescȝinvokeLater()或invokeAndWait()Ҏ(gu)?</font></p> <p><font style="background-color: #cce8cf">创徏U程Q如果你需要创Z个线E――比如用来处理一些耗费大量计算能力或受I/O能力限制的工作――你可以使用一个线E工L(fng)如SwingWorker或Timer?</font></p> <p><font style="background-color: #cce8cf">Z么我们这样实现SwingQ我们用一些关于Swing的线E安全的背景资料来结束这文章?</font></p> <p><font style="background-color: #cce8cf">Swing的规则是Q?<br /> 一旦Swinglg被具现化QrealizedQ,所有可能媄(jing)响或依赖于组件状态的代码都应该在事gz֏U程中执行?</font></p> <p><font style="background-color: #cce8cf">q个规则可能听v来有点吓人,但对许多单的E序来说Q你用不着为线E问题操?j)。在我们深入如何撰写Swing代码之前Q让我们先来定义两个术语Q具现化QrealizedQ和事gz֏U程Qevent-dispatching threadQ?<br /> L(fng)化的意思是l徏的paint()Ҏ(gu)已经或可能会(x)被调用。一个作为顶U窗口的Swinglg当调用以下方法时被L(fng)化:(x)setVisible(true)、show()或(可能令你惊奇Qpack()。当一个窗口被L(fng)化,它包含的所有组仉被具现化。另一个具现化一个组件的Ҏ(gu)是将它放入到一个已l具现化的容器中。稍后你?x)看C些对lgL(fng)化的例子?<br /> 事gz֏U程是执行绘制和事g处理的线E。例如,paint()和actionPerformed()Ҏ(gu)?x)自动在事gz֏U程中执行。另一个将代码攑ֈ事gz֏U程中执行的Ҏ(gu)是用SwingUtilitiescȝinvokeLater()Ҏ(gu)?<br /> 所有可能媄(jing)响一个已L(fng)化的Swinglg的代码都必须在事件派发线E中执行。但q个规则有一些例外:(x) </font></p> <p><font style="background-color: #cce8cf">有些Ҏ(gu)是线E安全的Q在Swing API的文档中Q线E安全的Ҏ(gu)用以下文字标讎ͼ(x) <br /> This method is thread safe, although most Swing methods are not. <br /> Q这个方法是U程安全的,管大多数SwingҎ(gu)都不是。)(j) </font></p> <p><font style="background-color: #cce8cf">一个应用程序的GUI常常可以在主U程中构建和昄Q下面的典型代码是安全的Q只要没有(Swing或其他)(j)lg被具现化Q?</font></p> <font style="background-color: #cce8cf"> <p><br /> public class MyApplication { <br /> public static void main(String[] args) { <br />    JFrame f = new JFrame("Labels"); <br />    // 在这里将各组?nbsp; <br />    // 加入C框架……  <br />    f.pack();  <br />    f.show();  <br />    // 不要再做MGUI工作……  <br />    }  <br /> } </p> <p>上面所C的代码全部?#8220;main”U程中运行。对f.pack()的调用得JFrame以下的组仉被具现化。这意味着Qf.show()调用是不安全的且应该在事件派发线E中执行。尽如此,只要E序q没有一个看得到的GUIQJFrame或它的里面的lg几乎不可能在f.show()q回前收C个paint()调用。因为在f.show()调用之后不再有Q何GUI代码Q于是所有GUI工作都从ȝE{C(jin)事gz֏U程Q因此前面所讨论的代码实际上是线E安全的?</p> <p>一个applet的GUI可以在init()Ҏ(gu)中构造和昄Q现有的览器都不会(x)在一个applet的init()和start()Ҏ(gu)被调用前l制它。因而,在一个applet的init()Ҏ(gu)中构造GUI是安全的Q只要你不对applet中的对象调用show()或setVisible(true)Ҏ(gu)?<br /> 要顺便一提的是,如果applet中用了(jin)SwinglgQ就必须实现为JApplet的子cRƈ且,lg应该d到的JApplet内容H格Qcontent paneQ中Q而不要直接添加到JApplet。对MappletQ你都不应该在init()或start()Ҏ(gu)中执行费时的初始化操作;而应该启动一个线E来执行Ҏ(gu)的Q务?</p> <p>下述JComponentҎ(gu)是安全的Q可以从MU程调用Qrepaint()、revalidate()、和invalidate()。repaint()和revalidate()Ҏ(gu)Z件派发线E对h排队Qƈ分别调用paint()和validate()Ҏ(gu)。invalidate()Ҏ(gu)只在需要确认时标记一个组件和它的所有直接祖先?</p> <p>监听者列表可以由MU程修改Q调用addListenerTypeListener()和removeListenerTypeListener()Ҏ(gu)L安全的。对监听者列表的d/删除操作不会(x)对进行中的事件派发有M影响?</p> <p>注意Qrevalidate()和旧的validate()Ҏ(gu)之间的重要区别是Qrevalidate()?x)缓存请求ƈl合成一ơvalidate()调用。这和repaint()~存q组合绘制请求类伹{?<br /> 大多数初始化后的GUI工作自然地发生在事gz֏U程。一旦GUI成ؓ(f)可见Q大多数E序都是׃仉动的Q如按钮动作或鼠标点击,q些L在事件派发线E中处理的?<br /> 不过QL些程序需要在GUI成ؓ(f)可见后执行一些非事g驱动的GUI工作。比如:(x) </p> <p>在成为可用前需要进行长旉初始化操作的E序Q这cȝ序通常应该在初始化期间显C出GUIQ然后更新或改变GUI。初始化q程不应该在事gz֏U程中进行;否则Q重l组件和事gz֏?x)停止。尽如此,在初始化之后QGUI的更?改变q是应该在事件派发线E中q行Q理由是U程安全?</p> <p>必须响应非AWT事g来更新GUI的程序:(x)例如Q想象一个服务器E序从可能运行在其他机器上的E序得到h。这些请求可能在M时刻到达Qƈ且会(x)引v在一些可能未知的U程中对服务器的Ҏ(gu)调用。这个方法调用怎样更新GUI呢?在事件派发线E中执行GUI更新代码?</p> <p>SwingUtilitiescL供了(jin)两个Ҏ(gu)来帮助你在事件派发线E中执行代码Q?</p> <p>invokeLater()Q要求在事gz֏U程中执行某些代码。这个方法会(x)立即q回Q不?x)等待代码执行完毕?</p> <p>invokeAndWait()Q行ZinvokeLater()cMQ除?jin)这个方法?x){待代码执行完毕。一般地Q你可以用invokeLater()来代替这个方法?</p> <p><br /> 下面是一些用这几个API的例子。请同时参阅《The Java Tutorial》中?#8220;BINGO example”Q尤其是以下几个c:(x)CardWindow、ControlPane、Player和OverallStatusPane?</p> <p>使用invokeLater()Ҏ(gu) </p> <p>你可以从MU程调用invokeLater()Ҏ(gu)以请求事件派发线E运行特定代码。你必须把要q行的代码放C个Runnable对象的run()Ҏ(gu)中,q将此Runnable对象设ؓ(f)invokeLater()的参数。invokeLater()Ҏ(gu)?x)立卌回,不等待事件派发线E执行指定代码。这是一个用invokeLater()Ҏ(gu)的例子:(x) </p> <p><br /> Runnable doWorkRunnable = new Runnable() { <br />     public void run() { doWork(); } <br /> }; <br /> SwingUtilities.invokeLater(doWorkRunnable); </p> <p><br /> 使用invokeAndWait()Ҏ(gu) </p> <p>invokeAndWait()Ҏ(gu)和invokeLater()Ҏ(gu)很相|除了(jin)invokeAndWait()Ҏ(gu)?x)等事gz֏U程执行?jin)指定代码才q回。在可能的情况下Q你应该量用invokeLater()来代替invokeAndWait()。如果你真的要用invokeAndWait()Q请保调用invokeAndWait()的线E不?x)在调用期间持有M其他U程可能需要的锁?<br /> q是一个用invokeAndWait()的例子:(x) </p> <p><br /> void showHelloThereDialog()  <br />         throws Exception { <br />     Runnable showModalDialog = new  <br />       Runnable() { <br />         public void run() { <br />             JOptionPane.showMessageDialog( <br />                myMainFrame, "Hello There"); <br />         } <br />     }; <br />     SwingUtilities.invokeAndWait <br />        (showModalDialog); <br /> } </p> <p>cM圎ͼ假设一个线E需要对GUI的状态进行存取,比如文本域的内容Q它的代码可能类DP(x) </p> <p><br /> void printTextField() throws Exception { <br />     final String[] myStrings =  <br />        new String[2]; </p> <p>    Runnable getTextFieldText =  <br />       new Runnable() { <br />         public void run() { <br />             myStrings[0] =  <br />                textField0.getText(); <br />             myStrings[1] =  <br />                textField1.getText(); <br />         } <br />     }; <br />     SwingUtilities.invokeAndWait <br />       (getTextFieldText); </p> <p>    System.out.println(myStrings[0]  <br />                        + " " + myStrings[1]); <br /> } </p> <p>如果你能避免使用U程Q最好这样做。线E可能难于用,q得程序的debug更困难。一般来_(d)对于严格意义下的GUI工作Q线E是不必要的Q比如对lg属性的更新?<br /> 不管怎么_(d)有时候线E是必要的。下列情冉|使用U程的一些典型情况:(x) </p> <p>执行一费时的d而不必将事gz֏U程锁定。例子包括执行大量计的情况Q会(x)D大量c被装蝲的情况(如初始化Q,和ؓ(f)|络或磁盘I(y)/O而阻塞的情况?</p> <p>重复地执行一Ҏ(gu)作,通常在两ơ操作间间隔一个预定的旉周期?</p> <p>要等待来自客L(fng)消息?</p> <p>你可以用两个类来帮助你实现U程Q?</p> <p>SwingWorkerQ创Z个后台线E来执行Ҏ(gu)的操作?</p> <p>TimerQ创Z个线E来执行或多ơ执行某些代码,在两ơ执行间间隔用户定义的gq?</p> <p><br /> 使用SwingWorkerc?</p> <p>SwingWorkercdSwingWorker.java中实玎ͼq个cdƈ不包含在Java的Q何发行版中,所以你必须单独下蝲它?<br /> SwingWorkercd?jin)所有实C个后台线E所需的肮脏工作。虽然许多程序都不需要后台线E,后台U程在执行费时的操作时仍然是很有用的Q它能提高程序的性能观感?<br /> SwingWorker's get() method. Here's an example of using SwingWorker: <br /> 要用SwingWorkerc,你首先要实现它的一个子cR在子类中,你必d现construct()Ҏ(gu)q包含你的长旉操作。当你实例化SwingWorker的子cLQSwingWorker创徏一个线E但q不启动它。你要调用你的SwingWorker对象的start()Ҏ(gu)来启动线E,然后start()Ҏ(gu)?x)调用你的construct()Ҏ(gu)。当你需要construct()Ҏ(gu)q回的对象时Q可以调用SwingWorkercȝget()Ҏ(gu)。这是一个用SwingWorkercȝ例子Q?</p> <p><br /> ...// 在mainҎ(gu)中:(x) <br />     final SwingWorker worker =  <br />       new SwingWorker() { <br />         public Object construct() { <br />             return new  <br />                expensiveDialogComponent(); <br />         } <br />     }; <br />     worker.start(); </p> <p>...// 在动作事件处理方法中: <br />     JOptionPane.showMessageDialog <br />         (f, worker.get()); </p> <p>当程序的main()Ҏ(gu)调用start()Ҏ(gu)QSwingWorker启动一个新的线E来实例化ExpensiveDialogComponent。main()Ҏ(gu)q构造了(jin)׃个窗口和一个按钮组成的GUI?<br /> 当用L(fng)?yn)L钮,E序阻塞,如果必要Q阻塞到ExpensiveDialogComponent创徏完成。然后程序显CZ个包含ExpensiveDialogComponent的模式对话框。你可以在MyApplication.java扑ֈ整个E序?</p> <p>使用Timerc?</p> <p>Timerc通过一个ActionListener来执行或多次执行一Ҏ(gu)作。你创徏定时器的时候可以指定操作执行的频率Qƈ且你可以指定定时器的动作事g的监听者(action listenerQ。启动定时器后,动作监听者的actionPerformed()Ҏ(gu)?x)被Q多ơ)(j)调用来执行操作?<br /> 定时器动作监听者(action listenerQ定义的actionPerformed()Ҏ(gu)在事gz֏U程中调用。这意味着你不必在其中使用invokeLater()Ҏ(gu)?<br /> q是一个用TimercL实现动画循环的例子:(x) </p> <p><br /> public class AnimatorApplicationTimer  <br />   extends JFrame implements  <br />   ActionListener { <br />     ...//在这里定义实例变?<br />     Timer timer; </p> <p>    public AnimatorApplicationTimer(...) { <br />         ... <br />         // 创徏一个定时器?nbsp;  <br />         // 来调用此对象action handler?<br />         timer = new Timer(delay, this); <br />         timer.setInitialDelay(0); <br />         timer.setCoalesce(true); <br />         ... <br />     } </p> <p>    public void startAnimation() { <br />         if (frozen) { <br />             // 什么都不做。应用户要求  <br />             // 停止变换囑փ?<br />         } else { <br />             // 启动Q或重启动)(j)动画Q?<br />             timer.start(); <br />         } <br />     } </p> <p>    public void stopAnimation() { <br />         // 停止动画U程?<br />         timer.stop(); <br />     } </p> <p>    public void actionPerformed <br />       (ActionEvent e) { <br />         // q到下一帧动甅R?<br />         frameNumber++; </p> <p>        // 昄?<br />         repaint(); <br />     } <br />     ... <br /> } </p> <p>在一个线E中执行所有的用户界面代码有这样一些优点:(x) </p> <p>lg开发者不必对U程~程有深入的理解Q像ViewPoint和Trestleq类工具包中的所有组仉必须完全支持多线E访问,使得扩展非常困难Q尤其对不精通线E编E的开发者来说。最q的一些工具包如SubArctic和IFCQ都采用和SwingcM的设计?</p> <p>事g以可预知的次序派发:(x)invokeLater()排队的runnable对象从鼠标和键盘事g、定时器事g、绘制请求的同一个队列派发。在一些组件完全支持多U程讉K的工具包中,lg的改变被变化无常的线E调度程序穿插到事g处理q程中。这使得全面试变得困难甚至不可能?</p> <p>更低的代P(x)试心(j)锁住临界区的工具包要p实的时间和I间在锁的管理上。每当工具包中调用某个可能在客户代码中实现的Ҏ(gu)Ӟ如publiccM的Q何public和protectedҎ(gu)Q,工具包都要保存它的状态ƈ释放所有锁Q以便客户代码能在必要时获得锁。当控制权交回到工具包,工具包又必须重新抓住它的锁ƈ恢复状态。所有应用程序都不得不负担这一代h(hun)Q即使大多数应用E序q不需要对GUI的ƈ发访问?</p> <p>q是的SubArctic Java Toolkit的作者对在工具包中支持多U程讉K的问题的描述Q?<br /> 我们的基本信条是Q当设计和徏造多U程应用E序Q尤其是那些包括GUIlg的应用程序时Q必M证极端小?j)。线E的使用可能?x)很有欺骗性。在许多情况下,它们表现得能够极好的化编成,使得设计“专注于单一d的简单自d?#8221;成ؓ(f)可能。在一些情况下它们的确化了(jin)设计和编码。然而,在几乎所有的情况下,它们都得调试、测试和l护的困隑֤大增加甚xZ可能。无论大多数E序员所受的训练、他们的l验和实践,q是我们用来帮助自己的工P都不是能够用来对付非军_论的。例如,全面试Q这L困难的)(j)在bug依赖于时间时是几乎不可能的。尤其对于Java来说Q一个程序要q行在许多不同类型的机器的操作系l^CQƈ且每个程序都必须在抢先和非抢先式调度下都能正常工作?<br /> ׃q些固有的困难,我们力劝你三思是否绝Ҏ(gu)使用U程的必要。尽如此,有些情况下用线E是必要的(或者是被其他Y件包强加的)(j)Q所以subArctic提供?jin)一个线E安全的讉K机制。本章讨Z(jin)q一机制和怎样在一个独立线E中安全地操作交互树(wi)?<br /> 他们所说的U程安全机制非常cM于SwingUtilitiescL供的invokeLater()和invokeAndWait()Ҏ(gu)?/font></p> <img src ="http://www.aygfsteel.com/lishen226/aggbug/298965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/lishen226/" target="_blank">锋行</a> 2009-10-20 09:49 <a href="http://www.aygfsteel.com/lishen226/archive/2009/10/20/298965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Swing学习(fn)W记之swing渲染基本原理http://www.aygfsteel.com/lishen226/archive/2009/10/20/298927.html锋行锋行Tue, 20 Oct 2009 01:26:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/10/20/298927.htmlhttp://www.aygfsteel.com/lishen226/comments/298927.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/10/20/298927.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/298927.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/298927.htmlSwing学习(fn)W记之swing渲染基本原理

主要内容Q事Ӟl制Q渲染,双缓ԌU程

 

一?事g

 

1、事件来源:(x)本地pȝQ应用程序本w?/font>

2、所有的事g都存储在一个队列里?/font>

3、Java.awt.EventQueue从队列中取数据ƈz֏QEventQueue的派发机制由单独的线EEDTQEvent Dispatch ThreadQ处理?/font>

 

二、绘?/font>

 

1、绘制请求发P(x)awt或者swing本n、对swing发vh

2、异步重l请求:(x)所有异步请求都是repaint()的变体,包括整个l徏的绘制和l徏某个区域的绘?/font>

3、同步绘制请求:(x)Jcomponent.paintImmediately()和Component.paint()

 

三、渲?/font>

 

1、画家算?/font>

2、paintComponent()

3、paint()

4、setpaque()

 

四、双~冲

 

五、线E?/font>

1、swingU程包括Q主U程Q应用程序的L法)(j)Q工具包U程Q扑L(fng)l事Ӟ(j)QEDTQ将扑获的线E派发)(j)

2、线E模型:(x)单一的规则,所以要遵从此规则,量事件让EDTq行z֏?/font>

3、invokeLater()

4、isEventDispatchThread()

5、invokeAndWait

 

六、定时器和事件派?/font>

 

1、java.util.Timer

2、javax.swing.Timer

 

七、SwingWorker

1、done()

2、doInBackground()

3、get

4、process



锋行 2009-10-20 09:26 发表评论
]]>
[转]GridBagLayout和GridBagConstraintshttp://www.aygfsteel.com/lishen226/archive/2009/05/21/271992.html锋行锋行Thu, 21 May 2009 07:34:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/05/21/271992.htmlhttp://www.aygfsteel.com/lishen226/comments/271992.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/05/21/271992.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/271992.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/271992.html自己惛_个小E序Q却在布局上犯?jin)难Q用FlowLayout和BorderLayoutq些功能不够强大Q用GridBagLayout却不?x),只好求助于文档?jin)?/p>

文档对这个布局理器介l很详细Q但是最痛苦的是英文。不q幸好它有实例,l过在网上查阅和推敲实例Q终于对GridBagLayout的用有?jin)一个成型的?jin)解Q拿出来与大家分享?/p>

GridBagLayout是一个灵zȝ布局理器,部g如果惛_入其中需借助GridBagConstraintsQ其中有若干个参敎ͼ解释如下Q?/p>

gridx/gridyQ组件的横纵坐标

gridwidthQ组件所占列敎ͼ也是lg的宽?/p>

gridheightQ组件所占行敎ͼ也是lg的高?/p>

fillQ当lg在其格内而不能撑满其格时Q通过fill的值来讑֮填充方式Q有四个?/p>

ipadxQ?lg间的横向间距

ipadyQ组仉的纵向间?/p>

insetsQ当lg不能填满其格Ӟ通过insets来指定四周(即上下左叻I(j)所留空?/p>

anchorQ同h当组件不能填满其格时Q通过anchor来设|组件的位置Qanchor有两U|l对和相对的值分别有         若干个,文档中有Q可自行查看

weightxQ行的权重,通过q个属性来军_如何分配行的剩余I间

weightyQ列的权重,通过q个属性来军_如何分配列的剩余I间

 

q是文档实用Q用例子来说?/p>

 

 

import java.awt.*;

 import java.util.*;

 import java.applet.Applet;

 

 public class GridBagEx1 extends Applet {

 

     protected void makebutton(String name,

                               GridBagLayout gridbag,

                               GridBagConstraints c) {

         Button button = new Button(name);

         gridbag.setConstraints(button, c);

         add(button);

     }

 

     public void init() {

         GridBagLayout gridbag = new GridBagLayout();

         GridBagConstraints c = new GridBagConstraints();

 

         setFont(new Font("SansSerif", Font.PLAIN, 14));

         setLayout(gridbag);

 

         c.fill = GridBagConstraints.BOTH;

         c.weightx = 1.0;

         makebutton("Button1", gridbag, c);

         makebutton("Button2", gridbag, c);

         makebutton("Button3", gridbag, c);

 

       c.gridwidth = GridBagConstraints.REMAINDER; //end row

         makebutton("Button4", gridbag, c);

 

         c.weightx = 0.0;   //reset to the default

         makebutton("Button5", gridbag, c); //another row

 

    c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row

         makebutton("Button6", gridbag, c);

 

    c.gridwidth = GridBagConstraints.REMAINDER; //end row

         makebutton("Button7", gridbag, c);

 

    c.gridwidth = 1;     //reset to the default

    c.gridheight = 2;

         c.weighty = 1.0;

         makebutton("Button8", gridbag, c);

 

         c.weighty = 0.0;   //reset to the default

    c.gridwidth = GridBagConstraints.REMAINDER; //end row

    c.gridheight = 1;   //reset to the default

         makebutton("Button9", gridbag, c);

         makebutton("Button10", gridbag, c);

 

         setSize(300, 100);

     }

 

     public static void main(String args[]) {

    Frame f = new Frame("GridBag Layout Example");

    GridBagEx1 ex1 = new GridBagEx1();

 

    ex1.init();

 

    f.add("Center", ex1);

    f.pack();

    f.setSize(f.getPreferredSize());

    f.setVisible(true);

     }

 }

 

可以自行q行Q查看其l果

文档对其各个按钮的参数设定解释如下:(x)


Button1, Button2, Button3: weightx = 1.0
Button4: weightx = 1.0, gridwidth = GridBagConstraints.REMAINDER
Button5: gridwidth = GridBagConstraints.REMAINDER
Button6: gridwidth = GridBagConstraints.RELATIVE
Button7: gridwidth = GridBagConstraints.REMAINDER
Button8: gridheight = 2, weighty = 1.0
Button9, Button 10: gridwidth = GridBagConstraints.REMAINDER

 

对照着E序和运行结果,q有其参数设定,我的理解如下Q?

W一行:(x)W一行之所以有四个按钮Q关键点在于Qweightx=1.0Q这样就可以在前边的按钮后l加入按钮,而button4成ؓ(f)行尾是因为其gridwidth = GridBagConstraints.REMAINDERQ这句话p定它是行的末?
W二行:(x)既然W一行都有末了(jin)Q那么再加入按钮的话Q必定是另v一行了(jin)Q这个道理)(j)。此时加入了(jin)button5Q而button5又被讑֮Z(jin)本行的最后一个(gridwidth = GridBagConstraints.REMAINDERQ,加之它又是第二行的第一个按钮,所以第二行只有一个按钮,是button5?
W三行:(x)button6不可避免的成Z(jin)W一个按钮,它被讑֮?jin)gridwidth = GridBagConstraints.RELATIVEQ表明button6要紧挨它前边的那个按钮和最后的那个按钮Q也是说它一定是倒数W二个按钮(为最后一个按钮的出现做好?jin)准备?j)。button7出现?jin),׃有gridwidth = GridBagConstraints.REMAINDERQ它?yu)׃?f)W三行封?jin)口。第三行l束?
W四行:(x)q一行有一个特D的按钮button8Q它的设定ؓ(f)gridheight = 2, weighty = 1.0Q即它占用两行一列(其实q个一列和两行都是相对的)(j)。这一行还没封口,所以后面来的button9加在?jin)这一行,因ؓ(f)它gridwidth = GridBagConstraints.REMAINDERQ所以第四行口?
W五行:(x)q一行button8已经占据?jin)第一个的位置Q因为button8的gridheight=2Q,所以后来的button10加在W二Q同L(fng)于gridwidth = GridBagConstraints.REMAINDERQ第五行口?

要理解GridBagLayoutQ最好从例子的理解开始,呵呵?
|上q有另外几篇介绍它的文章Q大家也可参?
http://blog.163.com/everlee@126/blog/static/263574220089621157826/
http://hi.baidu.com/zml1003/blog/item/43728f6ee02a7bd980cb4afc.html
文章出处QDIY部落(http://www.diybl.com/course/3_program/java/javajs/20090405/164188.html)



锋行 2009-05-21 15:34 发表评论
]]>
[转]困扰?jin)我一天的GridBagLayoutl于解决?jin)?/title><link>http://www.aygfsteel.com/lishen226/archive/2009/05/21/271854.html</link><dc:creator>锋行</dc:creator><author>锋行</author><pubDate>Thu, 21 May 2009 01:30:00 GMT</pubDate><guid>http://www.aygfsteel.com/lishen226/archive/2009/05/21/271854.html</guid><wfw:comment>http://www.aygfsteel.com/lishen226/comments/271854.html</wfw:comment><comments>http://www.aygfsteel.com/lishen226/archive/2009/05/21/271854.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/lishen226/comments/commentRss/271854.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/lishen226/services/trackbacks/271854.html</trackback:ping><description><![CDATA[首先GridBagLayoutq个布局ȝ器类只有一个构造函敎ͼ但是它必dGridBagConstraintsq个它的U束对象一起用来讄lg的大和位置Q?<br /> <br /> 说到q里不得不说GridBagConstraints的几个至关重要的属性fill , anchor, gridx, gridy, weightx, weighty , gridwidth, gridheight , insets ipdax ,ipday <br /> <br /> 首先F(tun)ILL的作用就是当lg的大小于它的显C区域的时候设|是否改变它的大由它的几个帔R值GridBagConstraints.BOTH/NONE/VERTICAL/HORIZONTAL军_Q?<br /> <br /> 接着是gridx,gridyq是lg的放|位|就不用说了(jin) <br /> <br /> gridwidth ,gridheightq是扩大lg的显C区域的大小的一个是水^一个是垂直?<br /> <br /> q有是anchor是组件小于显C区域的时候组件的默认攄位置也就是东南西北中几个属性?<br /> <br /> q有是insets是几个组件的间距它有个构造函数new INSETS(a,b,c,d) 分别是上中下右的间距 <br /> <br /> q有是内部的艰巨ipdax ipday q有weightx weighty用来讄H口变大Ӟ各组件跟着变大的比例,当数字越大,表示lg能得到更多的I间Q默认值皆?。当然还有其它很多小l节 我很懒所以自己去官方的API <div id="wmqeeuq" class="Hir246"></div> <br /> <br /> 你不要看说得q么单但你要深刻体会(x)其中的精髓却不轻易!Q!Q!Q!Q!Q! <br /> <br /> 我自qȝQ当你设|组件的大小的时候务必要讄FILL属性假如不N么Q你怎么讄GRIDWIDTH 和GRIDHEIGHT的值那个组件是肯定不会(x)变的q是默认值给 <br /> <br /> 莫慌啊在x??q有当你讄?jin)FILL为GridBagConstraints.BOTH的话你假如其它的lg不重新改设FILL那肯定水q会(x)随着你的应用E序H口慢慢拉大而变长!所以要记?假如不想被拉大就必须重设它的?<br /> <br /> q有gridwidth 和gridheight官方说的是改变显C区域的大小 但是我自p为应该是长和宽的比例l?<br /> <br /> q有REMAINDER和RELATIVEq两个属性也很重要其中的自己慢慢体会(x)因ؓ(f)用在GridBagConstraints的不同的属性上效果也不同所 <br /> <br /> RELATIVE <br /> 指定此组件ؓ(f)其行或列Qgridwidth、gridheightQ中的倒数W二个组Ӟ或者让此组件紧跟在以前d的组Ӟgridx、gridyQ之?<br /> <br /> REMAINDER <br /> 指定此组件是其行或列中的最后一个组?<br /> <br /> Q( 而且默认拉大H口不会(x)增大昄区域 而且假如讄?gridwidth = GridBagConstraints.REMAINDER那么即讄?jin)WEIGHTX=0.0q个lg和它的左面一个也?x)拉大?<br /> <br /> 其中的好处自׃后设计GUI是就?x)慢慢体会(x)?jin) <br /> <br /> g现在只记得这么多?<br /> <br /> 假如以后惌v?x)写?<br /> <br /> 因ؓ(f)我当初ؓ(f)?jin)这个去BAIDU GOOGLEL遍了(jin)感觉都是些书书上的样 说得不太清楚 <br /> <br /> 所以希望学q个的不要走弯\Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!大家设计GUI做得来漂亮!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q! <br /> <img src ="http://www.aygfsteel.com/lishen226/aggbug/271854.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/lishen226/" target="_blank">锋行</a> 2009-05-21 09:30 <a href="http://www.aygfsteel.com/lishen226/archive/2009/05/21/271854.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]javaq接数据库大?/title><link>http://www.aygfsteel.com/lishen226/archive/2009/05/07/269349.html</link><dc:creator>锋行</dc:creator><author>锋行</author><pubDate>Thu, 07 May 2009 02:25:00 GMT</pubDate><guid>http://www.aygfsteel.com/lishen226/archive/2009/05/07/269349.html</guid><wfw:comment>http://www.aygfsteel.com/lishen226/comments/269349.html</wfw:comment><comments>http://www.aygfsteel.com/lishen226/archive/2009/05/07/269349.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/lishen226/comments/commentRss/269349.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/lishen226/services/trackbacks/269349.html</trackback:ping><description><![CDATA[<p style="border-bottom: 1px dotted; margin: 15px auto; width: 760px" id="blogtitle_fks_085065086094088075093084094095080086086075085082085069" class="g_p_center g_t_wrap g_t_left g_t_20 g_c_pdin c07 brd01"><span style="font-family: '微Y雅黑', '黑体', Arial, Helvetica, Sans-Serif">javaq接数据库大?</span><span id="wmqeeuq" class="g_t_10 c08"> 2008-09-23 14:10</span></p> <div style="width: 760px; margin-bottom: 20px" class="g_p_center g_t_right g_c_pdin g_h_20 c08"> <div id="wmqeeuq" class="g_p_left"><a style="font-size: 12px" id="aBelongClsfks_085065086094088075093084094095080086086075085082085069" class="g_c_ul c05" onclick="NEBlog.gPermaLinkPage.updownMenu.openSameClass('fks_095071081082088064081081074071084081089066080085080', 'java');" href="#">分类Qjava</a> </div> <div>字号Q?<a style="font-size: 12px" id="bigfont" class="g_c_ul c05" onclick="NEBlog.gPermaLinkPage.updownMenu.changeFont('blogtext_fks_085065086094088075093084094095080086086075085082085069', 1);return false;" href="#">?/a><span style="display: none" id="bigfont_off" class="g_t_bold c07">?/span>  <a style="font-size: 12px" id="middlefont" class="g_c_ul c05" onclick="NEBlog.gPermaLinkPage.updownMenu.changeFont('blogtext_fks_085065086094088075093084094095080086086075085082085069', 2);return false;" href="#">?/a><span style="display: none" id="middlefont_off" class="g_t_bold c07">?/span>  <a style="display: none; font-size: 12px" id="smallfont" class="g_c_ul c05" onclick="NEBlog.gPermaLinkPage.updownMenu.changeFont('blogtext_fks_085065086094088075093084094095080086086075085082085069', 3);return false;" href="#">?/a><span style="display: inline" id="smallfont_off" class="g_t_bold c07">?/span> </div> </div> <div id="wmqeeuq" class="g_blog_list"> <div style="width: 760px" id="blogtext_fks_085065086094088075093084094095080086086075085082085069" class="g_t_center g_c_pdin g_p_center c07 content"> <p style="text-indent: 2em">开发中q接数据库的方式有多?可以直接用jdbcq接,也可以配|服务器的连接池.写法也有多种,可以直接写在jsp面?但通常都会(x)写个专用的类,用单态之cȝ设计模式把他装h.但其中的基本q接驱动形式代码是不变的,下面是些CZ代码Q你一定将jdbc的驱动程序放到服务器的类路径里,然后要在数据库里Z个表test,有两个字D|如ؓ(f)test1Qtest2Q可以用下面SQL?</p> <p style="text-indent: 2em">create table test(test1 varchar(20),test2 varchar(20) </p> <p style="text-indent: 2em">然后向这个表写入一条测试纪?</p> <p style="text-indent: 2em">那么现在开始我们的jsp和数据库之旅吧?</p> <p style="text-indent: 2em">一、jspq接Oracle8/8i/9i数据库(用thin模式Q?</p> <p style="text-indent: 2em">testoracle.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); </p> <p style="text-indent: 2em">String url="jdbc:oracle:thin:@localhost:1521:orcl"; </p> <p style="text-indent: 2em">//orclZ的数据库的SID </p> <p style="text-indent: 2em">String user="scott"; </p> <p style="text-indent: 2em">String password="tiger"; </p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url,user,password); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">二、jspq接Sql Server7.0/2000数据?</p> <p style="text-indent: 2em">testsqlserver.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); </p> <p style="text-indent: 2em">String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs"; </p> <p style="text-indent: 2em">//pubsZ的数据库?</p> <p style="text-indent: 2em">String user="sa"; </p> <p style="text-indent: 2em">String password=""; </p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url,user,password); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">三、jspq接DB2数据?</p> <p style="text-indent: 2em">testdb2.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); </p> <p style="text-indent: 2em">String url="jdbc:db2://localhost:5000/sample"; </p> <p style="text-indent: 2em">//sampleZ的数据库?</p> <p style="text-indent: 2em">String user="admin"; </p> <p style="text-indent: 2em">String password=""; </p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url,user,password); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">四、jspq接Informix数据?</p> <p style="text-indent: 2em">testinformix.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("com.informix.jdbc.IfxDriver").newInstance(); </p> <p style="text-indent: 2em">String url = </p> <p style="text-indent: 2em">"jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver; </p> <p style="text-indent: 2em">user=testuser;password=testpassword"; </p> <p style="text-indent: 2em">//testDBZ的数据库?</p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">五、jspq接Sybase数据?</p> <p style="text-indent: 2em">testmysql.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("com.sybase.jdbc.SybDriver").newInstance(); </p> <p style="text-indent: 2em">String url =" jdbc:sybase:Tds:localhost:5007/tsdata"; </p> <p style="text-indent: 2em">//tsdataZ的数据库?</p> <p style="text-indent: 2em">Properties sysProps = System.getProperties(); </p> <p style="text-indent: 2em">SysProps.put("user","userid"); </p> <p style="text-indent: 2em">SysProps.put("password","user_password"); </p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url, SysProps); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">六、jspq接MySQL数据?</p> <p style="text-indent: 2em">testmysql.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("org.gjt.mm.mysql.Driver").newInstance(); </p> <p style="text-indent: 2em">String url ="jdbc:mysql://localhost/softforum?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" </p> <p style="text-indent: 2em">//testDBZ的数据库?</p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">七、jspq接PostgreSQL数据?</p> <p style="text-indent: 2em">testmysql.jsp如下Q?</p> <p style="text-indent: 2em"><%@ page contentType="text/html;charset=gb2312"%> </p> <p style="text-indent: 2em"><%@ page import="java.sql.*"%> </p> <p style="text-indent: 2em"><html> </p> <p style="text-indent: 2em"><body> </p> <p style="text-indent: 2em"><%Class.forName("org.postgresql.Driver").newInstance(); </p> <p style="text-indent: 2em">String url ="jdbc:postgresql://localhost/soft" </p> <p style="text-indent: 2em">//softZ的数据库?</p> <p style="text-indent: 2em">String user="myuser"; </p> <p style="text-indent: 2em">String password="mypassword"; </p> <p style="text-indent: 2em">Connection conn= DriverManager.getConnection(url,user,password); </p> <p style="text-indent: 2em">Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); </p> <p style="text-indent: 2em">String sql="select * from test"; </p> <p style="text-indent: 2em">ResultSet rs=stmt.executeQuery(sql); </p> <p style="text-indent: 2em">while(rs.next()) {%> </p> <p style="text-indent: 2em">(zhn)的W一个字D内容ؓ(f)Q?lt;%=rs.getString(1)%> </p> <p style="text-indent: 2em">(zhn)的W二个字D内容ؓ(f)Q?lt;%=rs.getString(2)%> </p> <p style="text-indent: 2em"><%}%> </p> <p style="text-indent: 2em"><%out.print("数据?**作成功,恭喜?);%> </p> <p style="text-indent: 2em"><%rs.close(); </p> <p style="text-indent: 2em">stmt.close(); </p> <p style="text-indent: 2em">conn.close(); </p> <p style="text-indent: 2em">%> </p> <p style="text-indent: 2em"></body> </p> <p style="text-indent: 2em"></html> </p> <p style="text-indent: 2em">?q接access例子</p> <p style="text-indent: 2em">public class AccessTest {</p> <p style="text-indent: 2em"> public static void main(String args[]) {</p> <p style="text-indent: 2em">  try {</p> <p style="text-indent: 2em">   String strurl = "jdbc:odbc:MS Access Database;DBQ=d:\\books.mdb";</p> <p style="text-indent: 2em">   Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");</p> <p style="text-indent: 2em">   Connection conn = DriverManager.getConnection(strurl, "", "");</p> <p style="text-indent: 2em">   Statement stmt = conn.createStatement();</p> <p style="text-indent: 2em">   ResultSet rs = stmt.executeQuery("select * from books");</p> <p style="text-indent: 2em">   while (rs.next())</p> <p style="text-indent: 2em">   {</p> <p style="text-indent: 2em">    System.out.print(rs.getString(1) + "  ");</p> <p style="text-indent: 2em">    System.out.print(rs.getString(2));</p> <p style="text-indent: 2em">   }</p> <p style="text-indent: 2em">  } catch (Exception e) {</p> <p style="text-indent: 2em">   System.out.println(e);</p> <p style="text-indent: 2em">  }</p> <p style="text-indent: 2em"> }</p> <p style="text-indent: 2em">}</p> </div> 二、JDBCq接MySql方式<br /> <br /> 下面是用JDBCq接MySql的一个小的教E?<br /> <br /> 1、查N动程?br /> <br /> MySQL目前提供的java驱动E序为Connection/JQ可以从MySQL官方|站下蝲Qƈ扑ֈmysql-connector-java-3.0.15-ga-bin.jar文gQ此驱动E序为纯java驱动E序Q不需做其他配|?br /> <br /> 2、动态指定classpath<br /> <br /> 如果需要执行时动态指定classpathQ就在执行时采用Qcp方式。否则将上面?jar文g加入到classpath环境变量中?br /> <br /> 3、加载驱动程?br /> <br /> try{<br /> Class.forName(com.mysql.jdbc.Driver);<br /> System.out.println(Success loading Mysql Driver!);<br /> }catch(Exception e)<br /> {<br /> System.out.println(Error loading Mysql Driver!);<br /> e.printStackTrace();<br /> }<br /> <br /> 4、设|连接的url<br /> <br /> jdbcQmysqlQ?/localhost/databasename[?pa=va][Qpa=va]  <br /> <br /> 三、以下列Z(jin)在用JDBC来连接Oracle数据库时可以使用的一些技?br /> <br /> 1、在客户端Y件开发中使用Thin驱动E序<br /> <br /> 在开发Java软g斚wQOracle的数据库提供?jin)四U类型的驱动E序Q二U用于应用Y件、applets、servlets{客L(fng)软gQ另外二U?用于数据库中的Java存储q程{服务器端Y件。在客户机端软g的开发中Q我们可以选择OCI驱动E序或Thin驱动E序。OCI驱动E序利用Java?地化接口QJNIQ,通过Oracle客户端Y件与数据库进行通讯。Thin驱动E序是纯Java驱动E序Q它直接与数据库q行通讯。ؓ(f)?jin)获得最高的?能,Oracle在客L(fng)软g的开发中使用OCI驱动E序Q这g是正的。但我徏议用Thin驱动E序Q因为通过多次试发现Q在通常情况 下,Thin驱动E序的性能都超q了(jin)OCI驱动E序?br /> <br /> 2、关闭自动提交功能,提高pȝ性能<br /> <br /> 在第一ơ徏立与数据库的q接Ӟ在缺省情况下Q连接是在自动提交模式下的。ؓ(f)?jin)获得更好的性能Q可以通过调用带布?yu)(dng)值false参数的ConnectioncȝsetAutoCommit()Ҏ(gu)关闭自动提交功能Q如下所C:(x)<br /> <br /> conn.setAutoCommit(false);<br /> <br /> 值得注意的是Q一旦关闭了(jin)自动提交功能Q我们就需要通过调用Connectioncȝcommit()和rollback()Ҏ(gu)来h工的方式对事务进行管理?br /> <br /> 3、在动态SQL或有旉限制的命令中使用Statement对象<br /> <br /> 在执行SQL命o(h)Ӟ我们有二U选择Q可以用PreparedStatement对象Q也可以使用Statement对象。无论多次C用同一?SQL命o(h)QPreparedStatement都只对它解析和编译一ơ。当使用Statement对象Ӟ每次执行一个SQL命o(h)Ӟ都会(x)对它q行解析 和编译。这可能?x)你认为,使用PreparedStatement对象比用Statement对象的速度更快。然而,我进行的试表明Q在客户端Y?中,情况q如此。因此,在有旉限制的SQL操作中,除非成批地处理SQL命o(h)Q我们应当考虑使用Statement对象?br /> <br /> 此外Q用Statement对象也得编写动态SQL命o(h)更加单,因ؓ(f)我们可以字W串q接在一P建立一个有效的SQL命o(h)。因此,我认为,Statement对象可以使动态SQL命o(h)的创建和执行变得更加单?br /> <br /> 4、利用helper函数对动态SQL命o(h)q行格式?br /> <br /> 在创Z用Statement对象执行的动态SQL命o(h)Ӟ我们需要处理一些格式化斚w的问题。例如,如果我们惛_Z个将名字O'Reilly插入?中的SQL命o(h)Q则必须使用二个相连?#8220;''”h换O'Reilly中的“'”受完成这些工作的最好的Ҏ(gu)是创Z个完成替换操作的helper?法,然后在连接字W串?j)服用公式表达一个SQL命o(h)Ӟ使用创徏的helperҎ(gu)。与此类似的是,我们可以让helperҎ(gu)接受一个Date型的| 然后让它输出ZOracle的to_date()函数的字W串表达式?br /> <br /> 5、利用PreparedStatement对象提高数据库的M效率<br /> <br /> 在用PreparedStatement对象执行SQL命o(h)Ӟ命o(h)被数据库q行解析和编译,然后被放到命令缓冲区。然后,每当执行同一?PreparedStatement对象Ӟ它就?x)被再解析一ơ,但不?x)被再次~译。在~冲Z可以发现预编译的命o(h)Qƈ且可以重C用。在有大量用L(fng) 企业U应用Y件中Q经怼(x)重复执行相同的SQL命o(h)Q用PreparedStatement对象带来的编译次数的减少能够提高数据库的M性能。如果不 是在客户端创建、预备、执行PreparedStatementd需要的旉长于StatementdQ我?x)徏议在除动态SQL命o(h)之外的所有情况下 使用PreparedStatement对象?br /> <br /> 6、在成批处理重复的插入或更新操作中用PreparedStatement对象<br /> <br /> 如果成批地处理插入和更新操作Q就能够显著地减它们所需要的旉。Oracle提供的Statement?CallableStatementq不真正地支持批处理Q只有PreparedStatement对象才真正地支持批处理。我们可以?addBatch()和executeBatch()Ҏ(gu)选择标准的JDBC批处理,或者通过利用PreparedStatement对象?setExecuteBatch()Ҏ(gu)和标准的executeUpdate()Ҏ(gu)选择速度更快的Oracle专有的方法。要使用Oracle专有的批 处理机制Q可以以如下所C的方式调用setExecuteBatch()Q?br /> <br /> PreparedStatement pstmt3D null;<br /> try {<br /> ((OraclePreparedStatement)pstmt).setExecuteBatch(30);<br /> ...<br /> pstmt.executeUpdate();<br /> } <br /> 调用setExecuteBatch()时指定的值是一个上限,当达到该值时Q就?x)自动地引发SQL命o(h)执行Q标准的executeUpdate()?法就?x)被作?f)批处理送到数据库中。我们可以通过调用PreparedStatementcȝsendBatch()Ҏ(gu)随时传输批处理Q务?br /> <br /> 7、用Oracle locatorҎ(gu)插入、更新大对象QLOBQ?br /> <br /> Oracle的PreparedStatementcM完全支持BLOB和CLOB{大对象的处理,其是Thin驱动E序不支持利?PreparedStatement对象的setObject()和setBinaryStream()Ҏ(gu)讄BLOB的|也不支持利用 setCharacterStream()Ҏ(gu)讄CLOB的倹{只有locator本n中的Ҏ(gu)才能够从数据库中获取LOBcd的倹{可以?PreparedStatement对象插入或更新LOBQ但需要用locator才能获取LOB的倹{由于存在这二个问题Q因此,我徏议?locator的方法来插入、更新或获取LOB的倹{?br /> <br /> 8、用SQL92语法调用存储q程<br /> <br /> 在调用存储过E时Q我们可以用SQL92或Oracle PL/SQLQ由于用Oracle PL/SQLq没有什么实际的好处Q而且?x)给以后l护你的应用E序的开发h员带来麻?ch),因此Q我在调用存储过E时使用SQL92?br /> <br /> 9、用Object SQL对象模式{Ud数据库中<br /> <br /> 既然可以Oracle的数据库作ؓ(f)一U面向对象的数据库来使用Q就可以考虑应用程序中的面向对象模式{到数据库中。目前的Ҏ(gu)是创建Java bean作ؓ(f)伪装的数据库对象Q将它们的属性映到关系表中Q然后在q些bean中添加方法。尽这样作在Java中没有什么问题,但由于操作都是在数据 库之外进行的Q因此其他访问数据库的应用Y件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创徏一个新的数据库对象cd在数据库中模 仿其数据和操作,然后使用JPublisher{工L(fng)成自qJava beancR如果用这U方式,不但Java应用E序可以使用应用软g的对象模式,其他需要共享你的应用中的数据和操作的应用Y件也可以使用应用软g中的 对象模式?br /> <br /> 10、利用SQL完成数据库内的操?br /> <br /> 我要向大家介l的最重要的经验是充分利用SQL的面向集合的Ҏ(gu)来解x据库处理需求,而不是用Java{过E化的编E语a?br /> <br /> 如果~程人员要在一个表中查找许多行Q结果中的每个行都会(x)查找其他表中的数据,最后,~程人员创徏?jin)独立的UPDATE命o(h)来成批地更新W一个表中的?据。与此类似的d可以通过在set子句中用多列子查询而在一个UPDATE命o(h)中完成。当能够在单一的SQL命o(h)中完成Q务,何必要让数据在网上流?去的?我徏议用戯真学?fn)如何最大限度地发挥SQL的功能?<br /> <br /> <strong>JDBC基础教程之驱动设|?/strong> <br /> <font face="Tahoma">1、概q?br />    DriverManager cL JDBC 的管理层Q作用于用户和驱动程序之间。它跟踪可用的驱动程序,q在数据库和相应驱动E序之间建立q接。另外,DriverManager cM处理诸如驱动E序d旉限制?qing)登录和跟踪消息的显C等事务?br />   <br /> <br />   <br /> <br />   <br /> <br /> ?于简单的应用E序Q一般程序员需要在此类中直接用的唯一Ҏ(gu)?DriverManager.getConnection。正如名U所C,该方法将建立与数据库的连接。JDBC 允许用户调用 DriverManager 的方?getDriver、getDrivers ?registerDriver ?Driver 的方?connect。但多数情况下,?DriverManager cȝ理徏立连接的l节Z{?br />    1、跟t可用驱动程?br />    DriverManager cd含一?Driver c,它们已通过调用Ҏ(gu) DriverManager.registerDriver 对自p行了(jin)注册。所?Driver c都必须包含有一个静态部分。它创徏该类的实例,然后在加载该实例?DriverManager c进行注册。这P用户正常情况下将不会(x)直接调用 DriverManager.registerDriverQ而是在加载驱动程序时由驱动程序自动调用。加?Driver c,然后自动?DriverManager 中注册的方式有两U:(x)<br />    通过调用Ҏ(gu) Class.forName。这显式地加蝲驱动E序cR由于这与外部设|无养I因此推荐使用q种加蝲驱动E序的方法。以下代码加载类 acme.db.DriverQ?br /> class.forname("acme.db.driver"); <br /> <br />    如果?acme.db.Driver ~写为加载时创徏实例Qƈ调用以该实例为参数的 DriverManager.registerDriverQ本该如此)(j)Q则它在 DriverManager 的驱动程序列表中Qƈ可用于创接?br />    ?q将驱动E序d?java.lang.System 的属?jdbc.drivers 中。这是一个由 DriverManager cd载的驱动E序cd的列表,由冒号分隔:(x)初始?DriverManager cLQ它搜烦(ch)pȝ属?jdbc.driversQ如果用户已输入?jin)一个或多个驱动E序Q则 DriverManager cd试图加蝲它们。以下代码说明程序员如何?~/.hotjava/properties 中输入三个驱动程序类Q启动时QHotJava 把它加载到pȝ属性列表中Q:(x)<br />   <br /> <br />   <br /> <br /> jdbc.drivers=foo.bah.driver:wombat.sql.driver:bad.test.ourdriver; <br /> <br />    ?DriverManager Ҏ(gu)的第一ơ调用将自动加蝲q些驱动E序cR?br />    ?意:(x)加蝲驱动E序的第二种Ҏ(gu)需要持久的预设环境。如果对q一点不能保证,则调用方?Class.forName 昑ּ地加载每个驱动程序就昑־更ؓ(f)安全。这也是引入特定驱动E序的方法,因ؓ(f)一?DriverManager c被初始化,它将不再(g)?jdbc.drivers 属性列表?br />    在以上两U情况中Q新加蝲?Driver c都要通过调用 DriverManager.registerDriver c进行自我注册。如上所qͼ加蝲cL自动执行这一q程?br />    ׃安全斚w的原因,JDBC 理层将跟踪哪个cd载器提供哪个驱动E序。这P?DriverManager cL开q接Ӟ它仅使用本地文gpȝ或与发出q接h的代码相同的cd载器提供的驱动程序?br />    2、徏立连?br />    ??Driver cdƈ?DriverManager cM注册后,它们卛_用来与数据库建立q接。当调用 DriverManager.getConnection Ҏ(gu)发出q接hӞDriverManager 检查每个驱动程序,查看它是否可以徏立连接?br />    有时可能有多?JDBC 驱动E序可以与给定的 URL q接。例如,与给定远E数据库q接Ӟ可以使用 JDBC-ODBC 桥驱动程序、JDBC 到通用|络协议驱动E序或数据库厂商提供的驱动程序。在q种情况下,试驱动E序的顺序至关重要,因ؓ(f) DriverManager 用它所扑ֈ的第一个可以成功连接到l定 URL 的驱动程序?br />    首先 DriverManager 试图按注册的序使用每个驱动E序Qjdbc.drivers 中列出的驱动E序L先注册)(j)。它?yu)蟩q代码不可信ȝ驱动E序Q除非加载它们的源与试图打开q接的代码的源相同?br />    它通过轮流在每个驱动程序上调用Ҏ(gu) Driver.connectQƈ向它们传递用户开始传递给Ҏ(gu) DriverManager.getConnection ?URL 来对驱动E序q行试Q然后连接第一个认 URL 的驱动程序?br />    q种Ҏ(gu)初看h效率不高Q但׃不可能同时加载数十个驱动E序Q因此每ơ连接实际只需几个q程调用和字W串比较?br />    以下代码是通常情况下用驱动E序Q例?JDBC-ODBC 桥驱动程序)(j)建立q接所需所有步骤的CZQ?br />   <br /> <br />    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加蝲驱动E序 <br /> <br />    String url = "jdbc:dbc:fred";<br />    DriverManager.getConnection(url, "userID", "passwd");</font><br /> </div> <img src ="http://www.aygfsteel.com/lishen226/aggbug/269349.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/lishen226/" target="_blank">锋行</a> 2009-05-07 10:25 <a href="http://www.aygfsteel.com/lishen226/archive/2009/05/07/269349.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]dom4j实例http://www.aygfsteel.com/lishen226/archive/2009/05/06/269156.html锋行锋行Wed, 06 May 2009 01:30:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/05/06/269156.htmlhttp://www.aygfsteel.com/lishen226/comments/269156.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/05/06/269156.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/269156.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/269156.htmldom4j实例

http://haiyupeter.javaeye.com/blog/306572

关键? dom4j实例

 国外的dom4j已经很流行了(jin)Q国内的相关资料相对较少Q但普及(qing)风暴也即到来。我们公司(老外开的)(j)解析XML是用的dom4j?br />   今天公司没事做,自己也写一个小例子贴上来,嘻~~
 
books.xml:

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <books>  
  3.     <!--This is a test for dom4j, jakoes, 2007.7.19-->  
  4.     <book show="yes" url="lucene.net">  
  5.         <title id="456">Lucene Studing</title>  
  6.     </book>  
  7.     <book show="yes" url="dom4j.com">  
  8.         <title id="123">Dom4j Tutorials</title>  
  9.     </book>  
  10.     <book show="no" url="spring.org">  
  11.         <title id="789">Spring in Action</title>  
  12.     </book>  
  13.     <owner>O'Reilly</owner>  
  14. </books>  
 



下面我们使用dom4j的xPath来解析:(x)

segment of ParseXML.java:

Java代码 复制代码
  1. public void parseBooks(){   
  2.       
  3.     SAXReader reader = new SAXReader();   
  4.     try {   
  5.         Document doc = reader.read("books.xml");   
  6.         Node root = doc.selectSingleNode("/books");   
  7.         List list = root.selectNodes("book[@url='dom4j.com']");   
  8.           
  9.         for(Object o:list){   
  10.               
  11.             Element e = (Element) o;   
  12.             String show=e.attributeValue("show");   
  13.             System.out.println("show = " + show);   
  14.         }   
  15.          
  16.     } catch (Exception e) {   
  17.         e.printStackTrace();   
  18.     }   
  19. }  
 


  Document doc = reader.read("books.xml");的意思是加蝲XML文档Q此是可以用doc.asXML()来查看,它将打印整个xml文档?br />
  Node root = doc.selectSingleNode("/books");是读取刚才加载的xml文档内的books节点下的所有内容,对于本例也是整个xml文档?br />   当然我们也可以加?books下的某一个节点,如:(x)book节点
Node root = doc.selectSingleNode("/books/book");
或:(x)Node root = doc.selectSingleNode("/books/*");
注意Q如果有多个book节点Q它只会(x)dW一?br /> root.asXML()打华ͼ(x)
<book show="yes" url="lucene.net">
        <title id="456">Lucene Studing</title>
</book>

  既然加蝲?jin)这么多Q那我怎么_的得到我惌的节点呢Q别急,看下面:(x)
List list = root.selectNodes("book[@url='dom4j.com']");
它的意思就是读取books节点下的book节点Q且book的节点的url属性ؓ(f)dom4j.com
Z么用list来接收呢Q如果有两个book节点Q且它们的url属性都为dom4j.comQ此时就闭到l(f)ist里了(jin)?br />
  如果惌取books下的所有book节点Q可以这P(x)
List list = root.selectNodes("book");

  如果惌取books节点下的book节点下的title节点Q可以这P(x)
List list2 = root.selectNodes("book[@url='dom4j.com']/title[@id='123']");

  注意QselectNodes()参数的格式:(x)
  节点名[@属性名='属性?]Q如Qbook[@url='dom4j.com']
  如果有多个节点,?#8220;/”分开Q如Qbook[@url='dom4j.com']/title[@id='123']

  最q就是读取封闭在List里的内容?jin),可以用Node来读取,也可以用Element来{换?br /> attributeValue("属?)是读取该节点的属性?br /> getText()是读取节点的的内宏V?/p>



锋行 2009-05-06 09:30 发表评论
]]>
[转]js中innerHTML与innerText的用法与区别 http://www.aygfsteel.com/lishen226/archive/2009/04/02/263529.html锋行锋行Thu, 02 Apr 2009 06:00:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/04/02/263529.htmlhttp://www.aygfsteel.com/lishen226/comments/263529.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/04/02/263529.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/263529.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/263529.htmljs中innerHTML与innerText的用法与区别

用法Q?br />
<div id="test">
   <span style="color:red">test1</span> test2
</div>

在JS中可以用:(x)

test.innerHTML:

  也就是从对象的v始位|到l止位置的全部内?包括Html标签?

  上例中的test.innerHTML的g是“<span style="color:red">test1</span> test2 ”?br />
test.innerText: 

  从v始位|到l止位置的内? 但它去除Html标签 

  上例中的text.innerTest的g是“test1 test2”, 其中span标签去除?jin)?

test.outerHTML:

  除了(jin)包含innerHTML的全部内容外, q包含对象标{本w?/p>

  上例中的text.outerHTML的g是<div id="test"><span style="color:red">test1</span> test2</div>


完整CZQ?/strong>

<div id="test">
   <span style="color:red">test1</span> test2
</div>

<a href="javascript:alert(test.innerHTML)">innerHTML内容</a>
<a href="javascript:alert(test.innerText)">inerHTML内容</a>
<a href="javascript:alert(test.outerHTML)">outerHTML内容</a>

特别说明Q?/strong>

  innerHTML是符合W3C标准的属性,而innerText只适用于IE览器,因此Q尽可能地去使用innerHTMLQ而少用innerTextQ如果要输出不含HTML标签的内容,可以使用innerHTML取得包含HTML标签的内容后Q再用正则表辑ּ去除HTML标签Q下面是一个简单的W合W3C标准的示例:(x)

<a href="javascript:alert(document.getElementById('test').innerHTML.replace(/<.+?>/gim,''))">无HTML,W合W3C标准</a>

-------------------------------------------------------------------------------------------------------------------------------

<html>
<head></head>
<frameset frameborder="yes" frameborder="1" rows="40%,*">
<frame name="top" src="1.html">
<frame name="bottom" src="2.html">
</frameset>
</html>

<html>
<head>
<script language="javascript">
function init()
{   
    var aaa = parent.window.frames[0].document.body.innerHTML;
    alert(aaa);
}
</script>
</head>
<body>
<p align="center">nothing</p>
<p align="center"><input type="button" onclick="init()"; value="click"></p>
</body>
</html>

<html>
<center>汽R 房 女h</center>
</html>



锋行 2009-04-02 14:00 发表评论
]]>
dwr配置文gdwr.xml解http://www.aygfsteel.com/lishen226/archive/2009/03/16/259927.html锋行锋行Mon, 16 Mar 2009 01:13:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/03/16/259927.htmlhttp://www.aygfsteel.com/lishen226/comments/259927.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/03/16/259927.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/259927.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/259927.htmldwr配置文gdwr.xml解
2007-08-10 00:16

本h对dwr 中文文档关于dwr.xml做的一个整?Ua(b)体力z,有用得着的朋友别忘顶一下,留个联系方式一起交学?fn)?/p>

dwr.xml是DWR的配|文件。默认情况下Q应该把它放到WEB-INF目录(web.xml的目??/p>

创徏dwr.xml文g

dwr.xml文g的结构如?

<!DOCTYPE dwr PUBLIC    "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"    "http://www.getahead.ltd.uk/dwr/dwr10.dtd"><dwr>  <!-- init is only needed if you are extending DWR -->  <init>    <creator id="..." class="..."/>    <converter id="..." class="..."/>  </init>  <!-- without allow, DWR isn't allowed to do anything -->  <allow>    <create creator="..." javascript="..."/>    <convert converter="..." match="..."/>  </allow>  <!-- you may need to tell DWR about method signatures -->  <signatures>     ...  </signatures></dwr>

术语

q里是一些必ȝ解的术语 - 参数?x)?strong>convertedQ远EBean?x)?strong>created。所以如果你有一个叫A的beanQ它有一个方法叫A.blah(B) 那么你需要一个A?strong>creator和一个B?strong>converter?/p>

一Q?lt;allow>

allowD落里面定义的试DWR可以创徏和{换的cR?/p>

二:(x)Creators

dwr.xml文g中的create元素的结构如下:(x)

<allow>  <create creator="..." javascript="..." scope="...">    <param name="..." value="..."/>    <auth method="..." role="..."/>    <exclude method="..."/>    <include method="..."/>  </create>   ...</allow>

q里的多数元素都是可选的 - 你真正必ȝ道的是指定一个creator和一个javascript名字?/p>

creator属?/strong> 是必ȝ - 它用来指定用那U创造器?/p>

默认情况下DWR1.1?U创造器。它们是Q?/p>

  • new: 用Java的new关键字创造对象?
  • none: 它不创徏对象Q看下面的原因?(v1.1+)
  • scripted: 通过BSF使用脚本语言创徏对象Q例如BeanShell或Groovy?
  • spring: 通过Spring框架讉KBean?
  • jsf: 使用JSF的Bean?(v1.1+)
  • struts: 使用Struts的FormBean?(v1.1+)
  • pageflow: 讉KBeehive或Weblogic的PageFlow?(v1.1+)

 

如果你需要写自己的创造器Q你必须在init部分注册它?/p>

javascript属?/strong> 用于指定览器中q个被创造出来的对象的名字。你不能使用Javascript的关键字?/p>

scope属?/strong> 非常cMservlet规范中的scope?它允怽指定q个bean在什么生命范围。选项?application", "session", "request" ?page"。这些值对于Servlet和JSP开发者来说应该相当熟(zhn)了(jin)?/p>

scope属性是可选的。默认是"page"。如果要使用"session"需要cookies。当前的DWR不支持ULR重写?/p>

param元素 被用来指定创造器的其他参敎ͼ每种构造器各有不同。例如,"new"创造器需要知道要创徏的对象类型是什么。每一个创造器的参数在各自的文档中能找到。请查看上面的链接?/p>

include和exclude元素 允许创造器来限制类中方法的讉K。一个创造器必须指定include列表或exclude列表之一。如果是include列表则暗C默认的讉K{略?拒绝"Q如果是exclude列表则暗C默认的讉K{略?允许"?/p>

例如要拒l防范除?em>setWibble()以外的所有方法,你应该把如下内容d到dwr.xml中?/p>

<create creator="new" javascript="Fred">  <param name="class" value="com.example.Fred"/>  <include method="setWibble"/></create>

对于加入到create元素中的cȝ所有方法都是默认可见的?/p>

auth元素 允许你指定一个J2EE的角色作为将来的讉K控制(g)?

<create creator="new" javascript="Fred">  <param name="class" value="com.example.Fred"/>  <auth method="setWibble" role="admin"/></create>

 

new创造器在DWR中已l默认声明了(jin)Q?strong><creator id="new" class="uk.ltd.getahead.dwr.create.NewCreator"/> 。你不需要在dwr.xml文g中添加这D话Q它已经存在于DWR的内部dwr.xml文g中了(jin)?/p>

q个创造器通过c默认的够早函数创造对象实例。用new创造器有一些好处:(x)

  • 安全:DWR创造的对象生存的事件越短,多次调用中间的g一致的错误Z(x)少?
  • 内存消耗低Q?如果你的站点用户量非常大Q这个创造器可以减少VM的内存溢出?

你可以通过下面的方式用new创造器来创造远E调用BeanQ?/p>

<allow>  <create creator="new" javascript="Blah">    <param name="class" value="java.util.Date"/>  </create>   ... </allow>

q些代码?java.util.Date 映射成JavascriptQƈ且命名ؓ(f)BlahQ所以在Javascript中当你调用Blah.toString(reply) 那么一个新?java.util.Date ׃(x)通过默认的构造函数创造出来, 然后 toString() Ҏ(gu)被调用, 然后l果数据q回lreplyҎ(gu)(在这个例子中date是字W串格式)?/p>

 


 

none'创造器不创ZQ何对?- 它会(x)假设你不需要创建对象。这有可能是对的Q有两个原因?/p>

你可能在使用的scope不是"page"(看上?Qƈ在在前面已经把这个对象创建到q个scope中了(jin)Q这时你׃需要再创徏对象?jin)?/p>

q有一U情冉|要调用的Ҏ(gu)是静态的Q这时也不需要创建对象。DWR?x)在调用创徏器之前先(g)查一下这个方法是不是静态的?/p>

对于上诉两种情况Q你仍然需要class参数Q用来告诉DWR它是在操作的对象cd是什么?/p>

 


 

scripted创造器在DWR中已l默认声明了(jin)Q?lt;creator id="script" class="uk.ltd.getahead.dwr.create.ScriptedCreator"/>

q个创造器用BSF来执行脚本得到BeanQ例如:(x)

<allow>   ...  <create creator="script" javascript="EmailValidator">    <param name="language" value="beanshell"/>    <param name="script">       import org.apache.commons.validator.EmailValidator;       return EmailValidator.getInstance();    </param>  </create>   ...</allow>

script创造器有如下参敎ͼ(x)

参数 DWR版本 描述
language 1.0 脚本语言Q字W串Q例?beanshell'. (必需)
script 1.0 要执行的脚本?(必需Q除非scriptPath参数存在)
scriptPath 1.1 脚本文g路径?(必需Q除非script参数存在)
reloadable 1.1 是否(g)脚本文件的改动Q以重新加蝲 (可? 默认true)
class 1.0 创造出对象的类?可?. 如果没有DWR通过创造器得到cd?/td>

需要了(jin)解的主题

要用这个创造器Q你需要把一些辅助库攑ֈWEB-INF/lib文g夹下Q?span class="nobr">BSF的jar?sup>Q你要用?span class="nobr">脚本语言的jar?sup>?/p>

当一个类是用script创造出来的Qƈ且scope是session或applicationQ如果你的脚本改变,session中的cdscript中的cd不一致了(jin)。这样会(x)出现错误。虽然web容器不用重启Q但是用户需要先d(或以某种方式清空session)Q然后再d?/p>

当clazz参数不ؓ(f)I,q且用来创造新实例QDWR单的调用 class.newInstance() Ҏ(gu)。这U方法是没问题的Q除非脚本正在用某个参数创徏一个类Q或者调用某个函数来配置q个cR?不幸的是Q每ơ请求都要重新运行scriptq成上面的问题?/p>



锋行 2009-03-16 09:13 发表评论
]]>
dwr.xml中的{֐(Signatures) DWR中文文档http://www.aygfsteel.com/lishen226/archive/2009/03/16/259920.html锋行锋行Mon, 16 Mar 2009 00:52:00 GMThttp://www.aygfsteel.com/lishen226/archive/2009/03/16/259920.htmlhttp://www.aygfsteel.com/lishen226/comments/259920.htmlhttp://www.aygfsteel.com/lishen226/archive/2009/03/16/259920.html#Feedback0http://www.aygfsteel.com/lishen226/comments/commentRss/259920.htmlhttp://www.aygfsteel.com/lishen226/services/trackbacks/259920.html【{】dwr.xml中的{֐(Signatures) DWR中文文档 from http://wiki.javascud.org
2007-12-28 14:10

dwr.xml中的{֐(Signatures)

signaturesDDWR能确定集合中存放的数据类型。例如下面的定义中我们无法知道list中存攄是什么类型?/p>

public class Check
            {
            public void setLotteryResults(List nos)
            {
            ...
            }
            }

signaturesD允许我们暗CDWR应该用什么类型去处理。格式对以了(jin)解JDK5的泛型的人来说很Ҏ(gu)理解?/p>

<signatures>
            <![CDATA[
            import java.util.List;
            import com.example.Check;
            Check.setLotteryResults(List<Integer> nos);
            ]]>
            </signatures>

DWR中又一个解析器专门来做qg事,所以即便你的环境时JDK1.3 DWR也能正常工作?/p>

解析规则基本上会(x)和你预想规则的一?有两个例?Q所以java.lang下面的类型会(x)被默认import?/p>

W一个是DWR1.0中解析器的bugQ某些环境下不能q回正确cd。所以你也不用管它了(jin)?/p>

W二个是q个解析器时"阛_(sunny day)"解析器。就是说它非常宽松,不想~译器那样严格的保证你一定正。所以有时它也会(x)允许你丢失importQ?/p>

<signatures>
            <![CDATA[
            import java.util.List;
            Check.setLotteryResults(List<Integer>);
            ]]>
            </signatures>

来的DWR版本?x)用一个更正式的解析器Q这个编译器?x)基于官方Java定义Q所以你最好不要用太多这个不严格的东ѝ?/p>

signaturesD只是用来确定泛型参C的类型参数。DWR?x)自׃用反机制或者运行时cd定cdQ或者假讑֮是一个Stringcd。所以:(x)

不需要signatures - 没有泛型参数Q?/p>

public void method(String p);
            public void method(String[] p);

需要signatures - DWR不能通过反射定Q?/p>

public void method(List<Date> p);
            public void method(Map<String, WibbleBean> p);

不需要signatures - DWR能正的猜出:

public void method(List<String> p);
            public void method(Map<String, String> p);

不需要signatures - DWR可以通过q行时类型确定:(x)

public List<Date> method(String p);

没有必要让Javascript中的所有对象的key都是Stringcd - 你可以用其他类型作为key。但是他们在使用之前?x)被转换成Stringcd。DWR1.x用Javascript的特性把key转换成String。DWR2.0可能?x)用toString()Ҏ(gu)Q在服务D进行这一转换?/p>



锋行 2009-03-16 08:52 发表评论
]]>
վ֩ģ壺 İ| | | | ɳƺ| | | | | ƺ| ƽ| ٹ| ˳ƽ| | | | | | | | | | | ɽ| | ǭ| ԫ| ij| | | | ϳ| ̶| ɽ| ̩| | | | | ³| |